file_manager: Fix a bug where hosted documents could not be opened without active...
[chromium-blink-merge.git] / net / spdy / spdy_network_transaction_unittest.cc
blobf3f9f34499587f9bfb8464d28261f20454bfe544
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <string>
6 #include <vector>
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
10 #include "base/file_util.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/run_loop.h"
14 #include "base/stl_util.h"
15 #include "net/base/auth.h"
16 #include "net/base/net_log_unittest.h"
17 #include "net/base/request_priority.h"
18 #include "net/base/upload_bytes_element_reader.h"
19 #include "net/base/upload_data_stream.h"
20 #include "net/base/upload_file_element_reader.h"
21 #include "net/http/http_network_session_peer.h"
22 #include "net/http/http_network_transaction.h"
23 #include "net/http/http_server_properties.h"
24 #include "net/http/http_transaction_unittest.h"
25 #include "net/socket/client_socket_pool_base.h"
26 #include "net/socket/next_proto.h"
27 #include "net/spdy/buffered_spdy_framer.h"
28 #include "net/spdy/spdy_http_stream.h"
29 #include "net/spdy/spdy_http_utils.h"
30 #include "net/spdy/spdy_session.h"
31 #include "net/spdy/spdy_session_pool.h"
32 #include "net/spdy/spdy_test_util_common.h"
33 #include "net/spdy/spdy_test_utils.h"
34 #include "net/url_request/url_request_test_util.h"
35 #include "testing/platform_test.h"
37 //-----------------------------------------------------------------------------
39 namespace net {
41 namespace {
42 const char kRequestUrl[] = "http://www.google.com/";
44 enum SpdyNetworkTransactionTestSSLType {
45 SPDYNPN,
46 SPDYNOSSL,
47 SPDYSSL,
50 struct SpdyNetworkTransactionTestParams {
51 SpdyNetworkTransactionTestParams()
52 : protocol(kProtoSPDY2),
53 ssl_type(SPDYNPN) {}
55 SpdyNetworkTransactionTestParams(
56 NextProto protocol,
57 SpdyNetworkTransactionTestSSLType ssl_type)
58 : protocol(protocol),
59 ssl_type(ssl_type) {}
61 NextProto protocol;
62 SpdyNetworkTransactionTestSSLType ssl_type;
65 SpdySessionDependencies* CreateSpdySessionDependencies(
66 SpdyNetworkTransactionTestParams test_params) {
67 return new SpdySessionDependencies(test_params.protocol);
70 SpdySessionDependencies* CreateSpdySessionDependencies(
71 SpdyNetworkTransactionTestParams test_params,
72 ProxyService* proxy_service) {
73 return new SpdySessionDependencies(test_params.protocol, proxy_service);
76 } // namespace
78 class SpdyNetworkTransactionTest
79 : public ::testing::TestWithParam<SpdyNetworkTransactionTestParams> {
80 protected:
81 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol) {
84 virtual ~SpdyNetworkTransactionTest() {
85 // UploadDataStream posts deletion tasks back to the message loop on
86 // destruction.
87 upload_data_stream_.reset();
88 base::RunLoop().RunUntilIdle();
91 virtual void SetUp() {
92 google_get_request_initialized_ = false;
93 google_post_request_initialized_ = false;
94 google_chunked_post_request_initialized_ = false;
95 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
98 struct TransactionHelperResult {
99 int rv;
100 std::string status_line;
101 std::string response_data;
102 HttpResponseInfo response_info;
105 // A helper class that handles all the initial npn/ssl setup.
106 class NormalSpdyTransactionHelper {
107 public:
108 NormalSpdyTransactionHelper(const HttpRequestInfo& request,
109 RequestPriority priority,
110 const BoundNetLog& log,
111 SpdyNetworkTransactionTestParams test_params,
112 SpdySessionDependencies* session_deps)
113 : request_(request),
114 priority_(priority),
115 session_deps_(session_deps == NULL ?
116 CreateSpdySessionDependencies(test_params) :
117 session_deps),
118 session_(SpdySessionDependencies::SpdyCreateSession(
119 session_deps_.get())),
120 log_(log),
121 test_params_(test_params),
122 deterministic_(false),
123 spdy_enabled_(true) {
124 switch (test_params_.ssl_type) {
125 case SPDYNOSSL:
126 case SPDYSSL:
127 port_ = 80;
128 break;
129 case SPDYNPN:
130 port_ = 443;
131 break;
132 default:
133 NOTREACHED();
137 ~NormalSpdyTransactionHelper() {
138 // Any test which doesn't close the socket by sending it an EOF will
139 // have a valid session left open, which leaks the entire session pool.
140 // This is just fine - in fact, some of our tests intentionally do this
141 // so that we can check consistency of the SpdySessionPool as the test
142 // finishes. If we had put an EOF on the socket, the SpdySession would
143 // have closed and we wouldn't be able to check the consistency.
145 // Forcefully close existing sessions here.
146 session()->spdy_session_pool()->CloseAllSessions();
149 void SetDeterministic() {
150 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
151 session_deps_.get());
152 deterministic_ = true;
155 void SetSpdyDisabled() {
156 spdy_enabled_ = false;
157 port_ = 80;
160 void RunPreTestSetup() {
161 if (!session_deps_.get())
162 session_deps_.reset(CreateSpdySessionDependencies(test_params_));
163 if (!session_.get())
164 session_ = SpdySessionDependencies::SpdyCreateSession(
165 session_deps_.get());
166 HttpStreamFactory::set_use_alternate_protocols(false);
167 HttpStreamFactory::set_force_spdy_over_ssl(false);
168 HttpStreamFactory::set_force_spdy_always(false);
170 std::vector<NextProto> next_protos = SpdyNextProtos();
172 switch (test_params_.ssl_type) {
173 case SPDYNPN:
174 session_->http_server_properties()->SetAlternateProtocol(
175 HostPortPair("www.google.com", 80), 443,
176 AlternateProtocolFromNextProto(test_params_.protocol));
177 HttpStreamFactory::set_use_alternate_protocols(true);
178 HttpStreamFactory::SetNextProtos(next_protos);
179 break;
180 case SPDYNOSSL:
181 HttpStreamFactory::set_force_spdy_over_ssl(false);
182 HttpStreamFactory::set_force_spdy_always(true);
183 break;
184 case SPDYSSL:
185 HttpStreamFactory::set_force_spdy_over_ssl(true);
186 HttpStreamFactory::set_force_spdy_always(true);
187 break;
188 default:
189 NOTREACHED();
192 // We're now ready to use SSL-npn SPDY.
193 trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
196 // Start the transaction, read some data, finish.
197 void RunDefaultTest() {
198 if (!StartDefaultTest())
199 return;
200 FinishDefaultTest();
203 bool StartDefaultTest() {
204 output_.rv = trans_->Start(&request_, callback.callback(), log_);
206 // We expect an IO Pending or some sort of error.
207 EXPECT_LT(output_.rv, 0);
208 return output_.rv == ERR_IO_PENDING;
211 void FinishDefaultTest() {
212 output_.rv = callback.WaitForResult();
213 if (output_.rv != OK) {
214 session_->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED);
215 return;
218 // Verify responses.
219 const HttpResponseInfo* response = trans_->GetResponseInfo();
220 ASSERT_TRUE(response != NULL);
221 ASSERT_TRUE(response->headers.get() != NULL);
222 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
223 EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
224 if (HttpStreamFactory::spdy_enabled()) {
225 EXPECT_EQ(
226 HttpResponseInfo::ConnectionInfoFromNextProto(
227 test_params_.protocol),
228 response->connection_info);
229 } else {
230 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
231 response->connection_info);
233 if (test_params_.ssl_type == SPDYNPN && spdy_enabled_) {
234 EXPECT_TRUE(response->was_npn_negotiated);
235 } else {
236 EXPECT_TRUE(!response->was_npn_negotiated);
238 // If SPDY is not enabled, a HTTP request should not be diverted
239 // over a SSL session.
240 if (!spdy_enabled_) {
241 EXPECT_EQ(request_.url.SchemeIs("https"),
242 response->was_npn_negotiated);
244 EXPECT_EQ("127.0.0.1", response->socket_address.host());
245 EXPECT_EQ(port_, response->socket_address.port());
246 output_.status_line = response->headers->GetStatusLine();
247 output_.response_info = *response; // Make a copy so we can verify.
248 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
251 // Most tests will want to call this function. In particular, the MockReads
252 // should end with an empty read, and that read needs to be processed to
253 // ensure proper deletion of the spdy_session_pool.
254 void VerifyDataConsumed() {
255 for (DataVector::iterator it = data_vector_.begin();
256 it != data_vector_.end(); ++it) {
257 EXPECT_TRUE((*it)->at_read_eof()) << "Read count: "
258 << (*it)->read_count()
259 << " Read index: "
260 << (*it)->read_index();
261 EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
262 << (*it)->write_count()
263 << " Write index: "
264 << (*it)->write_index();
268 // Occasionally a test will expect to error out before certain reads are
269 // processed. In that case we want to explicitly ensure that the reads were
270 // not processed.
271 void VerifyDataNotConsumed() {
272 for (DataVector::iterator it = data_vector_.begin();
273 it != data_vector_.end(); ++it) {
274 EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: "
275 << (*it)->read_count()
276 << " Read index: "
277 << (*it)->read_index();
278 EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
279 << (*it)->write_count()
280 << " Write index: "
281 << (*it)->write_index();
285 void RunToCompletion(StaticSocketDataProvider* data) {
286 RunPreTestSetup();
287 AddData(data);
288 RunDefaultTest();
289 VerifyDataConsumed();
292 void AddData(StaticSocketDataProvider* data) {
293 DCHECK(!deterministic_);
294 data_vector_.push_back(data);
295 SSLSocketDataProvider* ssl_provider =
296 new SSLSocketDataProvider(ASYNC, OK);
297 if (test_params_.ssl_type == SPDYNPN)
298 ssl_provider->SetNextProto(test_params_.protocol);
300 ssl_vector_.push_back(ssl_provider);
301 if (test_params_.ssl_type == SPDYNPN || test_params_.ssl_type == SPDYSSL)
302 session_deps_->socket_factory->AddSSLSocketDataProvider(ssl_provider);
304 session_deps_->socket_factory->AddSocketDataProvider(data);
305 if (test_params_.ssl_type == SPDYNPN) {
306 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
307 StaticSocketDataProvider* hanging_non_alternate_protocol_socket =
308 new StaticSocketDataProvider(NULL, 0, NULL, 0);
309 hanging_non_alternate_protocol_socket->set_connect_data(
310 never_finishing_connect);
311 session_deps_->socket_factory->AddSocketDataProvider(
312 hanging_non_alternate_protocol_socket);
313 alternate_vector_.push_back(hanging_non_alternate_protocol_socket);
317 void AddDeterministicData(DeterministicSocketData* data) {
318 DCHECK(deterministic_);
319 data_vector_.push_back(data);
320 SSLSocketDataProvider* ssl_provider =
321 new SSLSocketDataProvider(ASYNC, OK);
322 if (test_params_.ssl_type == SPDYNPN)
323 ssl_provider->SetNextProto(test_params_.protocol);
325 ssl_vector_.push_back(ssl_provider);
326 if (test_params_.ssl_type == SPDYNPN ||
327 test_params_.ssl_type == SPDYSSL) {
328 session_deps_->deterministic_socket_factory->
329 AddSSLSocketDataProvider(ssl_provider);
331 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
332 if (test_params_.ssl_type == SPDYNPN) {
333 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
334 DeterministicSocketData* hanging_non_alternate_protocol_socket =
335 new DeterministicSocketData(NULL, 0, NULL, 0);
336 hanging_non_alternate_protocol_socket->set_connect_data(
337 never_finishing_connect);
338 session_deps_->deterministic_socket_factory->AddSocketDataProvider(
339 hanging_non_alternate_protocol_socket);
340 alternate_deterministic_vector_.push_back(
341 hanging_non_alternate_protocol_socket);
345 void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
346 session_ = session;
348 HttpNetworkTransaction* trans() { return trans_.get(); }
349 void ResetTrans() { trans_.reset(); }
350 TransactionHelperResult& output() { return output_; }
351 const HttpRequestInfo& request() const { return request_; }
352 const scoped_refptr<HttpNetworkSession>& session() const {
353 return session_;
355 scoped_ptr<SpdySessionDependencies>& session_deps() {
356 return session_deps_;
358 int port() const { return port_; }
359 SpdyNetworkTransactionTestParams test_params() const {
360 return test_params_;
363 private:
364 typedef std::vector<StaticSocketDataProvider*> DataVector;
365 typedef ScopedVector<SSLSocketDataProvider> SSLVector;
366 typedef ScopedVector<StaticSocketDataProvider> AlternateVector;
367 typedef ScopedVector<DeterministicSocketData> AlternateDeterministicVector;
368 HttpRequestInfo request_;
369 RequestPriority priority_;
370 scoped_ptr<SpdySessionDependencies> session_deps_;
371 scoped_refptr<HttpNetworkSession> session_;
372 TransactionHelperResult output_;
373 scoped_ptr<StaticSocketDataProvider> first_transaction_;
374 SSLVector ssl_vector_;
375 TestCompletionCallback callback;
376 scoped_ptr<HttpNetworkTransaction> trans_;
377 scoped_ptr<HttpNetworkTransaction> trans_http_;
378 DataVector data_vector_;
379 AlternateVector alternate_vector_;
380 AlternateDeterministicVector alternate_deterministic_vector_;
381 const BoundNetLog& log_;
382 SpdyNetworkTransactionTestParams test_params_;
383 int port_;
384 bool deterministic_;
385 bool spdy_enabled_;
388 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
389 int expected_status);
391 void ConnectStatusHelper(const MockRead& status);
393 const HttpRequestInfo& CreateGetPushRequest() {
394 google_get_push_request_.method = "GET";
395 google_get_push_request_.url = GURL("http://www.google.com/foo.dat");
396 google_get_push_request_.load_flags = 0;
397 return google_get_push_request_;
400 const HttpRequestInfo& CreateGetRequest() {
401 if (!google_get_request_initialized_) {
402 google_get_request_.method = "GET";
403 google_get_request_.url = GURL(kDefaultURL);
404 google_get_request_.load_flags = 0;
405 google_get_request_initialized_ = true;
407 return google_get_request_;
410 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
411 if (!google_get_request_initialized_) {
412 google_get_request_.method = "GET";
413 google_get_request_.url = GURL(kDefaultURL);
414 google_get_request_.load_flags = 0;
415 google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
416 google_get_request_initialized_ = true;
418 return google_get_request_;
421 const HttpRequestInfo& CreatePostRequest() {
422 if (!google_post_request_initialized_) {
423 ScopedVector<UploadElementReader> element_readers;
424 element_readers.push_back(
425 new UploadBytesElementReader(kUploadData, kUploadDataSize));
426 upload_data_stream_.reset(new UploadDataStream(&element_readers, 0));
428 google_post_request_.method = "POST";
429 google_post_request_.url = GURL(kDefaultURL);
430 google_post_request_.upload_data_stream = upload_data_stream_.get();
431 google_post_request_initialized_ = true;
433 return google_post_request_;
436 const HttpRequestInfo& CreateFilePostRequest() {
437 if (!google_post_request_initialized_) {
438 base::FilePath file_path;
439 CHECK(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
440 CHECK_EQ(static_cast<int>(kUploadDataSize),
441 file_util::WriteFile(file_path, kUploadData, kUploadDataSize));
443 ScopedVector<UploadElementReader> element_readers;
444 element_readers.push_back(
445 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
446 file_path,
448 kUploadDataSize,
449 base::Time()));
450 upload_data_stream_.reset(new UploadDataStream(&element_readers, 0));
452 google_post_request_.method = "POST";
453 google_post_request_.url = GURL(kDefaultURL);
454 google_post_request_.upload_data_stream = upload_data_stream_.get();
455 google_post_request_initialized_ = true;
457 return google_post_request_;
460 const HttpRequestInfo& CreateComplexPostRequest() {
461 if (!google_post_request_initialized_) {
462 const int kFileRangeOffset = 1;
463 const int kFileRangeLength = 3;
464 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
466 base::FilePath file_path;
467 CHECK(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
468 CHECK_EQ(static_cast<int>(kUploadDataSize),
469 file_util::WriteFile(file_path, kUploadData, kUploadDataSize));
471 ScopedVector<UploadElementReader> element_readers;
472 element_readers.push_back(
473 new UploadBytesElementReader(kUploadData, kFileRangeOffset));
474 element_readers.push_back(
475 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
476 file_path,
477 kFileRangeOffset,
478 kFileRangeLength,
479 base::Time()));
480 element_readers.push_back(new UploadBytesElementReader(
481 kUploadData + kFileRangeOffset + kFileRangeLength,
482 kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
483 upload_data_stream_.reset(new UploadDataStream(&element_readers, 0));
485 google_post_request_.method = "POST";
486 google_post_request_.url = GURL(kDefaultURL);
487 google_post_request_.upload_data_stream = upload_data_stream_.get();
488 google_post_request_initialized_ = true;
490 return google_post_request_;
493 const HttpRequestInfo& CreateChunkedPostRequest() {
494 if (!google_chunked_post_request_initialized_) {
495 upload_data_stream_.reset(
496 new UploadDataStream(UploadDataStream::CHUNKED, 0));
497 google_chunked_post_request_.method = "POST";
498 google_chunked_post_request_.url = GURL(kDefaultURL);
499 google_chunked_post_request_.upload_data_stream =
500 upload_data_stream_.get();
501 google_chunked_post_request_initialized_ = true;
503 return google_chunked_post_request_;
506 // Read the result of a particular transaction, knowing that we've got
507 // multiple transactions in the read pipeline; so as we read, we may have
508 // to skip over data destined for other transactions while we consume
509 // the data for |trans|.
510 int ReadResult(HttpNetworkTransaction* trans,
511 StaticSocketDataProvider* data,
512 std::string* result) {
513 const int kSize = 3000;
515 int bytes_read = 0;
516 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
517 TestCompletionCallback callback;
518 while (true) {
519 int rv = trans->Read(buf.get(), kSize, callback.callback());
520 if (rv == ERR_IO_PENDING) {
521 // Multiple transactions may be in the data set. Keep pulling off
522 // reads until we complete our callback.
523 while (!callback.have_result()) {
524 data->CompleteRead();
525 base::RunLoop().RunUntilIdle();
527 rv = callback.WaitForResult();
528 } else if (rv <= 0) {
529 break;
531 result->append(buf->data(), rv);
532 bytes_read += rv;
534 return bytes_read;
537 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
538 // This lengthy block is reaching into the pool to dig out the active
539 // session. Once we have the session, we verify that the streams are
540 // all closed and not leaked at this point.
541 const GURL& url = helper.request().url;
542 int port = helper.test_params().ssl_type == SPDYNPN ? 443 : 80;
543 HostPortPair host_port_pair(url.host(), port);
544 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
545 kPrivacyModeDisabled);
546 BoundNetLog log;
547 const scoped_refptr<HttpNetworkSession>& session = helper.session();
548 base::WeakPtr<SpdySession> spdy_session =
549 session->spdy_session_pool()->FindAvailableSession(key, log);
550 ASSERT_TRUE(spdy_session != NULL);
551 EXPECT_EQ(0u, spdy_session->num_active_streams());
552 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
555 void RunServerPushTest(OrderedSocketData* data,
556 HttpResponseInfo* response,
557 HttpResponseInfo* push_response,
558 const std::string& expected) {
559 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
560 BoundNetLog(), GetParam(), NULL);
561 helper.RunPreTestSetup();
562 helper.AddData(data);
564 HttpNetworkTransaction* trans = helper.trans();
566 // Start the transaction with basic parameters.
567 TestCompletionCallback callback;
568 int rv = trans->Start(
569 &CreateGetRequest(), callback.callback(), BoundNetLog());
570 EXPECT_EQ(ERR_IO_PENDING, rv);
571 rv = callback.WaitForResult();
573 // Request the pushed path.
574 scoped_ptr<HttpNetworkTransaction> trans2(
575 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
576 rv = trans2->Start(
577 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
578 EXPECT_EQ(ERR_IO_PENDING, rv);
579 base::RunLoop().RunUntilIdle();
581 // The data for the pushed path may be coming in more than 1 frame. Compile
582 // the results into a single string.
584 // Read the server push body.
585 std::string result2;
586 ReadResult(trans2.get(), data, &result2);
587 // Read the response body.
588 std::string result;
589 ReadResult(trans, data, &result);
591 // Verify that we consumed all test data.
592 EXPECT_TRUE(data->at_read_eof());
593 EXPECT_TRUE(data->at_write_eof());
595 // Verify that the received push data is same as the expected push data.
596 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
597 << result2
598 << "||||| Expected data: "
599 << expected;
601 // Verify the SYN_REPLY.
602 // Copy the response info, because trans goes away.
603 *response = *trans->GetResponseInfo();
604 *push_response = *trans2->GetResponseInfo();
606 VerifyStreamsClosed(helper);
609 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
610 int result) {
611 helper->ResetTrans();
614 static void StartTransactionCallback(
615 const scoped_refptr<HttpNetworkSession>& session,
616 int result) {
617 scoped_ptr<HttpNetworkTransaction> trans(
618 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
619 TestCompletionCallback callback;
620 HttpRequestInfo request;
621 request.method = "GET";
622 request.url = GURL("http://www.google.com/");
623 request.load_flags = 0;
624 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
625 EXPECT_EQ(ERR_IO_PENDING, rv);
626 callback.WaitForResult();
629 SpdyTestUtil spdy_util_;
631 private:
632 scoped_ptr<UploadDataStream> upload_data_stream_;
633 bool google_get_request_initialized_;
634 bool google_post_request_initialized_;
635 bool google_chunked_post_request_initialized_;
636 HttpRequestInfo google_get_request_;
637 HttpRequestInfo google_post_request_;
638 HttpRequestInfo google_chunked_post_request_;
639 HttpRequestInfo google_get_push_request_;
640 base::ScopedTempDir temp_dir_;
643 //-----------------------------------------------------------------------------
644 // All tests are run with three different connection types: SPDY after NPN
645 // negotiation, SPDY without SSL, and SPDY with SSL.
647 // TODO(akalin): Use ::testing::Combine() when we are able to use
648 // <tr1/tuple>.
649 INSTANTIATE_TEST_CASE_P(
650 Spdy,
651 SpdyNetworkTransactionTest,
652 ::testing::Values(
653 SpdyNetworkTransactionTestParams(kProtoSPDY2, SPDYNOSSL),
654 SpdyNetworkTransactionTestParams(kProtoSPDY2, SPDYSSL),
655 SpdyNetworkTransactionTestParams(kProtoSPDY2, SPDYNPN),
656 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNOSSL),
657 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYSSL),
658 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNPN),
659 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNOSSL),
660 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYSSL),
661 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN),
662 SpdyNetworkTransactionTestParams(kProtoSPDY4a2, SPDYNOSSL),
663 SpdyNetworkTransactionTestParams(kProtoSPDY4a2, SPDYSSL),
664 SpdyNetworkTransactionTestParams(kProtoSPDY4a2, SPDYNPN),
665 SpdyNetworkTransactionTestParams(kProtoHTTP2Draft04, SPDYNOSSL),
666 SpdyNetworkTransactionTestParams(kProtoHTTP2Draft04, SPDYSSL),
667 SpdyNetworkTransactionTestParams(kProtoHTTP2Draft04, SPDYNPN)));
669 // Verify HttpNetworkTransaction constructor.
670 TEST_P(SpdyNetworkTransactionTest, Constructor) {
671 scoped_ptr<SpdySessionDependencies> session_deps(
672 CreateSpdySessionDependencies(GetParam()));
673 scoped_refptr<HttpNetworkSession> session(
674 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
675 scoped_ptr<HttpTransaction> trans(
676 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
679 TEST_P(SpdyNetworkTransactionTest, Get) {
680 // Construct the request.
681 scoped_ptr<SpdyFrame> req(
682 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
683 MockWrite writes[] = { CreateMockWrite(*req) };
685 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
686 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
687 MockRead reads[] = {
688 CreateMockRead(*resp),
689 CreateMockRead(*body),
690 MockRead(ASYNC, 0, 0) // EOF
693 DelayedSocketData data(1, reads, arraysize(reads),
694 writes, arraysize(writes));
695 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
696 BoundNetLog(), GetParam(), NULL);
697 helper.RunToCompletion(&data);
698 TransactionHelperResult out = helper.output();
699 EXPECT_EQ(OK, out.rv);
700 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
701 EXPECT_EQ("hello!", out.response_data);
704 TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
705 for (RequestPriority p = MINIMUM_PRIORITY; p < NUM_PRIORITIES;
706 p = RequestPriority(p + 1)) {
707 // Construct the request.
708 scoped_ptr<SpdyFrame> req(
709 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true));
710 MockWrite writes[] = { CreateMockWrite(*req) };
712 SpdyPriority spdy_prio = 0;
713 EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio));
714 // this repeats the RequestPriority-->SpdyPriority mapping from
715 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
716 // sure it's being done right.
717 if (spdy_util_.spdy_version() < SPDY3) {
718 switch(p) {
719 case HIGHEST:
720 EXPECT_EQ(0, spdy_prio);
721 break;
722 case MEDIUM:
723 EXPECT_EQ(1, spdy_prio);
724 break;
725 case LOW:
726 case LOWEST:
727 EXPECT_EQ(2, spdy_prio);
728 break;
729 case IDLE:
730 EXPECT_EQ(3, spdy_prio);
731 break;
732 default:
733 FAIL();
735 } else {
736 switch(p) {
737 case HIGHEST:
738 EXPECT_EQ(0, spdy_prio);
739 break;
740 case MEDIUM:
741 EXPECT_EQ(1, spdy_prio);
742 break;
743 case LOW:
744 EXPECT_EQ(2, spdy_prio);
745 break;
746 case LOWEST:
747 EXPECT_EQ(3, spdy_prio);
748 break;
749 case IDLE:
750 EXPECT_EQ(4, spdy_prio);
751 break;
752 default:
753 FAIL();
757 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
758 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
759 MockRead reads[] = {
760 CreateMockRead(*resp),
761 CreateMockRead(*body),
762 MockRead(ASYNC, 0, 0) // EOF
765 DelayedSocketData data(1, reads, arraysize(reads),
766 writes, arraysize(writes));
767 HttpRequestInfo http_req = CreateGetRequest();
769 NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(),
770 GetParam(), NULL);
771 helper.RunToCompletion(&data);
772 TransactionHelperResult out = helper.output();
773 EXPECT_EQ(OK, out.rv);
774 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
775 EXPECT_EQ("hello!", out.response_data);
779 // Start three gets simultaniously; making sure that multiplexed
780 // streams work properly.
782 // This can't use the TransactionHelper method, since it only
783 // handles a single transaction, and finishes them as soon
784 // as it launches them.
786 // TODO(gavinp): create a working generalized TransactionHelper that
787 // can allow multiple streams in flight.
789 TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
790 scoped_ptr<SpdyFrame> req(
791 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
792 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
793 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
794 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
796 scoped_ptr<SpdyFrame> req2(
797 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
798 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
799 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
800 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
802 scoped_ptr<SpdyFrame> req3(
803 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
804 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
805 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
806 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
808 MockWrite writes[] = {
809 CreateMockWrite(*req),
810 CreateMockWrite(*req2),
811 CreateMockWrite(*req3),
813 MockRead reads[] = {
814 CreateMockRead(*resp, 1),
815 CreateMockRead(*body),
816 CreateMockRead(*resp2, 4),
817 CreateMockRead(*body2),
818 CreateMockRead(*resp3, 7),
819 CreateMockRead(*body3),
821 CreateMockRead(*fbody),
822 CreateMockRead(*fbody2),
823 CreateMockRead(*fbody3),
825 MockRead(ASYNC, 0, 0), // EOF
827 OrderedSocketData data(reads, arraysize(reads),
828 writes, arraysize(writes));
829 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
831 BoundNetLog log;
832 TransactionHelperResult out;
833 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
834 BoundNetLog(), GetParam(), NULL);
835 helper.RunPreTestSetup();
836 helper.AddData(&data);
837 // We require placeholder data because three get requests are sent out, so
838 // there needs to be three sets of SSL connection data.
839 helper.AddData(&data_placeholder);
840 helper.AddData(&data_placeholder);
841 scoped_ptr<HttpNetworkTransaction> trans1(
842 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
843 scoped_ptr<HttpNetworkTransaction> trans2(
844 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
845 scoped_ptr<HttpNetworkTransaction> trans3(
846 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
848 TestCompletionCallback callback1;
849 TestCompletionCallback callback2;
850 TestCompletionCallback callback3;
852 HttpRequestInfo httpreq1 = CreateGetRequest();
853 HttpRequestInfo httpreq2 = CreateGetRequest();
854 HttpRequestInfo httpreq3 = CreateGetRequest();
856 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
857 ASSERT_EQ(ERR_IO_PENDING, out.rv);
858 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
859 ASSERT_EQ(ERR_IO_PENDING, out.rv);
860 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
861 ASSERT_EQ(ERR_IO_PENDING, out.rv);
863 out.rv = callback1.WaitForResult();
864 ASSERT_EQ(OK, out.rv);
865 out.rv = callback3.WaitForResult();
866 ASSERT_EQ(OK, out.rv);
868 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
869 EXPECT_TRUE(response1->headers.get() != NULL);
870 EXPECT_TRUE(response1->was_fetched_via_spdy);
871 out.status_line = response1->headers->GetStatusLine();
872 out.response_info = *response1;
874 trans2->GetResponseInfo();
876 out.rv = ReadTransaction(trans1.get(), &out.response_data);
877 helper.VerifyDataConsumed();
878 EXPECT_EQ(OK, out.rv);
880 EXPECT_EQ(OK, out.rv);
881 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
882 EXPECT_EQ("hello!hello!", out.response_data);
885 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
886 scoped_ptr<SpdyFrame> req(
887 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
888 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
889 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
890 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
892 scoped_ptr<SpdyFrame> req2(
893 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
894 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
895 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
896 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
898 MockWrite writes[] = {
899 CreateMockWrite(*req),
900 CreateMockWrite(*req2),
902 MockRead reads[] = {
903 CreateMockRead(*resp, 1),
904 CreateMockRead(*body),
905 CreateMockRead(*resp2, 4),
906 CreateMockRead(*body2),
907 CreateMockRead(*fbody),
908 CreateMockRead(*fbody2),
909 MockRead(ASYNC, 0, 0), // EOF
911 OrderedSocketData data(reads, arraysize(reads),
912 writes, arraysize(writes));
914 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
916 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
917 data_placeholder.set_connect_data(never_finishing_connect);
919 BoundNetLog log;
920 TransactionHelperResult out;
921 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
922 BoundNetLog(), GetParam(), NULL);
923 helper.RunPreTestSetup();
924 helper.AddData(&data);
925 // We require placeholder data because two get requests are sent out, so
926 // there needs to be two sets of SSL connection data.
927 helper.AddData(&data_placeholder);
928 scoped_ptr<HttpNetworkTransaction> trans1(
929 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
930 scoped_ptr<HttpNetworkTransaction> trans2(
931 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
933 TestCompletionCallback callback1;
934 TestCompletionCallback callback2;
936 HttpRequestInfo httpreq1 = CreateGetRequest();
937 HttpRequestInfo httpreq2 = CreateGetRequest();
939 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
940 ASSERT_EQ(ERR_IO_PENDING, out.rv);
941 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
942 ASSERT_EQ(ERR_IO_PENDING, out.rv);
944 out.rv = callback1.WaitForResult();
945 ASSERT_EQ(OK, out.rv);
946 out.rv = callback2.WaitForResult();
947 ASSERT_EQ(OK, out.rv);
949 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
950 EXPECT_TRUE(response1->headers.get() != NULL);
951 EXPECT_TRUE(response1->was_fetched_via_spdy);
952 out.status_line = response1->headers->GetStatusLine();
953 out.response_info = *response1;
954 out.rv = ReadTransaction(trans1.get(), &out.response_data);
955 EXPECT_EQ(OK, out.rv);
956 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
957 EXPECT_EQ("hello!hello!", out.response_data);
959 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
960 EXPECT_TRUE(response2->headers.get() != NULL);
961 EXPECT_TRUE(response2->was_fetched_via_spdy);
962 out.status_line = response2->headers->GetStatusLine();
963 out.response_info = *response2;
964 out.rv = ReadTransaction(trans2.get(), &out.response_data);
965 EXPECT_EQ(OK, out.rv);
966 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
967 EXPECT_EQ("hello!hello!", out.response_data);
969 helper.VerifyDataConsumed();
972 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
973 scoped_ptr<SpdyFrame> req(
974 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
975 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
976 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
977 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
979 scoped_ptr<SpdyFrame> req2(
980 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
981 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
982 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
983 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
985 MockWrite writes[] = {
986 CreateMockWrite(*req),
987 CreateMockWrite(*req2),
989 MockRead reads[] = {
990 CreateMockRead(*resp, 1),
991 CreateMockRead(*body),
992 CreateMockRead(*resp2, 4),
993 CreateMockRead(*body2),
994 CreateMockRead(*fbody),
995 CreateMockRead(*fbody2),
996 MockRead(ASYNC, 0, 0), // EOF
998 OrderedSocketData preconnect_data(reads, arraysize(reads),
999 writes, arraysize(writes));
1001 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
1003 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1004 data_placeholder.set_connect_data(never_finishing_connect);
1006 BoundNetLog log;
1007 TransactionHelperResult out;
1008 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1009 BoundNetLog(), GetParam(), NULL);
1010 helper.RunPreTestSetup();
1011 helper.AddData(&preconnect_data);
1012 // We require placeholder data because 3 connections are attempted (first is
1013 // the preconnect, 2nd and 3rd are the never finished connections.
1014 helper.AddData(&data_placeholder);
1015 helper.AddData(&data_placeholder);
1017 scoped_ptr<HttpNetworkTransaction> trans1(
1018 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1019 scoped_ptr<HttpNetworkTransaction> trans2(
1020 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1022 TestCompletionCallback callback1;
1023 TestCompletionCallback callback2;
1025 HttpRequestInfo httpreq = CreateGetRequest();
1027 // Preconnect the first.
1028 SSLConfig preconnect_ssl_config;
1029 helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
1030 HttpStreamFactory* http_stream_factory =
1031 helper.session()->http_stream_factory();
1032 if (http_stream_factory->has_next_protos()) {
1033 preconnect_ssl_config.next_protos = http_stream_factory->next_protos();
1036 http_stream_factory->PreconnectStreams(
1037 1, httpreq, DEFAULT_PRIORITY,
1038 preconnect_ssl_config, preconnect_ssl_config);
1040 out.rv = trans1->Start(&httpreq, callback1.callback(), log);
1041 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1042 out.rv = trans2->Start(&httpreq, callback2.callback(), log);
1043 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1045 out.rv = callback1.WaitForResult();
1046 ASSERT_EQ(OK, out.rv);
1047 out.rv = callback2.WaitForResult();
1048 ASSERT_EQ(OK, out.rv);
1050 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1051 EXPECT_TRUE(response1->headers.get() != NULL);
1052 EXPECT_TRUE(response1->was_fetched_via_spdy);
1053 out.status_line = response1->headers->GetStatusLine();
1054 out.response_info = *response1;
1055 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1056 EXPECT_EQ(OK, out.rv);
1057 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1058 EXPECT_EQ("hello!hello!", out.response_data);
1060 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1061 EXPECT_TRUE(response2->headers.get() != NULL);
1062 EXPECT_TRUE(response2->was_fetched_via_spdy);
1063 out.status_line = response2->headers->GetStatusLine();
1064 out.response_info = *response2;
1065 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1066 EXPECT_EQ(OK, out.rv);
1067 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1068 EXPECT_EQ("hello!hello!", out.response_data);
1070 helper.VerifyDataConsumed();
1073 // Similar to ThreeGets above, however this test adds a SETTINGS
1074 // frame. The SETTINGS frame is read during the IO loop waiting on
1075 // the first transaction completion, and sets a maximum concurrent
1076 // stream limit of 1. This means that our IO loop exists after the
1077 // second transaction completes, so we can assert on read_index().
1078 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
1079 // Construct the request.
1080 scoped_ptr<SpdyFrame> req(
1081 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1082 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1083 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1084 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1086 scoped_ptr<SpdyFrame> req2(
1087 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1088 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1089 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1090 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1092 scoped_ptr<SpdyFrame> req3(
1093 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
1094 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1095 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
1096 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
1098 SettingsMap settings;
1099 const uint32 max_concurrent_streams = 1;
1100 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1101 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1102 scoped_ptr<SpdyFrame> settings_frame(
1103 spdy_util_.ConstructSpdySettings(settings));
1105 MockWrite writes[] = {
1106 CreateMockWrite(*req),
1107 CreateMockWrite(*req2),
1108 CreateMockWrite(*req3),
1111 MockRead reads[] = {
1112 CreateMockRead(*settings_frame, 1),
1113 CreateMockRead(*resp),
1114 CreateMockRead(*body),
1115 CreateMockRead(*fbody),
1116 CreateMockRead(*resp2, 7),
1117 CreateMockRead(*body2),
1118 CreateMockRead(*fbody2),
1119 CreateMockRead(*resp3, 12),
1120 CreateMockRead(*body3),
1121 CreateMockRead(*fbody3),
1123 MockRead(ASYNC, 0, 0), // EOF
1126 OrderedSocketData data(reads, arraysize(reads),
1127 writes, arraysize(writes));
1128 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1130 BoundNetLog log;
1131 TransactionHelperResult out;
1133 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1134 BoundNetLog(), GetParam(), NULL);
1135 helper.RunPreTestSetup();
1136 helper.AddData(&data);
1137 // We require placeholder data because three get requests are sent out, so
1138 // there needs to be three sets of SSL connection data.
1139 helper.AddData(&data_placeholder);
1140 helper.AddData(&data_placeholder);
1141 scoped_ptr<HttpNetworkTransaction> trans1(
1142 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1143 scoped_ptr<HttpNetworkTransaction> trans2(
1144 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1145 scoped_ptr<HttpNetworkTransaction> trans3(
1146 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1148 TestCompletionCallback callback1;
1149 TestCompletionCallback callback2;
1150 TestCompletionCallback callback3;
1152 HttpRequestInfo httpreq1 = CreateGetRequest();
1153 HttpRequestInfo httpreq2 = CreateGetRequest();
1154 HttpRequestInfo httpreq3 = CreateGetRequest();
1156 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1157 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1158 // Run transaction 1 through quickly to force a read of our SETTINGS
1159 // frame.
1160 out.rv = callback1.WaitForResult();
1161 ASSERT_EQ(OK, out.rv);
1163 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1164 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1165 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1166 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1167 out.rv = callback2.WaitForResult();
1168 ASSERT_EQ(OK, out.rv);
1169 EXPECT_EQ(7U, data.read_index()); // i.e. the third trans was queued
1171 out.rv = callback3.WaitForResult();
1172 ASSERT_EQ(OK, out.rv);
1174 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1175 ASSERT_TRUE(response1 != NULL);
1176 EXPECT_TRUE(response1->headers.get() != NULL);
1177 EXPECT_TRUE(response1->was_fetched_via_spdy);
1178 out.status_line = response1->headers->GetStatusLine();
1179 out.response_info = *response1;
1180 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1181 EXPECT_EQ(OK, out.rv);
1182 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1183 EXPECT_EQ("hello!hello!", out.response_data);
1185 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1186 out.status_line = response2->headers->GetStatusLine();
1187 out.response_info = *response2;
1188 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1189 EXPECT_EQ(OK, out.rv);
1190 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1191 EXPECT_EQ("hello!hello!", out.response_data);
1193 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1194 out.status_line = response3->headers->GetStatusLine();
1195 out.response_info = *response3;
1196 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1197 EXPECT_EQ(OK, out.rv);
1198 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1199 EXPECT_EQ("hello!hello!", out.response_data);
1201 helper.VerifyDataConsumed();
1203 EXPECT_EQ(OK, out.rv);
1206 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1207 // a fourth transaction. The third and fourth transactions have
1208 // different data ("hello!" vs "hello!hello!") and because of the
1209 // user specified priority, we expect to see them inverted in
1210 // the response from the server.
1211 TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
1212 // Construct the request.
1213 scoped_ptr<SpdyFrame> req(
1214 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1215 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1216 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1217 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1219 scoped_ptr<SpdyFrame> req2(
1220 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1221 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1222 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1223 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1225 scoped_ptr<SpdyFrame> req4(
1226 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true));
1227 scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1228 scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true));
1230 scoped_ptr<SpdyFrame> req3(
1231 spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true));
1232 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
1233 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false));
1234 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true));
1236 SettingsMap settings;
1237 const uint32 max_concurrent_streams = 1;
1238 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1239 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1240 scoped_ptr<SpdyFrame> settings_frame(
1241 spdy_util_.ConstructSpdySettings(settings));
1243 MockWrite writes[] = { CreateMockWrite(*req),
1244 CreateMockWrite(*req2),
1245 CreateMockWrite(*req4),
1246 CreateMockWrite(*req3),
1248 MockRead reads[] = {
1249 CreateMockRead(*settings_frame, 1),
1250 CreateMockRead(*resp),
1251 CreateMockRead(*body),
1252 CreateMockRead(*fbody),
1253 CreateMockRead(*resp2, 7),
1254 CreateMockRead(*body2),
1255 CreateMockRead(*fbody2),
1256 CreateMockRead(*resp4, 13),
1257 CreateMockRead(*fbody4),
1258 CreateMockRead(*resp3, 16),
1259 CreateMockRead(*body3),
1260 CreateMockRead(*fbody3),
1262 MockRead(ASYNC, 0, 0), // EOF
1265 OrderedSocketData data(reads, arraysize(reads),
1266 writes, arraysize(writes));
1267 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1269 BoundNetLog log;
1270 TransactionHelperResult out;
1271 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1272 BoundNetLog(), GetParam(), NULL);
1273 helper.RunPreTestSetup();
1274 helper.AddData(&data);
1275 // We require placeholder data because four get requests are sent out, so
1276 // there needs to be four sets of SSL connection data.
1277 helper.AddData(&data_placeholder);
1278 helper.AddData(&data_placeholder);
1279 helper.AddData(&data_placeholder);
1280 scoped_ptr<HttpNetworkTransaction> trans1(
1281 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1282 scoped_ptr<HttpNetworkTransaction> trans2(
1283 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1284 scoped_ptr<HttpNetworkTransaction> trans3(
1285 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1286 scoped_ptr<HttpNetworkTransaction> trans4(
1287 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
1289 TestCompletionCallback callback1;
1290 TestCompletionCallback callback2;
1291 TestCompletionCallback callback3;
1292 TestCompletionCallback callback4;
1294 HttpRequestInfo httpreq1 = CreateGetRequest();
1295 HttpRequestInfo httpreq2 = CreateGetRequest();
1296 HttpRequestInfo httpreq3 = CreateGetRequest();
1297 HttpRequestInfo httpreq4 = CreateGetRequest();
1299 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1300 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1301 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1302 out.rv = callback1.WaitForResult();
1303 ASSERT_EQ(OK, out.rv);
1305 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1306 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1307 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1308 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1309 out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
1310 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1312 out.rv = callback2.WaitForResult();
1313 ASSERT_EQ(OK, out.rv);
1314 EXPECT_EQ(data.read_index(), 7U); // i.e. the third & fourth trans queued
1316 out.rv = callback3.WaitForResult();
1317 ASSERT_EQ(OK, out.rv);
1319 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1320 EXPECT_TRUE(response1->headers.get() != NULL);
1321 EXPECT_TRUE(response1->was_fetched_via_spdy);
1322 out.status_line = response1->headers->GetStatusLine();
1323 out.response_info = *response1;
1324 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1325 EXPECT_EQ(OK, out.rv);
1326 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1327 EXPECT_EQ("hello!hello!", out.response_data);
1329 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1330 out.status_line = response2->headers->GetStatusLine();
1331 out.response_info = *response2;
1332 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1333 EXPECT_EQ(OK, out.rv);
1334 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1335 EXPECT_EQ("hello!hello!", out.response_data);
1337 // notice: response3 gets two hellos, response4 gets one
1338 // hello, so we know dequeuing priority was respected.
1339 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1340 out.status_line = response3->headers->GetStatusLine();
1341 out.response_info = *response3;
1342 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1343 EXPECT_EQ(OK, out.rv);
1344 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1345 EXPECT_EQ("hello!hello!", out.response_data);
1347 out.rv = callback4.WaitForResult();
1348 EXPECT_EQ(OK, out.rv);
1349 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
1350 out.status_line = response4->headers->GetStatusLine();
1351 out.response_info = *response4;
1352 out.rv = ReadTransaction(trans4.get(), &out.response_data);
1353 EXPECT_EQ(OK, out.rv);
1354 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1355 EXPECT_EQ("hello!", out.response_data);
1356 helper.VerifyDataConsumed();
1357 EXPECT_EQ(OK, out.rv);
1360 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1361 // deletes a session in the middle of the transaction to insure
1362 // that we properly remove pendingcreatestream objects from
1363 // the spdy_session
1364 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
1365 // Construct the request.
1366 scoped_ptr<SpdyFrame> req(
1367 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1368 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1369 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1370 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1372 scoped_ptr<SpdyFrame> req2(
1373 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1374 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1375 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1376 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1378 SettingsMap settings;
1379 const uint32 max_concurrent_streams = 1;
1380 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1381 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1382 scoped_ptr<SpdyFrame> settings_frame(
1383 spdy_util_.ConstructSpdySettings(settings));
1385 MockWrite writes[] = { CreateMockWrite(*req),
1386 CreateMockWrite(*req2),
1388 MockRead reads[] = {
1389 CreateMockRead(*settings_frame, 1),
1390 CreateMockRead(*resp),
1391 CreateMockRead(*body),
1392 CreateMockRead(*fbody),
1393 CreateMockRead(*resp2, 7),
1394 CreateMockRead(*body2),
1395 CreateMockRead(*fbody2),
1396 MockRead(ASYNC, 0, 0), // EOF
1399 OrderedSocketData data(reads, arraysize(reads),
1400 writes, arraysize(writes));
1401 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1403 BoundNetLog log;
1404 TransactionHelperResult out;
1405 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1406 BoundNetLog(), GetParam(), NULL);
1407 helper.RunPreTestSetup();
1408 helper.AddData(&data);
1409 // We require placeholder data because three get requests are sent out, so
1410 // there needs to be three sets of SSL connection data.
1411 helper.AddData(&data_placeholder);
1412 helper.AddData(&data_placeholder);
1413 scoped_ptr<HttpNetworkTransaction> trans1(
1414 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1415 scoped_ptr<HttpNetworkTransaction> trans2(
1416 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1417 scoped_ptr<HttpNetworkTransaction> trans3(
1418 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1420 TestCompletionCallback callback1;
1421 TestCompletionCallback callback2;
1422 TestCompletionCallback callback3;
1424 HttpRequestInfo httpreq1 = CreateGetRequest();
1425 HttpRequestInfo httpreq2 = CreateGetRequest();
1426 HttpRequestInfo httpreq3 = CreateGetRequest();
1428 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1429 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1430 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1431 out.rv = callback1.WaitForResult();
1432 ASSERT_EQ(OK, out.rv);
1434 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1435 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1436 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1437 delete trans3.release();
1438 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1439 out.rv = callback2.WaitForResult();
1440 ASSERT_EQ(OK, out.rv);
1442 EXPECT_EQ(8U, data.read_index());
1444 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1445 ASSERT_TRUE(response1 != NULL);
1446 EXPECT_TRUE(response1->headers.get() != NULL);
1447 EXPECT_TRUE(response1->was_fetched_via_spdy);
1448 out.status_line = response1->headers->GetStatusLine();
1449 out.response_info = *response1;
1450 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1451 EXPECT_EQ(OK, out.rv);
1452 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1453 EXPECT_EQ("hello!hello!", out.response_data);
1455 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1456 ASSERT_TRUE(response2 != NULL);
1457 out.status_line = response2->headers->GetStatusLine();
1458 out.response_info = *response2;
1459 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1460 EXPECT_EQ(OK, out.rv);
1461 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1462 EXPECT_EQ("hello!hello!", out.response_data);
1463 helper.VerifyDataConsumed();
1464 EXPECT_EQ(OK, out.rv);
1467 namespace {
1469 // The KillerCallback will delete the transaction on error as part of the
1470 // callback.
1471 class KillerCallback : public TestCompletionCallbackBase {
1472 public:
1473 explicit KillerCallback(HttpNetworkTransaction* transaction)
1474 : transaction_(transaction),
1475 callback_(base::Bind(&KillerCallback::OnComplete,
1476 base::Unretained(this))) {
1479 virtual ~KillerCallback() {}
1481 const CompletionCallback& callback() const { return callback_; }
1483 private:
1484 void OnComplete(int result) {
1485 if (result < 0)
1486 delete transaction_;
1488 SetResult(result);
1491 HttpNetworkTransaction* transaction_;
1492 CompletionCallback callback_;
1495 } // namespace
1497 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1498 // closes the socket while we have a pending transaction waiting for
1499 // a pending stream creation. http://crbug.com/52901
1500 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
1501 // Construct the request.
1502 scoped_ptr<SpdyFrame> req(
1503 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1504 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1505 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1506 scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1508 scoped_ptr<SpdyFrame> req2(
1509 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1510 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1512 SettingsMap settings;
1513 const uint32 max_concurrent_streams = 1;
1514 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1515 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1516 scoped_ptr<SpdyFrame> settings_frame(
1517 spdy_util_.ConstructSpdySettings(settings));
1519 MockWrite writes[] = { CreateMockWrite(*req),
1520 CreateMockWrite(*req2),
1522 MockRead reads[] = {
1523 CreateMockRead(*settings_frame, 1),
1524 CreateMockRead(*resp),
1525 CreateMockRead(*body),
1526 CreateMockRead(*fin_body),
1527 CreateMockRead(*resp2, 7),
1528 MockRead(ASYNC, ERR_CONNECTION_RESET, 0), // Abort!
1531 OrderedSocketData data(reads, arraysize(reads),
1532 writes, arraysize(writes));
1533 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1535 BoundNetLog log;
1536 TransactionHelperResult out;
1537 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1538 BoundNetLog(), GetParam(), NULL);
1539 helper.RunPreTestSetup();
1540 helper.AddData(&data);
1541 // We require placeholder data because three get requests are sent out, so
1542 // there needs to be three sets of SSL connection data.
1543 helper.AddData(&data_placeholder);
1544 helper.AddData(&data_placeholder);
1545 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session().get());
1546 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session().get());
1547 HttpNetworkTransaction* trans3(
1548 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1550 TestCompletionCallback callback1;
1551 TestCompletionCallback callback2;
1552 KillerCallback callback3(trans3);
1554 HttpRequestInfo httpreq1 = CreateGetRequest();
1555 HttpRequestInfo httpreq2 = CreateGetRequest();
1556 HttpRequestInfo httpreq3 = CreateGetRequest();
1558 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
1559 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1560 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1561 out.rv = callback1.WaitForResult();
1562 ASSERT_EQ(OK, out.rv);
1564 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
1565 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1566 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1567 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1568 out.rv = callback3.WaitForResult();
1569 ASSERT_EQ(ERR_ABORTED, out.rv);
1571 EXPECT_EQ(6U, data.read_index());
1573 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1574 ASSERT_TRUE(response1 != NULL);
1575 EXPECT_TRUE(response1->headers.get() != NULL);
1576 EXPECT_TRUE(response1->was_fetched_via_spdy);
1577 out.status_line = response1->headers->GetStatusLine();
1578 out.response_info = *response1;
1579 out.rv = ReadTransaction(&trans1, &out.response_data);
1580 EXPECT_EQ(OK, out.rv);
1582 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1583 ASSERT_TRUE(response2 != NULL);
1584 out.status_line = response2->headers->GetStatusLine();
1585 out.response_info = *response2;
1586 out.rv = ReadTransaction(&trans2, &out.response_data);
1587 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1589 helper.VerifyDataConsumed();
1592 // Test that a simple PUT request works.
1593 TEST_P(SpdyNetworkTransactionTest, Put) {
1594 // Setup the request
1595 HttpRequestInfo request;
1596 request.method = "PUT";
1597 request.url = GURL("http://www.google.com/");
1599 const SpdyHeaderInfo kSynStartHeader = {
1600 SYN_STREAM, // Kind = Syn
1601 1, // Stream ID
1602 0, // Associated stream ID
1603 ConvertRequestPriorityToSpdyPriority(
1604 LOWEST, spdy_util_.spdy_version()),
1605 kSpdyCredentialSlotUnused,
1606 CONTROL_FLAG_FIN, // Control Flags
1607 false, // Compressed
1608 RST_STREAM_INVALID, // Status
1609 NULL, // Data
1610 0, // Length
1611 DATA_FLAG_NONE // Data Flags
1613 scoped_ptr<SpdyHeaderBlock> put_headers(
1614 spdy_util_.ConstructPutHeaderBlock("http://www.google.com", 0));
1615 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyFrame(
1616 kSynStartHeader, put_headers.Pass()));
1617 MockWrite writes[] = {
1618 CreateMockWrite(*req),
1621 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1622 const SpdyHeaderInfo kSynReplyHeader = {
1623 SYN_REPLY, // Kind = SynReply
1624 1, // Stream ID
1625 0, // Associated stream ID
1626 ConvertRequestPriorityToSpdyPriority(
1627 LOWEST, spdy_util_.spdy_version()),
1628 kSpdyCredentialSlotUnused,
1629 CONTROL_FLAG_NONE, // Control Flags
1630 false, // Compressed
1631 RST_STREAM_INVALID, // Status
1632 NULL, // Data
1633 0, // Length
1634 DATA_FLAG_NONE // Data Flags
1636 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
1637 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
1638 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
1639 (*reply_headers)["content-length"] = "1234";
1640 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyFrame(
1641 kSynReplyHeader, reply_headers.Pass()));
1642 MockRead reads[] = {
1643 CreateMockRead(*resp),
1644 CreateMockRead(*body),
1645 MockRead(ASYNC, 0, 0) // EOF
1648 DelayedSocketData data(1, reads, arraysize(reads),
1649 writes, arraysize(writes));
1650 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1651 BoundNetLog(), GetParam(), NULL);
1652 helper.RunToCompletion(&data);
1653 TransactionHelperResult out = helper.output();
1655 EXPECT_EQ(OK, out.rv);
1656 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1659 // Test that a simple HEAD request works.
1660 TEST_P(SpdyNetworkTransactionTest, Head) {
1661 // Setup the request
1662 HttpRequestInfo request;
1663 request.method = "HEAD";
1664 request.url = GURL("http://www.google.com/");
1666 const SpdyHeaderInfo kSynStartHeader = {
1667 SYN_STREAM, // Kind = Syn
1668 1, // Stream ID
1669 0, // Associated stream ID
1670 ConvertRequestPriorityToSpdyPriority(
1671 LOWEST, spdy_util_.spdy_version()),
1672 kSpdyCredentialSlotUnused,
1673 CONTROL_FLAG_FIN, // Control Flags
1674 false, // Compressed
1675 RST_STREAM_INVALID, // Status
1676 NULL, // Data
1677 0, // Length
1678 DATA_FLAG_NONE // Data Flags
1680 scoped_ptr<SpdyHeaderBlock> head_headers(
1681 spdy_util_.ConstructHeadHeaderBlock("http://www.google.com", 0));
1682 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyFrame(
1683 kSynStartHeader, head_headers.Pass()));
1684 MockWrite writes[] = {
1685 CreateMockWrite(*req),
1688 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1689 const SpdyHeaderInfo kSynReplyHeader = {
1690 SYN_REPLY, // Kind = SynReply
1691 1, // Stream ID
1692 0, // Associated stream ID
1693 ConvertRequestPriorityToSpdyPriority(
1694 LOWEST, spdy_util_.spdy_version()),
1695 kSpdyCredentialSlotUnused,
1696 CONTROL_FLAG_NONE, // Control Flags
1697 false, // Compressed
1698 RST_STREAM_INVALID, // Status
1699 NULL, // Data
1700 0, // Length
1701 DATA_FLAG_NONE // Data Flags
1703 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
1704 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
1705 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
1706 (*reply_headers)["content-length"] = "1234";
1707 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyFrame(
1708 kSynReplyHeader,
1709 reply_headers.Pass()));
1710 MockRead reads[] = {
1711 CreateMockRead(*resp),
1712 CreateMockRead(*body),
1713 MockRead(ASYNC, 0, 0) // EOF
1716 DelayedSocketData data(1, reads, arraysize(reads),
1717 writes, arraysize(writes));
1718 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1719 BoundNetLog(), GetParam(), NULL);
1720 helper.RunToCompletion(&data);
1721 TransactionHelperResult out = helper.output();
1723 EXPECT_EQ(OK, out.rv);
1724 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1727 // Test that a simple POST works.
1728 TEST_P(SpdyNetworkTransactionTest, Post) {
1729 scoped_ptr<SpdyFrame> req(
1730 spdy_util_.ConstructSpdyPost(
1731 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1732 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1733 MockWrite writes[] = {
1734 CreateMockWrite(*req),
1735 CreateMockWrite(*body), // POST upload frame
1738 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1739 MockRead reads[] = {
1740 CreateMockRead(*resp),
1741 CreateMockRead(*body),
1742 MockRead(ASYNC, 0, 0) // EOF
1745 DelayedSocketData data(2, reads, arraysize(reads),
1746 writes, arraysize(writes));
1747 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
1748 BoundNetLog(), GetParam(), NULL);
1749 helper.RunToCompletion(&data);
1750 TransactionHelperResult out = helper.output();
1751 EXPECT_EQ(OK, out.rv);
1752 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1753 EXPECT_EQ("hello!", out.response_data);
1756 // Test that a POST with a file works.
1757 TEST_P(SpdyNetworkTransactionTest, FilePost) {
1758 scoped_ptr<SpdyFrame> req(
1759 spdy_util_.ConstructSpdyPost(
1760 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1761 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1762 MockWrite writes[] = {
1763 CreateMockWrite(*req),
1764 CreateMockWrite(*body), // POST upload frame
1767 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1768 MockRead reads[] = {
1769 CreateMockRead(*resp),
1770 CreateMockRead(*body),
1771 MockRead(ASYNC, 0, 0) // EOF
1774 DelayedSocketData data(2, reads, arraysize(reads),
1775 writes, arraysize(writes));
1776 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
1777 BoundNetLog(), GetParam(), NULL);
1778 helper.RunToCompletion(&data);
1779 TransactionHelperResult out = helper.output();
1780 EXPECT_EQ(OK, out.rv);
1781 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1782 EXPECT_EQ("hello!", out.response_data);
1785 // Test that a complex POST works.
1786 TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
1787 scoped_ptr<SpdyFrame> req(
1788 spdy_util_.ConstructSpdyPost(
1789 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1790 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1791 MockWrite writes[] = {
1792 CreateMockWrite(*req),
1793 CreateMockWrite(*body), // POST upload frame
1796 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1797 MockRead reads[] = {
1798 CreateMockRead(*resp),
1799 CreateMockRead(*body),
1800 MockRead(ASYNC, 0, 0) // EOF
1803 DelayedSocketData data(2, reads, arraysize(reads),
1804 writes, arraysize(writes));
1805 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
1806 DEFAULT_PRIORITY,
1807 BoundNetLog(), GetParam(), NULL);
1808 helper.RunToCompletion(&data);
1809 TransactionHelperResult out = helper.output();
1810 EXPECT_EQ(OK, out.rv);
1811 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1812 EXPECT_EQ("hello!", out.response_data);
1815 // Test that a chunked POST works.
1816 TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
1817 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1818 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1819 MockWrite writes[] = {
1820 CreateMockWrite(*req),
1821 CreateMockWrite(*body),
1824 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1825 MockRead reads[] = {
1826 CreateMockRead(*resp),
1827 CreateMockRead(*body),
1828 MockRead(ASYNC, 0, 0) // EOF
1831 DelayedSocketData data(2, reads, arraysize(reads),
1832 writes, arraysize(writes));
1833 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1834 DEFAULT_PRIORITY,
1835 BoundNetLog(), GetParam(), NULL);
1837 // These chunks get merged into a single frame when being sent.
1838 const int kFirstChunkSize = kUploadDataSize/2;
1839 helper.request().upload_data_stream->AppendChunk(
1840 kUploadData, kFirstChunkSize, false);
1841 helper.request().upload_data_stream->AppendChunk(
1842 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1844 helper.RunToCompletion(&data);
1845 TransactionHelperResult out = helper.output();
1846 EXPECT_EQ(OK, out.rv);
1847 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1848 EXPECT_EQ(kUploadData, out.response_data);
1851 // Test that a chunked POST works with chunks appended after transaction starts.
1852 TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
1853 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1854 scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
1855 scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false));
1856 scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
1857 MockWrite writes[] = {
1858 CreateMockWrite(*req),
1859 CreateMockWrite(*chunk1),
1860 CreateMockWrite(*chunk2),
1861 CreateMockWrite(*chunk3),
1864 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1865 MockRead reads[] = {
1866 CreateMockRead(*resp),
1867 CreateMockRead(*chunk1),
1868 CreateMockRead(*chunk2),
1869 CreateMockRead(*chunk3),
1870 MockRead(ASYNC, 0, 0) // EOF
1873 DelayedSocketData data(4, reads, arraysize(reads),
1874 writes, arraysize(writes));
1875 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1876 DEFAULT_PRIORITY,
1877 BoundNetLog(), GetParam(), NULL);
1879 helper.request().upload_data_stream->AppendChunk(
1880 kUploadData, kUploadDataSize, false);
1882 helper.RunPreTestSetup();
1883 helper.AddData(&data);
1884 ASSERT_TRUE(helper.StartDefaultTest());
1886 base::RunLoop().RunUntilIdle();
1887 helper.request().upload_data_stream->AppendChunk(
1888 kUploadData, kUploadDataSize, false);
1889 base::RunLoop().RunUntilIdle();
1890 helper.request().upload_data_stream->AppendChunk(
1891 kUploadData, kUploadDataSize, true);
1893 helper.FinishDefaultTest();
1894 helper.VerifyDataConsumed();
1896 std::string expected_response;
1897 expected_response += kUploadData;
1898 expected_response += kUploadData;
1899 expected_response += kUploadData;
1901 TransactionHelperResult out = helper.output();
1902 EXPECT_EQ(OK, out.rv);
1903 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1904 EXPECT_EQ(expected_response, out.response_data);
1907 // Test that a POST without any post data works.
1908 TEST_P(SpdyNetworkTransactionTest, NullPost) {
1909 // Setup the request
1910 HttpRequestInfo request;
1911 request.method = "POST";
1912 request.url = GURL(kRequestUrl);
1913 // Create an empty UploadData.
1914 request.upload_data_stream = NULL;
1916 // When request.upload_data_stream is NULL for post, content-length is
1917 // expected to be 0.
1918 scoped_ptr<SpdyFrame> req(
1919 spdy_util_.ConstructSpdyPost(kRequestUrl, 1, 0, LOWEST, NULL, 0));
1920 // Set the FIN bit since there will be no body.
1921 test::SetFrameFlags(req.get(), CONTROL_FLAG_FIN, spdy_util_.spdy_version());
1922 MockWrite writes[] = {
1923 CreateMockWrite(*req),
1926 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1927 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1928 MockRead reads[] = {
1929 CreateMockRead(*resp),
1930 CreateMockRead(*body),
1931 MockRead(ASYNC, 0, 0) // EOF
1934 DelayedSocketData data(1, reads, arraysize(reads),
1935 writes, arraysize(writes));
1937 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1938 BoundNetLog(), GetParam(), NULL);
1939 helper.RunToCompletion(&data);
1940 TransactionHelperResult out = helper.output();
1941 EXPECT_EQ(OK, out.rv);
1942 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1943 EXPECT_EQ("hello!", out.response_data);
1946 // Test that a simple POST works.
1947 TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
1948 // Create an empty UploadDataStream.
1949 ScopedVector<UploadElementReader> element_readers;
1950 UploadDataStream stream(&element_readers, 0);
1952 // Setup the request
1953 HttpRequestInfo request;
1954 request.method = "POST";
1955 request.url = GURL(kRequestUrl);
1956 request.upload_data_stream = &stream;
1958 const uint64 kContentLength = 0;
1959 scoped_ptr<SpdyFrame> req(
1960 spdy_util_.ConstructSpdyPost(
1961 kRequestUrl, 1, kContentLength, LOWEST, NULL, 0));
1962 // Set the FIN bit since there will be no body.
1963 test::SetFrameFlags(req.get(), CONTROL_FLAG_FIN, spdy_util_.spdy_version());
1964 MockWrite writes[] = {
1965 CreateMockWrite(*req),
1968 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1969 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1970 MockRead reads[] = {
1971 CreateMockRead(*resp),
1972 CreateMockRead(*body),
1973 MockRead(ASYNC, 0, 0) // EOF
1976 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
1978 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1979 BoundNetLog(), GetParam(), NULL);
1980 helper.RunToCompletion(&data);
1981 TransactionHelperResult out = helper.output();
1982 EXPECT_EQ(OK, out.rv);
1983 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1984 EXPECT_EQ("hello!", out.response_data);
1987 // While we're doing a post, the server sends back a SYN_REPLY.
1988 TEST_P(SpdyNetworkTransactionTest, PostWithEarlySynReply) {
1989 static const char upload[] = { "hello!" };
1990 ScopedVector<UploadElementReader> element_readers;
1991 element_readers.push_back(
1992 new UploadBytesElementReader(upload, sizeof(upload)));
1993 UploadDataStream stream(&element_readers, 0);
1995 // Setup the request
1996 HttpRequestInfo request;
1997 request.method = "POST";
1998 request.url = GURL(kRequestUrl);
1999 request.upload_data_stream = &stream;
2001 scoped_ptr<SpdyFrame> stream_reply(
2002 spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
2003 MockRead reads[] = {
2004 CreateMockRead(*stream_reply, 1),
2005 MockRead(ASYNC, 0, 4) // EOF
2008 scoped_ptr<SpdyFrame> req(
2009 spdy_util_.ConstructSpdyPost(
2010 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
2011 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2012 scoped_ptr<SpdyFrame> rst(
2013 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2014 MockWrite writes[] = {
2015 CreateMockWrite(*req, 0),
2016 CreateMockWrite(*body, 2),
2017 CreateMockWrite(*rst, 3)
2020 DeterministicSocketData data(reads, arraysize(reads),
2021 writes, arraysize(writes));
2022 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
2023 BoundNetLog(), GetParam(), NULL);
2024 helper.SetDeterministic();
2025 helper.RunPreTestSetup();
2026 helper.AddDeterministicData(&data);
2027 HttpNetworkTransaction* trans = helper.trans();
2029 TestCompletionCallback callback;
2030 int rv = trans->Start(
2031 &CreatePostRequest(), callback.callback(), BoundNetLog());
2032 EXPECT_EQ(ERR_IO_PENDING, rv);
2034 data.RunFor(4);
2035 rv = callback.WaitForResult();
2036 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
2037 data.RunFor(1);
2040 // The client upon cancellation tries to send a RST_STREAM frame. The mock
2041 // socket causes the TCP write to return zero. This test checks that the client
2042 // tries to queue up the RST_STREAM frame again.
2043 TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
2044 scoped_ptr<SpdyFrame> req(
2045 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2046 scoped_ptr<SpdyFrame> rst(
2047 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2048 MockWrite writes[] = {
2049 CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
2050 MockWrite(SYNCHRONOUS, 0, 0, 2),
2051 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
2054 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2055 MockRead reads[] = {
2056 CreateMockRead(*resp.get(), 1, ASYNC),
2057 MockRead(ASYNC, 0, 0, 4) // EOF
2060 DeterministicSocketData data(reads, arraysize(reads),
2061 writes, arraysize(writes));
2062 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2063 BoundNetLog(), GetParam(), NULL);
2064 helper.SetDeterministic();
2065 helper.RunPreTestSetup();
2066 helper.AddDeterministicData(&data);
2067 HttpNetworkTransaction* trans = helper.trans();
2069 TestCompletionCallback callback;
2070 int rv = trans->Start(
2071 &CreateGetRequest(), callback.callback(), BoundNetLog());
2072 EXPECT_EQ(ERR_IO_PENDING, rv);
2074 data.SetStop(2);
2075 data.Run();
2076 helper.ResetTrans();
2077 data.SetStop(20);
2078 data.Run();
2080 helper.VerifyDataConsumed();
2083 // Test that the transaction doesn't crash when we don't have a reply.
2084 TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
2085 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2086 MockRead reads[] = {
2087 CreateMockRead(*body),
2088 MockRead(ASYNC, 0, 0) // EOF
2091 DelayedSocketData data(1, reads, arraysize(reads), NULL, 0);
2092 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2093 BoundNetLog(), GetParam(), NULL);
2094 helper.RunToCompletion(&data);
2095 TransactionHelperResult out = helper.output();
2096 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2099 // Test that the transaction doesn't crash when we get two replies on the same
2100 // stream ID. See http://crbug.com/45639.
2101 TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
2102 scoped_ptr<SpdyFrame> req(
2103 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2104 scoped_ptr<SpdyFrame> rst(
2105 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_STREAM_IN_USE));
2106 MockWrite writes[] = {
2107 CreateMockWrite(*req),
2108 CreateMockWrite(*rst),
2111 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2112 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2113 MockRead reads[] = {
2114 CreateMockRead(*resp),
2115 CreateMockRead(*resp),
2116 CreateMockRead(*body),
2117 MockRead(ASYNC, 0, 0) // EOF
2120 DelayedSocketData data(1, reads, arraysize(reads),
2121 writes, arraysize(writes));
2123 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2124 BoundNetLog(), GetParam(), NULL);
2125 helper.RunPreTestSetup();
2126 helper.AddData(&data);
2128 HttpNetworkTransaction* trans = helper.trans();
2130 TestCompletionCallback callback;
2131 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2132 EXPECT_EQ(ERR_IO_PENDING, rv);
2133 rv = callback.WaitForResult();
2134 EXPECT_EQ(OK, rv);
2136 const HttpResponseInfo* response = trans->GetResponseInfo();
2137 ASSERT_TRUE(response != NULL);
2138 EXPECT_TRUE(response->headers.get() != NULL);
2139 EXPECT_TRUE(response->was_fetched_via_spdy);
2140 std::string response_data;
2141 rv = ReadTransaction(trans, &response_data);
2142 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
2144 helper.VerifyDataConsumed();
2147 TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
2148 // Construct the request.
2149 scoped_ptr<SpdyFrame> req(
2150 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2151 scoped_ptr<SpdyFrame> rst(
2152 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2153 MockWrite writes[] = {
2154 CreateMockWrite(*req),
2155 CreateMockWrite(*rst),
2158 const char* const headers[] = {
2159 "transfer-encoding", "chunked"
2161 scoped_ptr<SpdyFrame> resp(
2162 spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1));
2163 scoped_ptr<SpdyFrame> body(
2164 spdy_util_.ConstructSpdyBodyFrame(1, true));
2165 MockRead reads[] = {
2166 CreateMockRead(*resp),
2167 CreateMockRead(*body),
2168 MockRead(ASYNC, 0, 0) // EOF
2171 DelayedSocketData data(1, reads, arraysize(reads),
2172 writes, arraysize(writes));
2173 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2174 BoundNetLog(), GetParam(), NULL);
2175 helper.RunToCompletion(&data);
2176 TransactionHelperResult out = helper.output();
2177 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2179 helper.session()->spdy_session_pool()->CloseAllSessions();
2180 helper.VerifyDataConsumed();
2183 TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
2184 // Construct the request.
2185 scoped_ptr<SpdyFrame> req(
2186 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2187 scoped_ptr<SpdyFrame> rst(
2188 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
2189 MockWrite writes[] = {
2190 CreateMockWrite(*req),
2191 CreateMockWrite(*rst),
2194 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2195 const char* const headers[] = {
2196 "transfer-encoding", "chunked"
2198 scoped_ptr<SpdyFrame> push(
2199 spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2,
2200 2, 1, "http://www.google.com/1"));
2201 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2202 MockRead reads[] = {
2203 CreateMockRead(*resp),
2204 CreateMockRead(*push),
2205 CreateMockRead(*body),
2206 MockRead(ASYNC, 0, 0) // EOF
2209 DelayedSocketData data(1, reads, arraysize(reads),
2210 writes, arraysize(writes));
2211 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2212 BoundNetLog(), GetParam(), NULL);
2213 helper.RunToCompletion(&data);
2214 TransactionHelperResult out = helper.output();
2215 EXPECT_EQ(OK, out.rv);
2216 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2217 EXPECT_EQ("hello!", out.response_data);
2219 helper.session()->spdy_session_pool()->CloseAllSessions();
2220 helper.VerifyDataConsumed();
2223 TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
2224 // Construct the request.
2225 scoped_ptr<SpdyFrame> req(
2226 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2227 MockWrite writes[] = {
2228 CreateMockWrite(*req),
2231 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2232 MockRead reads[] = {
2233 CreateMockRead(*resp),
2234 // This following read isn't used by the test, except during the
2235 // RunUntilIdle() call at the end since the SpdySession survives the
2236 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2237 // MockRead will do here.
2238 MockRead(ASYNC, 0, 0) // EOF
2241 StaticSocketDataProvider data(reads, arraysize(reads),
2242 writes, arraysize(writes));
2244 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2245 BoundNetLog(), GetParam(), NULL);
2246 helper.RunPreTestSetup();
2247 helper.AddData(&data);
2248 HttpNetworkTransaction* trans = helper.trans();
2250 TestCompletionCallback callback;
2251 int rv = trans->Start(
2252 &CreateGetRequest(), callback.callback(), BoundNetLog());
2253 EXPECT_EQ(ERR_IO_PENDING, rv);
2254 helper.ResetTrans(); // Cancel the transaction.
2256 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2257 // MockClientSocketFactory) are still alive.
2258 base::RunLoop().RunUntilIdle();
2259 helper.VerifyDataNotConsumed();
2262 // Verify that the client sends a Rst Frame upon cancelling the stream.
2263 TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
2264 scoped_ptr<SpdyFrame> req(
2265 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2266 scoped_ptr<SpdyFrame> rst(
2267 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2268 MockWrite writes[] = {
2269 CreateMockWrite(*req, 0, SYNCHRONOUS),
2270 CreateMockWrite(*rst, 2, SYNCHRONOUS),
2273 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2274 MockRead reads[] = {
2275 CreateMockRead(*resp, 1, ASYNC),
2276 MockRead(ASYNC, 0, 0, 3) // EOF
2279 DeterministicSocketData data(reads, arraysize(reads),
2280 writes, arraysize(writes));
2282 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2283 BoundNetLog(),
2284 GetParam(), NULL);
2285 helper.SetDeterministic();
2286 helper.RunPreTestSetup();
2287 helper.AddDeterministicData(&data);
2288 HttpNetworkTransaction* trans = helper.trans();
2290 TestCompletionCallback callback;
2292 int rv = trans->Start(
2293 &CreateGetRequest(), callback.callback(), BoundNetLog());
2294 EXPECT_EQ(ERR_IO_PENDING, rv);
2296 data.SetStop(2);
2297 data.Run();
2298 helper.ResetTrans();
2299 data.SetStop(20);
2300 data.Run();
2302 helper.VerifyDataConsumed();
2305 // Verify that the client can correctly deal with the user callback attempting
2306 // to start another transaction on a session that is closing down. See
2307 // http://crbug.com/47455
2308 TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
2309 scoped_ptr<SpdyFrame> req(
2310 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2311 MockWrite writes[] = { CreateMockWrite(*req) };
2312 MockWrite writes2[] = { CreateMockWrite(*req) };
2314 // The indicated length of this frame is longer than its actual length. When
2315 // the session receives an empty frame after this one, it shuts down the
2316 // session, and calls the read callback with the incomplete data.
2317 const uint8 kGetBodyFrame2[] = {
2318 0x00, 0x00, 0x00, 0x01,
2319 0x01, 0x00, 0x00, 0x07,
2320 'h', 'e', 'l', 'l', 'o', '!',
2323 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2324 MockRead reads[] = {
2325 CreateMockRead(*resp, 2),
2326 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2327 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2328 arraysize(kGetBodyFrame2), 4),
2329 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2330 MockRead(ASYNC, 0, 0, 6), // EOF
2332 MockRead reads2[] = {
2333 CreateMockRead(*resp, 2),
2334 MockRead(ASYNC, 0, 0, 3), // EOF
2337 OrderedSocketData data(reads, arraysize(reads),
2338 writes, arraysize(writes));
2339 DelayedSocketData data2(1, reads2, arraysize(reads2),
2340 writes2, arraysize(writes2));
2342 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2343 BoundNetLog(), GetParam(), NULL);
2344 helper.RunPreTestSetup();
2345 helper.AddData(&data);
2346 helper.AddData(&data2);
2347 HttpNetworkTransaction* trans = helper.trans();
2349 // Start the transaction with basic parameters.
2350 TestCompletionCallback callback;
2351 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2352 EXPECT_EQ(ERR_IO_PENDING, rv);
2353 rv = callback.WaitForResult();
2355 const int kSize = 3000;
2356 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2357 rv = trans->Read(
2358 buf.get(),
2359 kSize,
2360 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
2361 helper.session()));
2362 // This forces an err_IO_pending, which sets the callback.
2363 data.CompleteRead();
2364 // This finishes the read.
2365 data.CompleteRead();
2366 helper.VerifyDataConsumed();
2369 // Verify that the client can correctly deal with the user callback deleting the
2370 // transaction. Failures will usually be valgrind errors. See
2371 // http://crbug.com/46925
2372 TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
2373 scoped_ptr<SpdyFrame> req(
2374 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2375 MockWrite writes[] = { CreateMockWrite(*req) };
2377 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2378 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2379 MockRead reads[] = {
2380 CreateMockRead(*resp.get(), 2),
2381 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2382 CreateMockRead(*body.get(), 4),
2383 MockRead(ASYNC, 0, 0, 5), // EOF
2386 OrderedSocketData data(reads, arraysize(reads),
2387 writes, arraysize(writes));
2389 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2390 BoundNetLog(), GetParam(), NULL);
2391 helper.RunPreTestSetup();
2392 helper.AddData(&data);
2393 HttpNetworkTransaction* trans = helper.trans();
2395 // Start the transaction with basic parameters.
2396 TestCompletionCallback callback;
2397 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2398 EXPECT_EQ(ERR_IO_PENDING, rv);
2399 rv = callback.WaitForResult();
2401 // Setup a user callback which will delete the session, and clear out the
2402 // memory holding the stream object. Note that the callback deletes trans.
2403 const int kSize = 3000;
2404 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2405 rv = trans->Read(
2406 buf.get(),
2407 kSize,
2408 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
2409 base::Unretained(&helper)));
2410 ASSERT_EQ(ERR_IO_PENDING, rv);
2411 data.CompleteRead();
2413 // Finish running rest of tasks.
2414 base::RunLoop().RunUntilIdle();
2415 helper.VerifyDataConsumed();
2418 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2419 TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
2420 const SpdyHeaderInfo kSynStartHeader = spdy_util_.MakeSpdyHeader(SYN_STREAM);
2421 scoped_ptr<SpdyHeaderBlock> headers(
2422 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2423 (*headers)["user-agent"] = "";
2424 (*headers)["accept-encoding"] = "gzip,deflate";
2425 scoped_ptr<SpdyHeaderBlock> headers2(
2426 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2427 (*headers2)["user-agent"] = "";
2428 (*headers2)["accept-encoding"] = "gzip,deflate";
2430 // Setup writes/reads to www.google.com
2431 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyFrame(
2432 kSynStartHeader, headers.Pass()));
2433 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyFrame(
2434 kSynStartHeader, headers2.Pass()));
2435 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
2436 MockWrite writes[] = {
2437 CreateMockWrite(*req, 1),
2439 MockRead reads[] = {
2440 CreateMockRead(*resp, 2),
2441 MockRead(ASYNC, 0, 0, 3) // EOF
2444 // Setup writes/reads to www.foo.com
2445 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2446 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2447 MockWrite writes2[] = {
2448 CreateMockWrite(*req2, 1),
2450 MockRead reads2[] = {
2451 CreateMockRead(*resp2, 2),
2452 CreateMockRead(*body2, 3),
2453 MockRead(ASYNC, 0, 0, 4) // EOF
2455 OrderedSocketData data(reads, arraysize(reads),
2456 writes, arraysize(writes));
2457 OrderedSocketData data2(reads2, arraysize(reads2),
2458 writes2, arraysize(writes2));
2460 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2461 HttpStreamFactory::set_force_spdy_over_ssl(false);
2462 HttpStreamFactory::set_force_spdy_always(true);
2463 TestDelegate d;
2465 SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
2466 net::URLRequest r(
2467 GURL("http://www.google.com/"), &d, &spdy_url_request_context);
2468 spdy_url_request_context.socket_factory().
2469 AddSocketDataProvider(&data);
2470 spdy_url_request_context.socket_factory().
2471 AddSocketDataProvider(&data2);
2473 d.set_quit_on_redirect(true);
2474 r.Start();
2475 base::RunLoop().Run();
2477 EXPECT_EQ(1, d.received_redirect_count());
2479 r.FollowDeferredRedirect();
2480 base::RunLoop().Run();
2481 EXPECT_EQ(1, d.response_started_count());
2482 EXPECT_FALSE(d.received_data_before_response());
2483 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r.status().status());
2484 std::string contents("hello!");
2485 EXPECT_EQ(contents, d.data_received());
2487 EXPECT_TRUE(data.at_read_eof());
2488 EXPECT_TRUE(data.at_write_eof());
2489 EXPECT_TRUE(data2.at_read_eof());
2490 EXPECT_TRUE(data2.at_write_eof());
2493 // Send a spdy request to www.google.com. Get a pushed stream that redirects to
2494 // www.foo.com.
2495 TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
2496 const SpdyHeaderInfo kSynStartHeader = spdy_util_.MakeSpdyHeader(SYN_STREAM);
2498 scoped_ptr<SpdyHeaderBlock> headers(
2499 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2500 (*headers)["user-agent"] = "";
2501 (*headers)["accept-encoding"] = "gzip,deflate";
2503 // Setup writes/reads to www.google.com
2504 scoped_ptr<SpdyFrame> req(
2505 spdy_util_.ConstructSpdyFrame(kSynStartHeader, headers.Pass()));
2506 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2507 scoped_ptr<SpdyFrame> rep(
2508 spdy_util_.ConstructSpdyPush(NULL,
2512 "http://www.google.com/foo.dat",
2513 "301 Moved Permanently",
2514 "http://www.foo.com/index.php"));
2515 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2516 scoped_ptr<SpdyFrame> rst(
2517 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
2518 MockWrite writes[] = {
2519 CreateMockWrite(*req, 1),
2520 CreateMockWrite(*rst, 6),
2522 MockRead reads[] = {
2523 CreateMockRead(*resp, 2),
2524 CreateMockRead(*rep, 3),
2525 CreateMockRead(*body, 4),
2526 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2527 MockRead(ASYNC, 0, 0, 7) // EOF
2530 // Setup writes/reads to www.foo.com
2531 scoped_ptr<SpdyHeaderBlock> headers2(
2532 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2533 (*headers2)["user-agent"] = "";
2534 (*headers2)["accept-encoding"] = "gzip,deflate";
2535 scoped_ptr<SpdyFrame> req2(
2536 spdy_util_.ConstructSpdyFrame(kSynStartHeader, headers2.Pass()));
2537 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2538 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2539 MockWrite writes2[] = {
2540 CreateMockWrite(*req2, 1),
2542 MockRead reads2[] = {
2543 CreateMockRead(*resp2, 2),
2544 CreateMockRead(*body2, 3),
2545 MockRead(ASYNC, 0, 0, 5) // EOF
2547 OrderedSocketData data(reads, arraysize(reads),
2548 writes, arraysize(writes));
2549 OrderedSocketData data2(reads2, arraysize(reads2),
2550 writes2, arraysize(writes2));
2552 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2553 HttpStreamFactory::set_force_spdy_over_ssl(false);
2554 HttpStreamFactory::set_force_spdy_always(true);
2555 TestDelegate d;
2556 TestDelegate d2;
2557 SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
2559 net::URLRequest r(
2560 GURL("http://www.google.com/"), &d, &spdy_url_request_context);
2561 spdy_url_request_context.socket_factory().
2562 AddSocketDataProvider(&data);
2564 r.Start();
2565 base::RunLoop().Run();
2567 EXPECT_EQ(0, d.received_redirect_count());
2568 std::string contents("hello!");
2569 EXPECT_EQ(contents, d.data_received());
2571 net::URLRequest r2(
2572 GURL("http://www.google.com/foo.dat"), &d2, &spdy_url_request_context);
2573 spdy_url_request_context.socket_factory().
2574 AddSocketDataProvider(&data2);
2576 d2.set_quit_on_redirect(true);
2577 r2.Start();
2578 base::RunLoop().Run();
2579 EXPECT_EQ(1, d2.received_redirect_count());
2581 r2.FollowDeferredRedirect();
2582 base::RunLoop().Run();
2583 EXPECT_EQ(1, d2.response_started_count());
2584 EXPECT_FALSE(d2.received_data_before_response());
2585 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2.status().status());
2586 std::string contents2("hello!");
2587 EXPECT_EQ(contents2, d2.data_received());
2589 data.CompleteRead();
2590 data2.CompleteRead();
2591 EXPECT_TRUE(data.at_read_eof());
2592 EXPECT_TRUE(data.at_write_eof());
2593 EXPECT_TRUE(data2.at_read_eof());
2594 EXPECT_TRUE(data2.at_write_eof());
2597 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
2598 scoped_ptr<SpdyFrame> stream1_syn(
2599 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2600 scoped_ptr<SpdyFrame> stream1_body(
2601 spdy_util_.ConstructSpdyBodyFrame(1, true));
2602 MockWrite writes[] = {
2603 CreateMockWrite(*stream1_syn, 1),
2606 scoped_ptr<SpdyFrame>
2607 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2608 scoped_ptr<SpdyFrame>
2609 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2613 "http://www.google.com/foo.dat"));
2614 const char kPushedData[] = "pushed";
2615 scoped_ptr<SpdyFrame> stream2_body(
2616 spdy_util_.ConstructSpdyBodyFrame(
2617 2, kPushedData, strlen(kPushedData), true));
2618 MockRead reads[] = {
2619 CreateMockRead(*stream1_reply, 2),
2620 CreateMockRead(*stream2_syn, 3),
2621 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2622 CreateMockRead(*stream2_body, 5),
2623 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2626 HttpResponseInfo response;
2627 HttpResponseInfo response2;
2628 std::string expected_push_result("pushed");
2629 OrderedSocketData data(reads, arraysize(reads),
2630 writes, arraysize(writes));
2631 RunServerPushTest(&data,
2632 &response,
2633 &response2,
2634 expected_push_result);
2636 // Verify the SYN_REPLY.
2637 EXPECT_TRUE(response.headers.get() != NULL);
2638 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2640 // Verify the pushed stream.
2641 EXPECT_TRUE(response2.headers.get() != NULL);
2642 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2645 TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
2646 scoped_ptr<SpdyFrame> stream1_syn(
2647 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2648 scoped_ptr<SpdyFrame> stream1_body(
2649 spdy_util_.ConstructSpdyBodyFrame(1, true));
2650 MockWrite writes[] = {
2651 CreateMockWrite(*stream1_syn, 1),
2654 scoped_ptr<SpdyFrame>
2655 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2656 scoped_ptr<SpdyFrame>
2657 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2661 "http://www.google.com/foo.dat"));
2662 const char kPushedData[] = "pushed";
2663 scoped_ptr<SpdyFrame> stream2_body(
2664 spdy_util_.ConstructSpdyBodyFrame(
2665 2, kPushedData, strlen(kPushedData), true));
2666 MockRead reads[] = {
2667 CreateMockRead(*stream2_syn, 2),
2668 CreateMockRead(*stream1_reply, 3),
2669 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2670 CreateMockRead(*stream2_body, 5),
2671 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2674 HttpResponseInfo response;
2675 HttpResponseInfo response2;
2676 std::string expected_push_result("pushed");
2677 OrderedSocketData data(reads, arraysize(reads),
2678 writes, arraysize(writes));
2679 RunServerPushTest(&data,
2680 &response,
2681 &response2,
2682 expected_push_result);
2684 // Verify the SYN_REPLY.
2685 EXPECT_TRUE(response.headers.get() != NULL);
2686 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2688 // Verify the pushed stream.
2689 EXPECT_TRUE(response2.headers.get() != NULL);
2690 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2693 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
2694 scoped_ptr<SpdyFrame> stream1_syn(
2695 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2696 MockWrite writes[] = { CreateMockWrite(*stream1_syn, 1), };
2698 scoped_ptr<SpdyFrame>
2699 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2700 scoped_ptr<SpdyFrame>
2701 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2705 "http://www.google.com/foo.dat"));
2706 const char kPushedData[] = "pushed";
2707 scoped_ptr<SpdyFrame> stream2_body(
2708 spdy_util_.ConstructSpdyBodyFrame(
2709 2, kPushedData, strlen(kPushedData), true));
2710 scoped_ptr<SpdyFrame>
2711 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2712 MockRead reads[] = {
2713 CreateMockRead(*stream1_reply, 2),
2714 CreateMockRead(*stream2_syn, 3),
2715 CreateMockRead(*stream2_body, 4),
2716 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2717 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2720 HttpResponseInfo response;
2721 HttpResponseInfo response2;
2722 std::string expected_push_result("pushed");
2723 OrderedSocketData data(reads, arraysize(reads),
2724 writes, arraysize(writes));
2725 RunServerPushTest(&data,
2726 &response,
2727 &response2,
2728 expected_push_result);
2730 // Verify the SYN_REPLY.
2731 EXPECT_TRUE(response.headers.get() != NULL);
2732 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2734 // Verify the pushed stream.
2735 EXPECT_TRUE(response2.headers.get() != NULL);
2736 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2739 TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
2740 scoped_ptr<SpdyFrame> stream1_syn(
2741 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2742 scoped_ptr<SpdyFrame> stream1_body(
2743 spdy_util_.ConstructSpdyBodyFrame(1, true));
2744 MockWrite writes[] = {
2745 CreateMockWrite(*stream1_syn, 1),
2748 scoped_ptr<SpdyFrame>
2749 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2750 scoped_ptr<SpdyFrame>
2751 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2755 "http://www.google.com/foo.dat"));
2756 scoped_ptr<SpdyFrame> stream2_rst(
2757 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
2758 MockRead reads[] = {
2759 CreateMockRead(*stream1_reply, 2),
2760 CreateMockRead(*stream2_syn, 3),
2761 CreateMockRead(*stream2_rst, 4),
2762 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2763 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2766 OrderedSocketData data(reads, arraysize(reads),
2767 writes, arraysize(writes));
2768 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2769 BoundNetLog(), GetParam(), NULL);
2771 helper.RunPreTestSetup();
2772 helper.AddData(&data);
2774 HttpNetworkTransaction* trans = helper.trans();
2776 // Start the transaction with basic parameters.
2777 TestCompletionCallback callback;
2778 int rv = trans->Start(
2779 &CreateGetRequest(), callback.callback(), BoundNetLog());
2780 EXPECT_EQ(ERR_IO_PENDING, rv);
2781 rv = callback.WaitForResult();
2782 EXPECT_EQ(OK, rv);
2784 // Verify that we consumed all test data.
2785 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
2786 << data.read_count()
2787 << " Read index: "
2788 << data.read_index();
2789 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
2790 << data.write_count()
2791 << " Write index: "
2792 << data.write_index();
2794 // Verify the SYN_REPLY.
2795 HttpResponseInfo response = *trans->GetResponseInfo();
2796 EXPECT_TRUE(response.headers.get() != NULL);
2797 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2800 // Verify that we don't leak streams and that we properly send a reset
2801 // if the server pushes the same stream twice.
2802 TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
2803 scoped_ptr<SpdyFrame> stream1_syn(
2804 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2805 scoped_ptr<SpdyFrame> stream1_body(
2806 spdy_util_.ConstructSpdyBodyFrame(1, true));
2807 scoped_ptr<SpdyFrame> stream3_rst(
2808 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
2809 MockWrite writes[] = {
2810 CreateMockWrite(*stream1_syn, 1),
2811 CreateMockWrite(*stream3_rst, 5),
2814 scoped_ptr<SpdyFrame>
2815 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2816 scoped_ptr<SpdyFrame>
2817 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2821 "http://www.google.com/foo.dat"));
2822 const char kPushedData[] = "pushed";
2823 scoped_ptr<SpdyFrame> stream2_body(
2824 spdy_util_.ConstructSpdyBodyFrame(
2825 2, kPushedData, strlen(kPushedData), true));
2826 scoped_ptr<SpdyFrame>
2827 stream3_syn(spdy_util_.ConstructSpdyPush(NULL,
2831 "http://www.google.com/foo.dat"));
2832 MockRead reads[] = {
2833 CreateMockRead(*stream1_reply, 2),
2834 CreateMockRead(*stream2_syn, 3),
2835 CreateMockRead(*stream3_syn, 4),
2836 CreateMockRead(*stream1_body, 6, SYNCHRONOUS),
2837 CreateMockRead(*stream2_body, 7),
2838 MockRead(ASYNC, ERR_IO_PENDING, 8), // Force a pause
2841 HttpResponseInfo response;
2842 HttpResponseInfo response2;
2843 std::string expected_push_result("pushed");
2844 OrderedSocketData data(reads, arraysize(reads),
2845 writes, arraysize(writes));
2846 RunServerPushTest(&data,
2847 &response,
2848 &response2,
2849 expected_push_result);
2851 // Verify the SYN_REPLY.
2852 EXPECT_TRUE(response.headers.get() != NULL);
2853 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2855 // Verify the pushed stream.
2856 EXPECT_TRUE(response2.headers.get() != NULL);
2857 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2860 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
2861 scoped_ptr<SpdyFrame> stream1_syn(
2862 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2863 scoped_ptr<SpdyFrame> stream1_body(
2864 spdy_util_.ConstructSpdyBodyFrame(1, true));
2865 MockWrite writes[] = {
2866 CreateMockWrite(*stream1_syn, 1),
2869 scoped_ptr<SpdyFrame>
2870 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2871 scoped_ptr<SpdyFrame>
2872 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2876 "http://www.google.com/foo.dat"));
2877 static const char kPushedData[] = "pushed my darling hello my baby";
2878 scoped_ptr<SpdyFrame> stream2_body_base(
2879 spdy_util_.ConstructSpdyBodyFrame(
2880 2, kPushedData, strlen(kPushedData), true));
2881 const size_t kChunkSize = strlen(kPushedData) / 4;
2882 scoped_ptr<SpdyFrame> stream2_body1(
2883 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2884 scoped_ptr<SpdyFrame> stream2_body2(
2885 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2886 scoped_ptr<SpdyFrame> stream2_body3(
2887 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2888 kChunkSize, false));
2889 scoped_ptr<SpdyFrame> stream2_body4(
2890 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2891 stream2_body_base->size() - 3 * kChunkSize, false));
2892 MockRead reads[] = {
2893 CreateMockRead(*stream1_reply, 2),
2894 CreateMockRead(*stream2_syn, 3),
2895 CreateMockRead(*stream2_body1, 4),
2896 CreateMockRead(*stream2_body2, 5),
2897 CreateMockRead(*stream2_body3, 6),
2898 CreateMockRead(*stream2_body4, 7),
2899 CreateMockRead(*stream1_body, 8, SYNCHRONOUS),
2900 MockRead(ASYNC, ERR_IO_PENDING, 9), // Force a pause
2903 HttpResponseInfo response;
2904 HttpResponseInfo response2;
2905 std::string expected_push_result("pushed my darling hello my baby");
2906 OrderedSocketData data(reads, arraysize(reads),
2907 writes, arraysize(writes));
2908 RunServerPushTest(&data, &response, &response2, kPushedData);
2910 // Verify the SYN_REPLY.
2911 EXPECT_TRUE(response.headers.get() != NULL);
2912 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2914 // Verify the pushed stream.
2915 EXPECT_TRUE(response2.headers.get() != NULL);
2916 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2919 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
2920 scoped_ptr<SpdyFrame> stream1_syn(
2921 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2922 scoped_ptr<SpdyFrame> stream1_body(
2923 spdy_util_.ConstructSpdyBodyFrame(1, true));
2924 MockWrite writes[] = {
2925 CreateMockWrite(*stream1_syn, 1),
2928 scoped_ptr<SpdyFrame>
2929 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2930 scoped_ptr<SpdyFrame>
2931 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2935 "http://www.google.com/foo.dat"));
2936 static const char kPushedData[] = "pushed my darling hello my baby";
2937 scoped_ptr<SpdyFrame> stream2_body_base(
2938 spdy_util_.ConstructSpdyBodyFrame(
2939 2, kPushedData, strlen(kPushedData), true));
2940 const size_t kChunkSize = strlen(kPushedData) / 4;
2941 scoped_ptr<SpdyFrame> stream2_body1(
2942 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2943 scoped_ptr<SpdyFrame> stream2_body2(
2944 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2945 scoped_ptr<SpdyFrame> stream2_body3(
2946 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2947 kChunkSize, false));
2948 scoped_ptr<SpdyFrame> stream2_body4(
2949 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2950 stream2_body_base->size() - 3 * kChunkSize, false));
2951 MockRead reads[] = {
2952 CreateMockRead(*stream1_reply, 2),
2953 CreateMockRead(*stream2_syn, 3),
2954 CreateMockRead(*stream2_body1, 4),
2955 CreateMockRead(*stream2_body2, 5),
2956 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2957 CreateMockRead(*stream2_body3, 7),
2958 CreateMockRead(*stream2_body4, 8),
2959 CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS),
2960 MockRead(ASYNC, ERR_IO_PENDING, 10) // Force a pause.
2963 HttpResponseInfo response;
2964 HttpResponseInfo response2;
2965 OrderedSocketData data(reads, arraysize(reads),
2966 writes, arraysize(writes));
2967 RunServerPushTest(&data, &response, &response2, kPushedData);
2969 // Verify the SYN_REPLY.
2970 EXPECT_TRUE(response.headers.get() != NULL);
2971 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2973 // Verify the pushed stream.
2974 EXPECT_TRUE(response2.headers.get() != NULL);
2975 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2978 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
2979 scoped_ptr<SpdyFrame> stream1_syn(
2980 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2981 scoped_ptr<SpdyFrame> stream1_body(
2982 spdy_util_.ConstructSpdyBodyFrame(1, true));
2983 scoped_ptr<SpdyFrame> stream2_rst(
2984 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
2985 MockWrite writes[] = {
2986 CreateMockWrite(*stream1_syn, 1),
2987 CreateMockWrite(*stream2_rst, 4),
2990 scoped_ptr<SpdyFrame>
2991 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2992 scoped_ptr<SpdyFrame>
2993 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2997 "http://www.google.com/foo.dat"));
2998 MockRead reads[] = {
2999 CreateMockRead(*stream1_reply, 2),
3000 CreateMockRead(*stream2_syn, 3),
3001 CreateMockRead(*stream1_body, 4),
3002 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3005 OrderedSocketData data(reads, arraysize(reads),
3006 writes, arraysize(writes));
3007 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3008 BoundNetLog(), GetParam(), NULL);
3010 helper.RunPreTestSetup();
3011 helper.AddData(&data);
3013 HttpNetworkTransaction* trans = helper.trans();
3015 // Start the transaction with basic parameters.
3016 TestCompletionCallback callback;
3017 int rv = trans->Start(
3018 &CreateGetRequest(), callback.callback(), BoundNetLog());
3019 EXPECT_EQ(ERR_IO_PENDING, rv);
3020 rv = callback.WaitForResult();
3021 EXPECT_EQ(OK, rv);
3023 // Verify that we consumed all test data.
3024 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3025 << data.read_count()
3026 << " Read index: "
3027 << data.read_index();
3028 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3029 << data.write_count()
3030 << " Write index: "
3031 << data.write_index();
3033 // Verify the SYN_REPLY.
3034 HttpResponseInfo response = *trans->GetResponseInfo();
3035 EXPECT_TRUE(response.headers.get() != NULL);
3036 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3039 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
3040 scoped_ptr<SpdyFrame> stream1_syn(
3041 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3042 scoped_ptr<SpdyFrame> stream1_body(
3043 spdy_util_.ConstructSpdyBodyFrame(1, true));
3044 scoped_ptr<SpdyFrame> stream2_rst(
3045 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
3046 MockWrite writes[] = {
3047 CreateMockWrite(*stream1_syn, 1),
3048 CreateMockWrite(*stream2_rst, 4),
3051 scoped_ptr<SpdyFrame>
3052 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3053 scoped_ptr<SpdyFrame>
3054 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3058 "http://www.google.com/foo.dat"));
3059 MockRead reads[] = {
3060 CreateMockRead(*stream1_reply, 2),
3061 CreateMockRead(*stream2_syn, 3),
3062 CreateMockRead(*stream1_body, 4),
3063 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
3066 OrderedSocketData data(reads, arraysize(reads),
3067 writes, arraysize(writes));
3068 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3069 BoundNetLog(), GetParam(), NULL);
3071 helper.RunPreTestSetup();
3072 helper.AddData(&data);
3074 HttpNetworkTransaction* trans = helper.trans();
3076 // Start the transaction with basic parameters.
3077 TestCompletionCallback callback;
3078 int rv = trans->Start(
3079 &CreateGetRequest(), callback.callback(), BoundNetLog());
3080 EXPECT_EQ(ERR_IO_PENDING, rv);
3081 rv = callback.WaitForResult();
3082 EXPECT_EQ(OK, rv);
3084 // Verify that we consumed all test data.
3085 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3086 << data.read_count()
3087 << " Read index: "
3088 << data.read_index();
3089 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3090 << data.write_count()
3091 << " Write index: "
3092 << data.write_index();
3094 // Verify the SYN_REPLY.
3095 HttpResponseInfo response = *trans->GetResponseInfo();
3096 EXPECT_TRUE(response.headers.get() != NULL);
3097 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3100 TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
3101 scoped_ptr<SpdyFrame> stream1_syn(
3102 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3103 scoped_ptr<SpdyFrame> stream1_body(
3104 spdy_util_.ConstructSpdyBodyFrame(1, true));
3105 scoped_ptr<SpdyFrame> stream2_rst(
3106 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
3107 MockWrite writes[] = {
3108 CreateMockWrite(*stream1_syn, 1),
3109 CreateMockWrite(*stream2_rst, 4),
3112 scoped_ptr<SpdyFrame>
3113 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3114 scoped_ptr<SpdyHeaderBlock> incomplete_headers(new SpdyHeaderBlock());
3115 (*incomplete_headers)["hello"] = "bye";
3116 (*incomplete_headers)[spdy_util_.GetStatusKey()] = "200 OK";
3117 (*incomplete_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
3118 scoped_ptr<SpdyFrame> stream2_syn(
3119 spdy_util_.ConstructSpdyControlFrame(incomplete_headers.Pass(),
3120 false,
3121 2, // Stream ID
3122 LOWEST,
3123 SYN_STREAM,
3124 CONTROL_FLAG_NONE,
3125 // Associated stream ID
3126 1));
3127 MockRead reads[] = {
3128 CreateMockRead(*stream1_reply, 2),
3129 CreateMockRead(*stream2_syn, 3),
3130 CreateMockRead(*stream1_body, 4),
3131 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3134 OrderedSocketData data(reads, arraysize(reads),
3135 writes, arraysize(writes));
3136 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3137 BoundNetLog(), GetParam(), NULL);
3139 helper.RunPreTestSetup();
3140 helper.AddData(&data);
3142 HttpNetworkTransaction* trans = helper.trans();
3144 // Start the transaction with basic parameters.
3145 TestCompletionCallback callback;
3146 int rv = trans->Start(
3147 &CreateGetRequest(), callback.callback(), BoundNetLog());
3148 EXPECT_EQ(ERR_IO_PENDING, rv);
3149 rv = callback.WaitForResult();
3150 EXPECT_EQ(OK, rv);
3151 // Verify that we consumed all test data.
3152 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3153 << data.read_count()
3154 << " Read index: "
3155 << data.read_index();
3156 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3157 << data.write_count()
3158 << " Write index: "
3159 << data.write_index();
3161 // Verify the SYN_REPLY.
3162 HttpResponseInfo response = *trans->GetResponseInfo();
3163 EXPECT_TRUE(response.headers.get() != NULL);
3164 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3167 // Verify that various SynReply headers parse correctly through the
3168 // HTTP layer.
3169 TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
3170 struct SynReplyHeadersTests {
3171 int num_headers;
3172 const char* extra_headers[5];
3173 SpdyHeaderBlock expected_headers;
3174 } test_cases[] = {
3175 // This uses a multi-valued cookie header.
3176 { 2,
3177 { "cookie", "val1",
3178 "cookie", "val2", // will get appended separated by NULL
3179 NULL
3182 // This is the minimalist set of headers.
3183 { 0,
3184 { NULL },
3186 // Headers with a comma separated list.
3187 { 1,
3188 { "cookie", "val1,val2",
3189 NULL
3194 test_cases[0].expected_headers["cookie"] = "val1";
3195 test_cases[0].expected_headers["cookie"] += '\0';
3196 test_cases[0].expected_headers["cookie"] += "val2";
3197 test_cases[0].expected_headers["hello"] = "bye";
3198 test_cases[0].expected_headers["status"] = "200";
3199 test_cases[0].expected_headers["version"] = "HTTP/1.1";
3201 test_cases[1].expected_headers["hello"] = "bye";
3202 test_cases[1].expected_headers["status"] = "200";
3203 test_cases[1].expected_headers["version"] = "HTTP/1.1";
3205 test_cases[2].expected_headers["cookie"] = "val1,val2";
3206 test_cases[2].expected_headers["hello"] = "bye";
3207 test_cases[2].expected_headers["status"] = "200";
3208 test_cases[2].expected_headers["version"] = "HTTP/1.1";
3210 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3211 scoped_ptr<SpdyFrame> req(
3212 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3213 MockWrite writes[] = { CreateMockWrite(*req) };
3215 scoped_ptr<SpdyFrame> resp(
3216 spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
3217 test_cases[i].num_headers,
3218 1));
3219 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3220 MockRead reads[] = {
3221 CreateMockRead(*resp),
3222 CreateMockRead(*body),
3223 MockRead(ASYNC, 0, 0) // EOF
3226 DelayedSocketData data(1, reads, arraysize(reads),
3227 writes, arraysize(writes));
3228 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3229 BoundNetLog(), GetParam(), NULL);
3230 helper.RunToCompletion(&data);
3231 TransactionHelperResult out = helper.output();
3233 EXPECT_EQ(OK, out.rv);
3234 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3235 EXPECT_EQ("hello!", out.response_data);
3237 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3238 EXPECT_TRUE(headers.get() != NULL);
3239 void* iter = NULL;
3240 std::string name, value;
3241 SpdyHeaderBlock header_block;
3242 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3243 if (header_block[name].empty()) {
3244 header_block[name] = value;
3245 } else {
3246 header_block[name] += '\0';
3247 header_block[name] += value;
3250 EXPECT_EQ(test_cases[i].expected_headers, header_block);
3254 // Verify that various SynReply headers parse vary fields correctly
3255 // through the HTTP layer, and the response matches the request.
3256 TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
3257 static const SpdyHeaderInfo syn_reply_info = {
3258 SYN_REPLY, // Syn Reply
3259 1, // Stream ID
3260 0, // Associated Stream ID
3261 ConvertRequestPriorityToSpdyPriority(
3262 LOWEST, spdy_util_.spdy_version()),
3263 kSpdyCredentialSlotUnused,
3264 CONTROL_FLAG_NONE, // Control Flags
3265 false, // Compressed
3266 RST_STREAM_INVALID, // Status
3267 NULL, // Data
3268 0, // Data Length
3269 DATA_FLAG_NONE // Data Flags
3271 // Modify the following data to change/add test cases:
3272 struct SynReplyTests {
3273 const SpdyHeaderInfo* syn_reply;
3274 bool vary_matches;
3275 int num_headers[2];
3276 const char* extra_headers[2][16];
3277 } test_cases[] = {
3278 // Test the case of a multi-valued cookie. When the value is delimited
3279 // with NUL characters, it needs to be unfolded into multiple headers.
3281 &syn_reply_info,
3282 true,
3283 { 1, 4 },
3284 { { "cookie", "val1,val2",
3285 NULL
3287 { "vary", "cookie",
3288 spdy_util_.GetStatusKey(), "200",
3289 spdy_util_.GetPathKey(), "/index.php",
3290 spdy_util_.GetVersionKey(), "HTTP/1.1",
3291 NULL
3294 }, { // Multiple vary fields.
3295 &syn_reply_info,
3296 true,
3297 { 2, 5 },
3298 { { "friend", "barney",
3299 "enemy", "snaggletooth",
3300 NULL
3302 { "vary", "friend",
3303 "vary", "enemy",
3304 spdy_util_.GetStatusKey(), "200",
3305 spdy_util_.GetPathKey(), "/index.php",
3306 spdy_util_.GetVersionKey(), "HTTP/1.1",
3307 NULL
3310 }, { // Test a '*' vary field.
3311 &syn_reply_info,
3312 false,
3313 { 1, 4 },
3314 { { "cookie", "val1,val2",
3315 NULL
3317 { "vary", "*",
3318 spdy_util_.GetStatusKey(), "200",
3319 spdy_util_.GetPathKey(), "/index.php",
3320 spdy_util_.GetVersionKey(), "HTTP/1.1",
3321 NULL
3324 }, { // Multiple comma-separated vary fields.
3325 &syn_reply_info,
3326 true,
3327 { 2, 4 },
3328 { { "friend", "barney",
3329 "enemy", "snaggletooth",
3330 NULL
3332 { "vary", "friend,enemy",
3333 spdy_util_.GetStatusKey(), "200",
3334 spdy_util_.GetPathKey(), "/index.php",
3335 spdy_util_.GetVersionKey(), "HTTP/1.1",
3336 NULL
3342 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3343 // Construct the request.
3344 scoped_ptr<SpdyFrame> frame_req(
3345 spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
3346 test_cases[i].num_headers[0],
3347 false, 1, LOWEST, true));
3349 MockWrite writes[] = {
3350 CreateMockWrite(*frame_req),
3353 // Construct the reply.
3354 scoped_ptr<SpdyFrame> frame_reply(
3355 spdy_util_.ConstructSpdyFrame(*test_cases[i].syn_reply,
3356 test_cases[i].extra_headers[1],
3357 test_cases[i].num_headers[1],
3358 NULL,
3359 0));
3361 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3362 MockRead reads[] = {
3363 CreateMockRead(*frame_reply),
3364 CreateMockRead(*body),
3365 MockRead(ASYNC, 0, 0) // EOF
3368 // Attach the headers to the request.
3369 int header_count = test_cases[i].num_headers[0];
3371 HttpRequestInfo request = CreateGetRequest();
3372 for (int ct = 0; ct < header_count; ct++) {
3373 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3374 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3375 request.extra_headers.SetHeader(header_key, header_value);
3378 DelayedSocketData data(1, reads, arraysize(reads),
3379 writes, arraysize(writes));
3380 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
3381 BoundNetLog(), GetParam(), NULL);
3382 helper.RunToCompletion(&data);
3383 TransactionHelperResult out = helper.output();
3385 EXPECT_EQ(OK, out.rv) << i;
3386 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
3387 EXPECT_EQ("hello!", out.response_data) << i;
3389 // Test the response information.
3390 EXPECT_TRUE(out.response_info.response_time >
3391 out.response_info.request_time) << i;
3392 base::TimeDelta test_delay = out.response_info.response_time -
3393 out.response_info.request_time;
3394 base::TimeDelta min_expected_delay;
3395 min_expected_delay.FromMilliseconds(10);
3396 EXPECT_GT(test_delay.InMillisecondsF(),
3397 min_expected_delay.InMillisecondsF()) << i;
3398 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3399 test_cases[i].vary_matches) << i;
3401 // Check the headers.
3402 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3403 ASSERT_TRUE(headers.get() != NULL) << i;
3404 void* iter = NULL;
3405 std::string name, value, lines;
3406 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3407 lines.append(name);
3408 lines.append(": ");
3409 lines.append(value);
3410 lines.append("\n");
3413 // Construct the expected header reply string.
3414 SpdyHeaderBlock reply_headers;
3415 AppendToHeaderBlock(test_cases[i].extra_headers[1],
3416 test_cases[i].num_headers[1],
3417 &reply_headers);
3418 std::string expected_reply =
3419 spdy_util_.ConstructSpdyReplyString(reply_headers);
3420 EXPECT_EQ(expected_reply, lines) << i;
3424 // Verify that we don't crash on invalid SynReply responses.
3425 TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
3426 const SpdyHeaderInfo kSynStartHeader = {
3427 SYN_REPLY, // Kind = SynReply
3428 1, // Stream ID
3429 0, // Associated stream ID
3430 ConvertRequestPriorityToSpdyPriority(
3431 LOWEST, spdy_util_.spdy_version()),
3432 kSpdyCredentialSlotUnused,
3433 CONTROL_FLAG_NONE, // Control Flags
3434 false, // Compressed
3435 RST_STREAM_INVALID, // Status
3436 NULL, // Data
3437 0, // Length
3438 DATA_FLAG_NONE // Data Flags
3441 struct InvalidSynReplyTests {
3442 int num_headers;
3443 const char* headers[10];
3444 } test_cases[] = {
3445 // SYN_REPLY missing status header
3446 { 4,
3447 { "cookie", "val1",
3448 "cookie", "val2",
3449 spdy_util_.GetPathKey(), "/index.php",
3450 spdy_util_.GetVersionKey(), "HTTP/1.1",
3451 NULL
3454 // SYN_REPLY missing version header
3455 { 2,
3456 { "status", "200",
3457 spdy_util_.GetPathKey(), "/index.php",
3458 NULL
3461 // SYN_REPLY with no headers
3462 { 0, { NULL }, },
3465 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3466 scoped_ptr<SpdyFrame> req(
3467 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3468 scoped_ptr<SpdyFrame> rst(
3469 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3470 MockWrite writes[] = {
3471 CreateMockWrite(*req),
3472 CreateMockWrite(*rst),
3475 scoped_ptr<SpdyFrame> resp(
3476 spdy_util_.ConstructSpdyFrame(kSynStartHeader,
3477 NULL, 0,
3478 test_cases[i].headers,
3479 test_cases[i].num_headers));
3480 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3481 MockRead reads[] = {
3482 CreateMockRead(*resp),
3483 MockRead(ASYNC, 0, 0) // EOF
3486 DelayedSocketData data(1, reads, arraysize(reads),
3487 writes, arraysize(writes));
3488 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3489 BoundNetLog(), GetParam(), NULL);
3490 helper.RunToCompletion(&data);
3491 TransactionHelperResult out = helper.output();
3492 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3496 // Verify that we don't crash on some corrupt frames.
3497 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
3498 // This is the length field that's too short.
3499 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3500 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3501 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3502 size_t right_size =
3503 (spdy_util_.spdy_version() < SPDY4) ?
3504 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize() :
3505 syn_reply_wrong_length->size();
3506 size_t wrong_size = right_size - 4;
3507 test::SetFrameLength(syn_reply_wrong_length.get(),
3508 wrong_size,
3509 spdy_util_.spdy_version());
3511 struct SynReplyTests {
3512 const SpdyFrame* syn_reply;
3513 } test_cases[] = {
3514 { syn_reply_wrong_length.get(), },
3517 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3518 scoped_ptr<SpdyFrame> req(
3519 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3520 scoped_ptr<SpdyFrame> rst(
3521 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3522 MockWrite writes[] = {
3523 CreateMockWrite(*req),
3524 CreateMockWrite(*rst),
3527 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3528 MockRead reads[] = {
3529 MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size),
3530 CreateMockRead(*body),
3531 MockRead(ASYNC, 0, 0) // EOF
3534 DelayedSocketData data(1, reads, arraysize(reads),
3535 writes, arraysize(writes));
3536 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3537 BoundNetLog(), GetParam(), NULL);
3538 helper.RunToCompletion(&data);
3539 TransactionHelperResult out = helper.output();
3540 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3544 // Test that we shutdown correctly on write errors.
3545 TEST_P(SpdyNetworkTransactionTest, WriteError) {
3546 scoped_ptr<SpdyFrame> req(
3547 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3548 MockWrite writes[] = {
3549 // We'll write 10 bytes successfully
3550 MockWrite(ASYNC, req->data(), 10),
3551 // Followed by ERROR!
3552 MockWrite(ASYNC, ERR_FAILED),
3555 DelayedSocketData data(2, NULL, 0,
3556 writes, arraysize(writes));
3557 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3558 BoundNetLog(), GetParam(), NULL);
3559 helper.RunToCompletion(&data);
3560 TransactionHelperResult out = helper.output();
3561 EXPECT_EQ(ERR_FAILED, out.rv);
3562 data.Reset();
3565 // Test that partial writes work.
3566 TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
3567 // Chop the SYN_STREAM frame into 5 chunks.
3568 scoped_ptr<SpdyFrame> req(
3569 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3570 const int kChunks = 5;
3571 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
3573 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3574 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3575 MockRead reads[] = {
3576 CreateMockRead(*resp),
3577 CreateMockRead(*body),
3578 MockRead(ASYNC, 0, 0) // EOF
3581 DelayedSocketData data(kChunks, reads, arraysize(reads),
3582 writes.get(), kChunks);
3583 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3584 BoundNetLog(), GetParam(), NULL);
3585 helper.RunToCompletion(&data);
3586 TransactionHelperResult out = helper.output();
3587 EXPECT_EQ(OK, out.rv);
3588 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3589 EXPECT_EQ("hello!", out.response_data);
3592 // In this test, we enable compression, but get a uncompressed SynReply from
3593 // the server. Verify that teardown is all clean.
3594 TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
3595 scoped_ptr<SpdyFrame> compressed(
3596 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
3597 scoped_ptr<SpdyFrame> rst(
3598 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3599 MockWrite writes[] = {
3600 CreateMockWrite(*compressed),
3603 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3604 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3605 MockRead reads[] = {
3606 CreateMockRead(*resp),
3609 DelayedSocketData data(1, reads, arraysize(reads),
3610 writes, arraysize(writes));
3611 SpdySessionDependencies* session_deps =
3612 CreateSpdySessionDependencies(GetParam());
3613 session_deps->enable_compression = true;
3614 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3615 BoundNetLog(), GetParam(), session_deps);
3616 helper.RunToCompletion(&data);
3617 TransactionHelperResult out = helper.output();
3618 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3619 data.Reset();
3622 // Test that the NetLog contains good data for a simple GET request.
3623 TEST_P(SpdyNetworkTransactionTest, NetLog) {
3624 static const char* const kExtraHeaders[] = {
3625 "user-agent", "Chrome",
3627 scoped_ptr<SpdyFrame> req(
3628 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
3629 MockWrite writes[] = { CreateMockWrite(*req) };
3631 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3632 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3633 MockRead reads[] = {
3634 CreateMockRead(*resp),
3635 CreateMockRead(*body),
3636 MockRead(ASYNC, 0, 0) // EOF
3639 CapturingBoundNetLog log;
3641 DelayedSocketData data(1, reads, arraysize(reads),
3642 writes, arraysize(writes));
3643 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
3644 DEFAULT_PRIORITY,
3645 log.bound(), GetParam(), NULL);
3646 helper.RunToCompletion(&data);
3647 TransactionHelperResult out = helper.output();
3648 EXPECT_EQ(OK, out.rv);
3649 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3650 EXPECT_EQ("hello!", out.response_data);
3652 // Check that the NetLog was filled reasonably.
3653 // This test is intentionally non-specific about the exact ordering of the
3654 // log; instead we just check to make sure that certain events exist, and that
3655 // they are in the right order.
3656 net::CapturingNetLog::CapturedEntryList entries;
3657 log.GetEntries(&entries);
3659 EXPECT_LT(0u, entries.size());
3660 int pos = 0;
3661 pos = net::ExpectLogContainsSomewhere(entries, 0,
3662 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3663 net::NetLog::PHASE_BEGIN);
3664 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3665 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3666 net::NetLog::PHASE_END);
3667 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3668 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3669 net::NetLog::PHASE_BEGIN);
3670 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3671 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3672 net::NetLog::PHASE_END);
3673 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3674 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3675 net::NetLog::PHASE_BEGIN);
3676 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3677 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3678 net::NetLog::PHASE_END);
3680 // Check that we logged all the headers correctly
3681 pos = net::ExpectLogContainsSomewhere(
3682 entries, 0,
3683 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
3684 net::NetLog::PHASE_NONE);
3686 base::ListValue* header_list;
3687 ASSERT_TRUE(entries[pos].params.get());
3688 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3690 std::vector<std::string> expected;
3691 expected.push_back(std::string(spdy_util_.GetHostKey()) + ": www.google.com");
3692 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
3693 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": http");
3694 expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
3695 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
3696 expected.push_back("user-agent: Chrome");
3697 EXPECT_EQ(expected.size(), header_list->GetSize());
3698 for (std::vector<std::string>::const_iterator it = expected.begin();
3699 it != expected.end();
3700 ++it) {
3701 base::StringValue header(*it);
3702 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3703 "Header not found: " << *it;
3707 // Since we buffer the IO from the stream to the renderer, this test verifies
3708 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3709 // on the network, but issued a Read for only 5 of those bytes) that the data
3710 // flow still works correctly.
3711 TEST_P(SpdyNetworkTransactionTest, BufferFull) {
3712 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3714 scoped_ptr<SpdyFrame> req(
3715 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3716 MockWrite writes[] = { CreateMockWrite(*req) };
3718 // 2 data frames in a single read.
3719 scoped_ptr<SpdyFrame> data_frame_1(
3720 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
3721 scoped_ptr<SpdyFrame> data_frame_2(
3722 framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
3723 const SpdyFrame* data_frames[2] = {
3724 data_frame_1.get(),
3725 data_frame_2.get(),
3727 char combined_data_frames[100];
3728 int combined_data_frames_len =
3729 CombineFrames(data_frames, arraysize(data_frames),
3730 combined_data_frames, arraysize(combined_data_frames));
3731 scoped_ptr<SpdyFrame> last_frame(
3732 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
3734 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3735 MockRead reads[] = {
3736 CreateMockRead(*resp),
3737 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3738 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3739 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3740 CreateMockRead(*last_frame),
3741 MockRead(ASYNC, 0, 0) // EOF
3744 DelayedSocketData data(1, reads, arraysize(reads),
3745 writes, arraysize(writes));
3747 TestCompletionCallback callback;
3749 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3750 BoundNetLog(), GetParam(), NULL);
3751 helper.RunPreTestSetup();
3752 helper.AddData(&data);
3753 HttpNetworkTransaction* trans = helper.trans();
3754 int rv = trans->Start(
3755 &CreateGetRequest(), callback.callback(), BoundNetLog());
3756 EXPECT_EQ(ERR_IO_PENDING, rv);
3758 TransactionHelperResult out = helper.output();
3759 out.rv = callback.WaitForResult();
3760 EXPECT_EQ(out.rv, OK);
3762 const HttpResponseInfo* response = trans->GetResponseInfo();
3763 EXPECT_TRUE(response->headers.get() != NULL);
3764 EXPECT_TRUE(response->was_fetched_via_spdy);
3765 out.status_line = response->headers->GetStatusLine();
3766 out.response_info = *response; // Make a copy so we can verify.
3768 // Read Data
3769 TestCompletionCallback read_callback;
3771 std::string content;
3772 do {
3773 // Read small chunks at a time.
3774 const int kSmallReadSize = 3;
3775 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3776 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3777 if (rv == net::ERR_IO_PENDING) {
3778 data.CompleteRead();
3779 rv = read_callback.WaitForResult();
3781 if (rv > 0) {
3782 content.append(buf->data(), rv);
3783 } else if (rv < 0) {
3784 NOTREACHED();
3786 } while (rv > 0);
3788 out.response_data.swap(content);
3790 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3791 // MockClientSocketFactory) are still alive.
3792 base::RunLoop().RunUntilIdle();
3794 // Verify that we consumed all test data.
3795 helper.VerifyDataConsumed();
3797 EXPECT_EQ(OK, out.rv);
3798 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3799 EXPECT_EQ("goodbye world", out.response_data);
3802 // Verify that basic buffering works; when multiple data frames arrive
3803 // at the same time, ensure that we don't notify a read completion for
3804 // each data frame individually.
3805 TEST_P(SpdyNetworkTransactionTest, Buffering) {
3806 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3808 scoped_ptr<SpdyFrame> req(
3809 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3810 MockWrite writes[] = { CreateMockWrite(*req) };
3812 // 4 data frames in a single read.
3813 scoped_ptr<SpdyFrame> data_frame(
3814 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3815 scoped_ptr<SpdyFrame> data_frame_fin(
3816 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3817 const SpdyFrame* data_frames[4] = {
3818 data_frame.get(),
3819 data_frame.get(),
3820 data_frame.get(),
3821 data_frame_fin.get()
3823 char combined_data_frames[100];
3824 int combined_data_frames_len =
3825 CombineFrames(data_frames, arraysize(data_frames),
3826 combined_data_frames, arraysize(combined_data_frames));
3828 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3829 MockRead reads[] = {
3830 CreateMockRead(*resp),
3831 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3832 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3833 MockRead(ASYNC, 0, 0) // EOF
3836 DelayedSocketData data(1, reads, arraysize(reads),
3837 writes, arraysize(writes));
3839 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3840 BoundNetLog(), GetParam(), NULL);
3841 helper.RunPreTestSetup();
3842 helper.AddData(&data);
3843 HttpNetworkTransaction* trans = helper.trans();
3845 TestCompletionCallback callback;
3846 int rv = trans->Start(
3847 &CreateGetRequest(), callback.callback(), BoundNetLog());
3848 EXPECT_EQ(ERR_IO_PENDING, rv);
3850 TransactionHelperResult out = helper.output();
3851 out.rv = callback.WaitForResult();
3852 EXPECT_EQ(out.rv, OK);
3854 const HttpResponseInfo* response = trans->GetResponseInfo();
3855 EXPECT_TRUE(response->headers.get() != NULL);
3856 EXPECT_TRUE(response->was_fetched_via_spdy);
3857 out.status_line = response->headers->GetStatusLine();
3858 out.response_info = *response; // Make a copy so we can verify.
3860 // Read Data
3861 TestCompletionCallback read_callback;
3863 std::string content;
3864 int reads_completed = 0;
3865 do {
3866 // Read small chunks at a time.
3867 const int kSmallReadSize = 14;
3868 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3869 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3870 if (rv == net::ERR_IO_PENDING) {
3871 data.CompleteRead();
3872 rv = read_callback.WaitForResult();
3874 if (rv > 0) {
3875 EXPECT_EQ(kSmallReadSize, rv);
3876 content.append(buf->data(), rv);
3877 } else if (rv < 0) {
3878 FAIL() << "Unexpected read error: " << rv;
3880 reads_completed++;
3881 } while (rv > 0);
3883 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3885 out.response_data.swap(content);
3887 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3888 // MockClientSocketFactory) are still alive.
3889 base::RunLoop().RunUntilIdle();
3891 // Verify that we consumed all test data.
3892 helper.VerifyDataConsumed();
3894 EXPECT_EQ(OK, out.rv);
3895 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3896 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3899 // Verify the case where we buffer data but read it after it has been buffered.
3900 TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
3901 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3903 scoped_ptr<SpdyFrame> req(
3904 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3905 MockWrite writes[] = { CreateMockWrite(*req) };
3907 // 5 data frames in a single read.
3908 scoped_ptr<SpdyFrame> syn_reply(
3909 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3910 // turn off FIN bit
3911 test::SetFrameFlags(
3912 syn_reply.get(), CONTROL_FLAG_NONE, spdy_util_.spdy_version());
3913 scoped_ptr<SpdyFrame> data_frame(
3914 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3915 scoped_ptr<SpdyFrame> data_frame_fin(
3916 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3917 const SpdyFrame* frames[5] = {
3918 syn_reply.get(),
3919 data_frame.get(),
3920 data_frame.get(),
3921 data_frame.get(),
3922 data_frame_fin.get()
3924 char combined_frames[200];
3925 int combined_frames_len =
3926 CombineFrames(frames, arraysize(frames),
3927 combined_frames, arraysize(combined_frames));
3929 MockRead reads[] = {
3930 MockRead(ASYNC, combined_frames, combined_frames_len),
3931 MockRead(ASYNC, 0, 0) // EOF
3934 DelayedSocketData data(1, reads, arraysize(reads),
3935 writes, arraysize(writes));
3937 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3938 BoundNetLog(), GetParam(), NULL);
3939 helper.RunPreTestSetup();
3940 helper.AddData(&data);
3941 HttpNetworkTransaction* trans = helper.trans();
3943 TestCompletionCallback callback;
3944 int rv = trans->Start(
3945 &CreateGetRequest(), callback.callback(), BoundNetLog());
3946 EXPECT_EQ(ERR_IO_PENDING, rv);
3948 TransactionHelperResult out = helper.output();
3949 out.rv = callback.WaitForResult();
3950 EXPECT_EQ(out.rv, OK);
3952 const HttpResponseInfo* response = trans->GetResponseInfo();
3953 EXPECT_TRUE(response->headers.get() != NULL);
3954 EXPECT_TRUE(response->was_fetched_via_spdy);
3955 out.status_line = response->headers->GetStatusLine();
3956 out.response_info = *response; // Make a copy so we can verify.
3958 // Read Data
3959 TestCompletionCallback read_callback;
3961 std::string content;
3962 int reads_completed = 0;
3963 do {
3964 // Read small chunks at a time.
3965 const int kSmallReadSize = 14;
3966 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3967 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3968 if (rv > 0) {
3969 EXPECT_EQ(kSmallReadSize, rv);
3970 content.append(buf->data(), rv);
3971 } else if (rv < 0) {
3972 FAIL() << "Unexpected read error: " << rv;
3974 reads_completed++;
3975 } while (rv > 0);
3977 EXPECT_EQ(3, reads_completed);
3979 out.response_data.swap(content);
3981 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3982 // MockClientSocketFactory) are still alive.
3983 base::RunLoop().RunUntilIdle();
3985 // Verify that we consumed all test data.
3986 helper.VerifyDataConsumed();
3988 EXPECT_EQ(OK, out.rv);
3989 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3990 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3993 // Verify the case where we buffer data and close the connection.
3994 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
3995 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3997 scoped_ptr<SpdyFrame> req(
3998 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3999 MockWrite writes[] = { CreateMockWrite(*req) };
4001 // All data frames in a single read.
4002 // NOTE: We don't FIN the stream.
4003 scoped_ptr<SpdyFrame> data_frame(
4004 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4005 const SpdyFrame* data_frames[4] = {
4006 data_frame.get(),
4007 data_frame.get(),
4008 data_frame.get(),
4009 data_frame.get()
4011 char combined_data_frames[100];
4012 int combined_data_frames_len =
4013 CombineFrames(data_frames, arraysize(data_frames),
4014 combined_data_frames, arraysize(combined_data_frames));
4015 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4016 MockRead reads[] = {
4017 CreateMockRead(*resp),
4018 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4019 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4020 MockRead(ASYNC, 0, 0) // EOF
4023 DelayedSocketData data(1, reads, arraysize(reads),
4024 writes, arraysize(writes));
4026 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4027 BoundNetLog(), GetParam(), NULL);
4028 helper.RunPreTestSetup();
4029 helper.AddData(&data);
4030 HttpNetworkTransaction* trans = helper.trans();
4032 TestCompletionCallback callback;
4034 int rv = trans->Start(
4035 &CreateGetRequest(), callback.callback(), BoundNetLog());
4036 EXPECT_EQ(ERR_IO_PENDING, rv);
4038 TransactionHelperResult out = helper.output();
4039 out.rv = callback.WaitForResult();
4040 EXPECT_EQ(out.rv, OK);
4042 const HttpResponseInfo* response = trans->GetResponseInfo();
4043 EXPECT_TRUE(response->headers.get() != NULL);
4044 EXPECT_TRUE(response->was_fetched_via_spdy);
4045 out.status_line = response->headers->GetStatusLine();
4046 out.response_info = *response; // Make a copy so we can verify.
4048 // Read Data
4049 TestCompletionCallback read_callback;
4051 std::string content;
4052 int reads_completed = 0;
4053 do {
4054 // Read small chunks at a time.
4055 const int kSmallReadSize = 14;
4056 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4057 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4058 if (rv == net::ERR_IO_PENDING) {
4059 data.CompleteRead();
4060 rv = read_callback.WaitForResult();
4062 if (rv > 0) {
4063 content.append(buf->data(), rv);
4064 } else if (rv < 0) {
4065 // This test intentionally closes the connection, and will get an error.
4066 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
4067 break;
4069 reads_completed++;
4070 } while (rv > 0);
4072 EXPECT_EQ(0, reads_completed);
4074 out.response_data.swap(content);
4076 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4077 // MockClientSocketFactory) are still alive.
4078 base::RunLoop().RunUntilIdle();
4080 // Verify that we consumed all test data.
4081 helper.VerifyDataConsumed();
4084 // Verify the case where we buffer data and cancel the transaction.
4085 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
4086 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4088 scoped_ptr<SpdyFrame> req(
4089 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4090 MockWrite writes[] = { CreateMockWrite(*req) };
4092 // NOTE: We don't FIN the stream.
4093 scoped_ptr<SpdyFrame> data_frame(
4094 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4096 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4097 MockRead reads[] = {
4098 CreateMockRead(*resp),
4099 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4100 CreateMockRead(*data_frame),
4101 MockRead(ASYNC, 0, 0) // EOF
4104 DelayedSocketData data(1, reads, arraysize(reads),
4105 writes, arraysize(writes));
4107 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4108 BoundNetLog(), GetParam(), NULL);
4109 helper.RunPreTestSetup();
4110 helper.AddData(&data);
4111 HttpNetworkTransaction* trans = helper.trans();
4112 TestCompletionCallback callback;
4114 int rv = trans->Start(
4115 &CreateGetRequest(), callback.callback(), BoundNetLog());
4116 EXPECT_EQ(ERR_IO_PENDING, rv);
4118 TransactionHelperResult out = helper.output();
4119 out.rv = callback.WaitForResult();
4120 EXPECT_EQ(out.rv, OK);
4122 const HttpResponseInfo* response = trans->GetResponseInfo();
4123 EXPECT_TRUE(response->headers.get() != NULL);
4124 EXPECT_TRUE(response->was_fetched_via_spdy);
4125 out.status_line = response->headers->GetStatusLine();
4126 out.response_info = *response; // Make a copy so we can verify.
4128 // Read Data
4129 TestCompletionCallback read_callback;
4131 do {
4132 const int kReadSize = 256;
4133 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
4134 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
4135 if (rv == net::ERR_IO_PENDING) {
4136 // Complete the read now, which causes buffering to start.
4137 data.CompleteRead();
4138 // Destroy the transaction, causing the stream to get cancelled
4139 // and orphaning the buffered IO task.
4140 helper.ResetTrans();
4141 break;
4143 // We shouldn't get here in this test.
4144 FAIL() << "Unexpected read: " << rv;
4145 } while (rv > 0);
4147 // Flush the MessageLoop; this will cause the buffered IO task
4148 // to run for the final time.
4149 base::RunLoop().RunUntilIdle();
4151 // Verify that we consumed all test data.
4152 helper.VerifyDataConsumed();
4155 // Test that if the server requests persistence of settings, that we save
4156 // the settings in the HttpServerProperties.
4157 TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
4158 static const SpdyHeaderInfo kSynReplyInfo = {
4159 SYN_REPLY, // Syn Reply
4160 1, // Stream ID
4161 0, // Associated Stream ID
4162 ConvertRequestPriorityToSpdyPriority(
4163 LOWEST, spdy_util_.spdy_version()),
4164 kSpdyCredentialSlotUnused,
4165 CONTROL_FLAG_NONE, // Control Flags
4166 false, // Compressed
4167 RST_STREAM_INVALID, // Status
4168 NULL, // Data
4169 0, // Data Length
4170 DATA_FLAG_NONE // Data Flags
4173 BoundNetLog net_log;
4174 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4175 net_log, GetParam(), NULL);
4176 helper.RunPreTestSetup();
4178 // Verify that no settings exist initially.
4179 HostPortPair host_port_pair("www.google.com", helper.port());
4180 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4181 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4182 host_port_pair).empty());
4184 // Construct the request.
4185 scoped_ptr<SpdyFrame> req(
4186 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4187 MockWrite writes[] = { CreateMockWrite(*req) };
4189 // Construct the reply.
4190 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4191 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4192 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4193 scoped_ptr<SpdyFrame> reply(
4194 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4196 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
4197 unsigned int kSampleValue1 = 0x0a0a0a0a;
4198 const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
4199 unsigned int kSampleValue2 = 0x0b0b0b0b;
4200 const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
4201 unsigned int kSampleValue3 = 0x0c0c0c0c;
4202 scoped_ptr<SpdyFrame> settings_frame;
4204 // Construct the SETTINGS frame.
4205 SettingsMap settings;
4206 // First add a persisted setting.
4207 settings[kSampleId1] =
4208 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
4209 // Next add a non-persisted setting.
4210 settings[kSampleId2] =
4211 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
4212 // Next add another persisted setting.
4213 settings[kSampleId3] =
4214 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
4215 settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
4218 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4219 MockRead reads[] = {
4220 CreateMockRead(*reply),
4221 CreateMockRead(*body),
4222 CreateMockRead(*settings_frame),
4223 MockRead(ASYNC, 0, 0) // EOF
4226 DelayedSocketData data(1, reads, arraysize(reads),
4227 writes, arraysize(writes));
4228 helper.AddData(&data);
4229 helper.RunDefaultTest();
4230 helper.VerifyDataConsumed();
4231 TransactionHelperResult out = helper.output();
4232 EXPECT_EQ(OK, out.rv);
4233 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4234 EXPECT_EQ("hello!", out.response_data);
4237 // Verify we had two persisted settings.
4238 const SettingsMap& settings_map =
4239 spdy_session_pool->http_server_properties()->GetSpdySettings(
4240 host_port_pair);
4241 ASSERT_EQ(2u, settings_map.size());
4243 // Verify the first persisted setting.
4244 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4245 EXPECT_TRUE(it1 != settings_map.end());
4246 SettingsFlagsAndValue flags_and_value1 = it1->second;
4247 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4248 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4250 // Verify the second persisted setting.
4251 SettingsMap::const_iterator it3 = settings_map.find(kSampleId3);
4252 EXPECT_TRUE(it3 != settings_map.end());
4253 SettingsFlagsAndValue flags_and_value3 = it3->second;
4254 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first);
4255 EXPECT_EQ(kSampleValue3, flags_and_value3.second);
4259 // Test that when there are settings saved that they are sent back to the
4260 // server upon session establishment.
4261 TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
4262 static const SpdyHeaderInfo kSynReplyInfo = {
4263 SYN_REPLY, // Syn Reply
4264 1, // Stream ID
4265 0, // Associated Stream ID
4266 ConvertRequestPriorityToSpdyPriority(
4267 LOWEST, spdy_util_.spdy_version()),
4268 kSpdyCredentialSlotUnused,
4269 CONTROL_FLAG_NONE, // Control Flags
4270 false, // Compressed
4271 RST_STREAM_INVALID, // Status
4272 NULL, // Data
4273 0, // Data Length
4274 DATA_FLAG_NONE // Data Flags
4277 BoundNetLog net_log;
4278 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4279 net_log, GetParam(), NULL);
4280 helper.RunPreTestSetup();
4282 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4284 SpdySessionPoolPeer pool_peer(spdy_session_pool);
4285 pool_peer.SetEnableSendingInitialData(true);
4287 // Verify that no settings exist initially.
4288 HostPortPair host_port_pair("www.google.com", helper.port());
4289 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4290 host_port_pair).empty());
4292 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
4293 unsigned int kSampleValue1 = 0x0a0a0a0a;
4294 const SpdySettingsIds kSampleId2 = SETTINGS_ROUND_TRIP_TIME;
4295 unsigned int kSampleValue2 = 0x0c0c0c0c;
4297 // First add a persisted setting.
4298 spdy_session_pool->http_server_properties()->SetSpdySetting(
4299 host_port_pair,
4300 kSampleId1,
4301 SETTINGS_FLAG_PLEASE_PERSIST,
4302 kSampleValue1);
4304 // Next add another persisted setting.
4305 spdy_session_pool->http_server_properties()->SetSpdySetting(
4306 host_port_pair,
4307 kSampleId2,
4308 SETTINGS_FLAG_PLEASE_PERSIST,
4309 kSampleValue2);
4311 EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4312 host_port_pair).size());
4314 // Construct the initial SETTINGS frame.
4315 SettingsMap initial_settings;
4316 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4317 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
4318 scoped_ptr<SpdyFrame> initial_settings_frame(
4319 spdy_util_.ConstructSpdySettings(initial_settings));
4321 // Construct the initial window update.
4322 scoped_ptr<SpdyFrame> initial_window_update(
4323 spdy_util_.ConstructSpdyWindowUpdate(
4324 kSessionFlowControlStreamId,
4325 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
4327 // Construct the persisted SETTINGS frame.
4328 const SettingsMap& settings =
4329 spdy_session_pool->http_server_properties()->GetSpdySettings(
4330 host_port_pair);
4331 scoped_ptr<SpdyFrame> settings_frame(
4332 spdy_util_.ConstructSpdySettings(settings));
4334 // Construct the request.
4335 scoped_ptr<SpdyFrame> req(
4336 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4338 std::vector<MockWrite> writes;
4339 if (GetParam().protocol == kProtoHTTP2Draft04) {
4340 writes.push_back(
4341 MockWrite(ASYNC,
4342 kHttp2ConnectionHeaderPrefix,
4343 kHttp2ConnectionHeaderPrefixSize));
4345 writes.push_back(CreateMockWrite(*initial_settings_frame));
4346 if (GetParam().protocol >= kProtoSPDY31) {
4347 writes.push_back(CreateMockWrite(*initial_window_update));
4349 writes.push_back(CreateMockWrite(*settings_frame));
4350 writes.push_back(CreateMockWrite(*req));
4352 // Construct the reply.
4353 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4354 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4355 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4356 scoped_ptr<SpdyFrame> reply(
4357 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4359 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4360 MockRead reads[] = {
4361 CreateMockRead(*reply),
4362 CreateMockRead(*body),
4363 MockRead(ASYNC, 0, 0) // EOF
4366 DelayedSocketData data(2, reads, arraysize(reads),
4367 vector_as_array(&writes), writes.size());
4368 helper.AddData(&data);
4369 helper.RunDefaultTest();
4370 helper.VerifyDataConsumed();
4371 TransactionHelperResult out = helper.output();
4372 EXPECT_EQ(OK, out.rv);
4373 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4374 EXPECT_EQ("hello!", out.response_data);
4377 // Verify we had two persisted settings.
4378 const SettingsMap& settings_map =
4379 spdy_session_pool->http_server_properties()->GetSpdySettings(
4380 host_port_pair);
4381 ASSERT_EQ(2u, settings_map.size());
4383 // Verify the first persisted setting.
4384 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4385 EXPECT_TRUE(it1 != settings_map.end());
4386 SettingsFlagsAndValue flags_and_value1 = it1->second;
4387 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4388 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4390 // Verify the second persisted setting.
4391 SettingsMap::const_iterator it2 = settings_map.find(kSampleId2);
4392 EXPECT_TRUE(it2 != settings_map.end());
4393 SettingsFlagsAndValue flags_and_value2 = it2->second;
4394 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first);
4395 EXPECT_EQ(kSampleValue2, flags_and_value2.second);
4399 TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
4400 scoped_ptr<SpdyFrame> req(
4401 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4402 MockWrite writes[] = { CreateMockWrite(*req) };
4404 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
4405 MockRead reads[] = {
4406 CreateMockRead(*go_away),
4409 DelayedSocketData data(1, reads, arraysize(reads),
4410 writes, arraysize(writes));
4411 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4412 BoundNetLog(), GetParam(), NULL);
4413 helper.AddData(&data);
4414 helper.RunToCompletion(&data);
4415 TransactionHelperResult out = helper.output();
4416 EXPECT_EQ(ERR_ABORTED, out.rv);
4419 TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
4420 scoped_ptr<SpdyFrame> req(
4421 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4422 MockWrite writes[] = { CreateMockWrite(*req) };
4424 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4425 MockRead reads[] = {
4426 CreateMockRead(*resp),
4427 MockRead(SYNCHRONOUS, 0, 0) // EOF
4430 DelayedSocketData data(1, reads, arraysize(reads),
4431 writes, arraysize(writes));
4432 BoundNetLog log;
4433 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4434 log, GetParam(), NULL);
4435 helper.RunPreTestSetup();
4436 helper.AddData(&data);
4437 HttpNetworkTransaction* trans = helper.trans();
4439 TestCompletionCallback callback;
4440 TransactionHelperResult out;
4441 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
4443 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4444 out.rv = callback.WaitForResult();
4445 EXPECT_EQ(out.rv, OK);
4447 const HttpResponseInfo* response = trans->GetResponseInfo();
4448 EXPECT_TRUE(response->headers.get() != NULL);
4449 EXPECT_TRUE(response->was_fetched_via_spdy);
4450 out.rv = ReadTransaction(trans, &out.response_data);
4451 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4453 // Verify that we consumed all test data.
4454 helper.VerifyDataConsumed();
4457 // Test to make sure we can correctly connect through a proxy.
4458 TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
4459 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4460 BoundNetLog(), GetParam(), NULL);
4461 helper.session_deps().reset(CreateSpdySessionDependencies(
4462 GetParam(),
4463 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4464 helper.SetSession(make_scoped_refptr(
4465 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4466 helper.RunPreTestSetup();
4467 HttpNetworkTransaction* trans = helper.trans();
4469 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4470 "Host: www.google.com\r\n"
4471 "Proxy-Connection: keep-alive\r\n\r\n"};
4472 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4473 "Host: www.google.com\r\n"
4474 "Proxy-Connection: keep-alive\r\n\r\n"};
4475 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4476 scoped_ptr<SpdyFrame> req(
4477 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4478 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4479 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4481 MockWrite writes_SPDYNPN[] = {
4482 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4483 CreateMockWrite(*req, 2),
4485 MockRead reads_SPDYNPN[] = {
4486 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4487 CreateMockRead(*resp, 3),
4488 CreateMockRead(*body.get(), 4),
4489 MockRead(ASYNC, 0, 0, 5),
4492 MockWrite writes_SPDYSSL[] = {
4493 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4494 CreateMockWrite(*req, 2),
4496 MockRead reads_SPDYSSL[] = {
4497 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4498 CreateMockRead(*resp, 3),
4499 CreateMockRead(*body.get(), 4),
4500 MockRead(ASYNC, 0, 0, 5),
4503 MockWrite writes_SPDYNOSSL[] = {
4504 CreateMockWrite(*req, 0),
4507 MockRead reads_SPDYNOSSL[] = {
4508 CreateMockRead(*resp, 1),
4509 CreateMockRead(*body.get(), 2),
4510 MockRead(ASYNC, 0, 0, 3),
4513 scoped_ptr<OrderedSocketData> data;
4514 switch(GetParam().ssl_type) {
4515 case SPDYNOSSL:
4516 data.reset(new OrderedSocketData(reads_SPDYNOSSL,
4517 arraysize(reads_SPDYNOSSL),
4518 writes_SPDYNOSSL,
4519 arraysize(writes_SPDYNOSSL)));
4520 break;
4521 case SPDYSSL:
4522 data.reset(new OrderedSocketData(reads_SPDYSSL,
4523 arraysize(reads_SPDYSSL),
4524 writes_SPDYSSL,
4525 arraysize(writes_SPDYSSL)));
4526 break;
4527 case SPDYNPN:
4528 data.reset(new OrderedSocketData(reads_SPDYNPN,
4529 arraysize(reads_SPDYNPN),
4530 writes_SPDYNPN,
4531 arraysize(writes_SPDYNPN)));
4532 break;
4533 default:
4534 NOTREACHED();
4537 helper.AddData(data.get());
4538 TestCompletionCallback callback;
4540 int rv = trans->Start(
4541 &CreateGetRequest(), callback.callback(), BoundNetLog());
4542 EXPECT_EQ(ERR_IO_PENDING, rv);
4544 rv = callback.WaitForResult();
4545 EXPECT_EQ(0, rv);
4547 // Verify the SYN_REPLY.
4548 HttpResponseInfo response = *trans->GetResponseInfo();
4549 EXPECT_TRUE(response.headers.get() != NULL);
4550 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4552 std::string response_data;
4553 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4554 EXPECT_EQ("hello!", response_data);
4555 helper.VerifyDataConsumed();
4558 // Test to make sure we can correctly connect through a proxy to www.google.com,
4559 // if there already exists a direct spdy connection to www.google.com. See
4560 // http://crbug.com/49874
4561 TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
4562 // When setting up the first transaction, we store the SpdySessionPool so that
4563 // we can use the same pool in the second transaction.
4564 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4565 BoundNetLog(), GetParam(), NULL);
4567 // Use a proxy service which returns a proxy fallback list from DIRECT to
4568 // myproxy:70. For this test there will be no fallback, so it is equivalent
4569 // to simply DIRECT. The reason for appending the second proxy is to verify
4570 // that the session pool key used does is just "DIRECT".
4571 helper.session_deps().reset(CreateSpdySessionDependencies(
4572 GetParam(),
4573 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4574 helper.SetSession(make_scoped_refptr(
4575 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4577 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4578 helper.RunPreTestSetup();
4580 // Construct and send a simple GET request.
4581 scoped_ptr<SpdyFrame> req(
4582 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4583 MockWrite writes[] = {
4584 CreateMockWrite(*req, 1),
4587 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4588 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4589 MockRead reads[] = {
4590 CreateMockRead(*resp, 2),
4591 CreateMockRead(*body, 3),
4592 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
4593 MockRead(ASYNC, 0, 5) // EOF
4595 OrderedSocketData data(reads, arraysize(reads),
4596 writes, arraysize(writes));
4597 helper.AddData(&data);
4598 HttpNetworkTransaction* trans = helper.trans();
4600 TestCompletionCallback callback;
4601 TransactionHelperResult out;
4602 out.rv = trans->Start(
4603 &CreateGetRequest(), callback.callback(), BoundNetLog());
4605 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4606 out.rv = callback.WaitForResult();
4607 EXPECT_EQ(out.rv, OK);
4609 const HttpResponseInfo* response = trans->GetResponseInfo();
4610 EXPECT_TRUE(response->headers.get() != NULL);
4611 EXPECT_TRUE(response->was_fetched_via_spdy);
4612 out.rv = ReadTransaction(trans, &out.response_data);
4613 EXPECT_EQ(OK, out.rv);
4614 out.status_line = response->headers->GetStatusLine();
4615 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4616 EXPECT_EQ("hello!", out.response_data);
4618 // Check that the SpdySession is still in the SpdySessionPool.
4619 HostPortPair host_port_pair("www.google.com", helper.port());
4620 SpdySessionKey session_pool_key_direct(
4621 host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled);
4622 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
4623 SpdySessionKey session_pool_key_proxy(
4624 host_port_pair,
4625 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
4626 kPrivacyModeDisabled);
4627 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
4629 // Set up data for the proxy connection.
4630 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4631 "Host: www.google.com\r\n"
4632 "Proxy-Connection: keep-alive\r\n\r\n"};
4633 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4634 "Host: www.google.com\r\n"
4635 "Proxy-Connection: keep-alive\r\n\r\n"};
4636 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4637 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
4638 "http://www.google.com/foo.dat", false, 1, LOWEST));
4639 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4640 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
4642 MockWrite writes_SPDYNPN[] = {
4643 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4644 CreateMockWrite(*req2, 2),
4646 MockRead reads_SPDYNPN[] = {
4647 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4648 CreateMockRead(*resp2, 3),
4649 CreateMockRead(*body2, 4),
4650 MockRead(ASYNC, 0, 5) // EOF
4653 MockWrite writes_SPDYNOSSL[] = {
4654 CreateMockWrite(*req2, 0),
4656 MockRead reads_SPDYNOSSL[] = {
4657 CreateMockRead(*resp2, 1),
4658 CreateMockRead(*body2, 2),
4659 MockRead(ASYNC, 0, 3) // EOF
4662 MockWrite writes_SPDYSSL[] = {
4663 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4664 CreateMockWrite(*req2, 2),
4666 MockRead reads_SPDYSSL[] = {
4667 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4668 CreateMockRead(*resp2, 3),
4669 CreateMockRead(*body2, 4),
4670 MockRead(ASYNC, 0, 0, 5),
4673 scoped_ptr<OrderedSocketData> data_proxy;
4674 switch(GetParam().ssl_type) {
4675 case SPDYNPN:
4676 data_proxy.reset(new OrderedSocketData(reads_SPDYNPN,
4677 arraysize(reads_SPDYNPN),
4678 writes_SPDYNPN,
4679 arraysize(writes_SPDYNPN)));
4680 break;
4681 case SPDYNOSSL:
4682 data_proxy.reset(new OrderedSocketData(reads_SPDYNOSSL,
4683 arraysize(reads_SPDYNOSSL),
4684 writes_SPDYNOSSL,
4685 arraysize(writes_SPDYNOSSL)));
4686 break;
4687 case SPDYSSL:
4688 data_proxy.reset(new OrderedSocketData(reads_SPDYSSL,
4689 arraysize(reads_SPDYSSL),
4690 writes_SPDYSSL,
4691 arraysize(writes_SPDYSSL)));
4692 break;
4693 default:
4694 NOTREACHED();
4697 // Create another request to www.google.com, but this time through a proxy.
4698 HttpRequestInfo request_proxy;
4699 request_proxy.method = "GET";
4700 request_proxy.url = GURL("http://www.google.com/foo.dat");
4701 request_proxy.load_flags = 0;
4702 scoped_ptr<SpdySessionDependencies> ssd_proxy(
4703 CreateSpdySessionDependencies(GetParam()));
4704 // Ensure that this transaction uses the same SpdySessionPool.
4705 scoped_refptr<HttpNetworkSession> session_proxy(
4706 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
4707 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
4708 BoundNetLog(), GetParam(), NULL);
4709 HttpNetworkSessionPeer session_peer(session_proxy);
4710 scoped_ptr<net::ProxyService> proxy_service(
4711 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
4712 session_peer.SetProxyService(proxy_service.get());
4713 helper_proxy.session_deps().swap(ssd_proxy);
4714 helper_proxy.SetSession(session_proxy);
4715 helper_proxy.RunPreTestSetup();
4716 helper_proxy.AddData(data_proxy.get());
4718 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
4719 TestCompletionCallback callback_proxy;
4720 int rv = trans_proxy->Start(
4721 &request_proxy, callback_proxy.callback(), BoundNetLog());
4722 EXPECT_EQ(ERR_IO_PENDING, rv);
4723 rv = callback_proxy.WaitForResult();
4724 EXPECT_EQ(0, rv);
4726 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
4727 EXPECT_TRUE(response_proxy.headers.get() != NULL);
4728 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
4730 std::string response_data;
4731 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
4732 EXPECT_EQ("hello!", response_data);
4734 data.CompleteRead();
4735 helper_proxy.VerifyDataConsumed();
4738 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4739 // on a new connection, if the connection was previously known to be good.
4740 // This can happen when a server reboots without saying goodbye, or when
4741 // we're behind a NAT that masked the RST.
4742 TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
4743 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4744 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4745 MockRead reads[] = {
4746 CreateMockRead(*resp),
4747 CreateMockRead(*body),
4748 MockRead(ASYNC, ERR_IO_PENDING),
4749 MockRead(ASYNC, ERR_CONNECTION_RESET),
4752 MockRead reads2[] = {
4753 CreateMockRead(*resp),
4754 CreateMockRead(*body),
4755 MockRead(ASYNC, 0, 0) // EOF
4758 // This test has a couple of variants.
4759 enum {
4760 // Induce the RST while waiting for our transaction to send.
4761 VARIANT_RST_DURING_SEND_COMPLETION,
4762 // Induce the RST while waiting for our transaction to read.
4763 // In this case, the send completed - everything copied into the SNDBUF.
4764 VARIANT_RST_DURING_READ_COMPLETION
4767 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4768 variant <= VARIANT_RST_DURING_READ_COMPLETION;
4769 ++variant) {
4770 DelayedSocketData data1(1, reads, arraysize(reads), NULL, 0);
4772 DelayedSocketData data2(1, reads2, arraysize(reads2), NULL, 0);
4774 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4775 BoundNetLog(), GetParam(), NULL);
4776 helper.AddData(&data1);
4777 helper.AddData(&data2);
4778 helper.RunPreTestSetup();
4780 for (int i = 0; i < 2; ++i) {
4781 scoped_ptr<HttpNetworkTransaction> trans(
4782 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
4784 TestCompletionCallback callback;
4785 int rv = trans->Start(
4786 &helper.request(), callback.callback(), BoundNetLog());
4787 EXPECT_EQ(ERR_IO_PENDING, rv);
4788 // On the second transaction, we trigger the RST.
4789 if (i == 1) {
4790 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4791 // Writes to the socket complete asynchronously on SPDY by running
4792 // through the message loop. Complete the write here.
4793 base::RunLoop().RunUntilIdle();
4796 // Now schedule the ERR_CONNECTION_RESET.
4797 EXPECT_EQ(3u, data1.read_index());
4798 data1.CompleteRead();
4799 EXPECT_EQ(4u, data1.read_index());
4801 rv = callback.WaitForResult();
4802 EXPECT_EQ(OK, rv);
4804 const HttpResponseInfo* response = trans->GetResponseInfo();
4805 ASSERT_TRUE(response != NULL);
4806 EXPECT_TRUE(response->headers.get() != NULL);
4807 EXPECT_TRUE(response->was_fetched_via_spdy);
4808 std::string response_data;
4809 rv = ReadTransaction(trans.get(), &response_data);
4810 EXPECT_EQ(OK, rv);
4811 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4812 EXPECT_EQ("hello!", response_data);
4815 helper.VerifyDataConsumed();
4819 // Test that turning SPDY on and off works properly.
4820 TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
4821 net::HttpStreamFactory::set_spdy_enabled(true);
4822 scoped_ptr<SpdyFrame> req(
4823 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4824 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
4826 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4827 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4828 MockRead spdy_reads[] = {
4829 CreateMockRead(*resp),
4830 CreateMockRead(*body),
4831 MockRead(ASYNC, 0, 0) // EOF
4834 DelayedSocketData data(1, spdy_reads, arraysize(spdy_reads),
4835 spdy_writes, arraysize(spdy_writes));
4836 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4837 BoundNetLog(), GetParam(), NULL);
4838 helper.RunToCompletion(&data);
4839 TransactionHelperResult out = helper.output();
4840 EXPECT_EQ(OK, out.rv);
4841 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4842 EXPECT_EQ("hello!", out.response_data);
4844 net::HttpStreamFactory::set_spdy_enabled(false);
4845 MockRead http_reads[] = {
4846 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4847 MockRead("hello from http"),
4848 MockRead(SYNCHRONOUS, OK),
4850 DelayedSocketData data2(1, http_reads, arraysize(http_reads), NULL, 0);
4851 NormalSpdyTransactionHelper helper2(CreateGetRequest(), DEFAULT_PRIORITY,
4852 BoundNetLog(), GetParam(), NULL);
4853 helper2.SetSpdyDisabled();
4854 helper2.RunToCompletion(&data2);
4855 TransactionHelperResult out2 = helper2.output();
4856 EXPECT_EQ(OK, out2.rv);
4857 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
4858 EXPECT_EQ("hello from http", out2.response_data);
4860 net::HttpStreamFactory::set_spdy_enabled(true);
4863 // Tests that Basic authentication works over SPDY
4864 TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
4865 net::HttpStreamFactory::set_spdy_enabled(true);
4867 // The first request will be a bare GET, the second request will be a
4868 // GET with an Authorization header.
4869 scoped_ptr<SpdyFrame> req_get(
4870 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4871 const char* const kExtraAuthorizationHeaders[] = {
4872 "authorization", "Basic Zm9vOmJhcg=="
4874 scoped_ptr<SpdyFrame> req_get_authorization(
4875 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4876 arraysize(kExtraAuthorizationHeaders) / 2,
4877 false, 3, LOWEST, true));
4878 MockWrite spdy_writes[] = {
4879 CreateMockWrite(*req_get, 1),
4880 CreateMockWrite(*req_get_authorization, 4),
4883 // The first response is a 401 authentication challenge, and the second
4884 // response will be a 200 response since the second request includes a valid
4885 // Authorization header.
4886 const char* const kExtraAuthenticationHeaders[] = {
4887 "www-authenticate",
4888 "Basic realm=\"MyRealm\""
4890 scoped_ptr<SpdyFrame> resp_authentication(
4891 spdy_util_.ConstructSpdySynReplyError(
4892 "401 Authentication Required",
4893 kExtraAuthenticationHeaders,
4894 arraysize(kExtraAuthenticationHeaders) / 2,
4895 1));
4896 scoped_ptr<SpdyFrame> body_authentication(
4897 spdy_util_.ConstructSpdyBodyFrame(1, true));
4898 scoped_ptr<SpdyFrame> resp_data(
4899 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4900 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
4901 MockRead spdy_reads[] = {
4902 CreateMockRead(*resp_authentication, 2),
4903 CreateMockRead(*body_authentication, 3),
4904 CreateMockRead(*resp_data, 5),
4905 CreateMockRead(*body_data, 6),
4906 MockRead(ASYNC, 0, 7),
4909 OrderedSocketData data(spdy_reads, arraysize(spdy_reads),
4910 spdy_writes, arraysize(spdy_writes));
4911 HttpRequestInfo request(CreateGetRequest());
4912 BoundNetLog net_log;
4913 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
4914 net_log, GetParam(), NULL);
4916 helper.RunPreTestSetup();
4917 helper.AddData(&data);
4918 HttpNetworkTransaction* trans = helper.trans();
4919 TestCompletionCallback callback;
4920 const int rv_start = trans->Start(&request, callback.callback(), net_log);
4921 EXPECT_EQ(ERR_IO_PENDING, rv_start);
4922 const int rv_start_complete = callback.WaitForResult();
4923 EXPECT_EQ(OK, rv_start_complete);
4925 // Make sure the response has an auth challenge.
4926 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
4927 ASSERT_TRUE(response_start != NULL);
4928 ASSERT_TRUE(response_start->headers.get() != NULL);
4929 EXPECT_EQ(401, response_start->headers->response_code());
4930 EXPECT_TRUE(response_start->was_fetched_via_spdy);
4931 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
4932 ASSERT_TRUE(auth_challenge != NULL);
4933 EXPECT_FALSE(auth_challenge->is_proxy);
4934 EXPECT_EQ("basic", auth_challenge->scheme);
4935 EXPECT_EQ("MyRealm", auth_challenge->realm);
4937 // Restart with a username/password.
4938 AuthCredentials credentials(ASCIIToUTF16("foo"), ASCIIToUTF16("bar"));
4939 TestCompletionCallback callback_restart;
4940 const int rv_restart = trans->RestartWithAuth(
4941 credentials, callback_restart.callback());
4942 EXPECT_EQ(ERR_IO_PENDING, rv_restart);
4943 const int rv_restart_complete = callback_restart.WaitForResult();
4944 EXPECT_EQ(OK, rv_restart_complete);
4945 // TODO(cbentzel): This is actually the same response object as before, but
4946 // data has changed.
4947 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
4948 ASSERT_TRUE(response_restart != NULL);
4949 ASSERT_TRUE(response_restart->headers.get() != NULL);
4950 EXPECT_EQ(200, response_restart->headers->response_code());
4951 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
4954 TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
4955 scoped_ptr<SpdyFrame> stream1_syn(
4956 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4957 scoped_ptr<SpdyFrame> stream1_body(
4958 spdy_util_.ConstructSpdyBodyFrame(1, true));
4959 MockWrite writes[] = {
4960 CreateMockWrite(*stream1_syn, 1),
4963 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
4964 spdy_util_.AddUrlToHeaderBlock(
4965 "http://www.google.com/foo.dat", initial_headers.get());
4966 scoped_ptr<SpdyFrame> stream2_syn(
4967 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
4968 false,
4970 LOWEST,
4971 SYN_STREAM,
4972 CONTROL_FLAG_NONE,
4973 1));
4975 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
4976 (*late_headers)["hello"] = "bye";
4977 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
4978 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4979 scoped_ptr<SpdyFrame> stream2_headers(
4980 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
4981 false,
4983 LOWEST,
4984 HEADERS,
4985 CONTROL_FLAG_NONE,
4986 0));
4988 scoped_ptr<SpdyFrame>
4989 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4990 const char kPushedData[] = "pushed";
4991 scoped_ptr<SpdyFrame> stream2_body(
4992 spdy_util_.ConstructSpdyBodyFrame(
4993 2, kPushedData, strlen(kPushedData), true));
4994 MockRead reads[] = {
4995 CreateMockRead(*stream1_reply, 2),
4996 CreateMockRead(*stream2_syn, 3),
4997 CreateMockRead(*stream2_headers, 4),
4998 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
4999 CreateMockRead(*stream2_body, 5),
5000 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5003 HttpResponseInfo response;
5004 HttpResponseInfo response2;
5005 std::string expected_push_result("pushed");
5006 OrderedSocketData data(reads, arraysize(reads),
5007 writes, arraysize(writes));
5008 RunServerPushTest(&data,
5009 &response,
5010 &response2,
5011 expected_push_result);
5013 // Verify the SYN_REPLY.
5014 EXPECT_TRUE(response.headers.get() != NULL);
5015 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5017 // Verify the pushed stream.
5018 EXPECT_TRUE(response2.headers.get() != NULL);
5019 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5022 TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
5023 // We push a stream and attempt to claim it before the headers come down.
5024 scoped_ptr<SpdyFrame> stream1_syn(
5025 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5026 scoped_ptr<SpdyFrame> stream1_body(
5027 spdy_util_.ConstructSpdyBodyFrame(1, true));
5028 MockWrite writes[] = {
5029 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5032 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5033 spdy_util_.AddUrlToHeaderBlock(
5034 "http://www.google.com/foo.dat", initial_headers.get());
5035 scoped_ptr<SpdyFrame> stream2_syn(
5036 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
5037 false,
5039 LOWEST,
5040 SYN_STREAM,
5041 CONTROL_FLAG_NONE,
5042 1));
5044 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5045 (*late_headers)["hello"] = "bye";
5046 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5047 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5048 scoped_ptr<SpdyFrame> stream2_headers(
5049 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5050 false,
5052 LOWEST,
5053 HEADERS,
5054 CONTROL_FLAG_NONE,
5055 0));
5057 scoped_ptr<SpdyFrame>
5058 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5059 const char kPushedData[] = "pushed";
5060 scoped_ptr<SpdyFrame> stream2_body(
5061 spdy_util_.ConstructSpdyBodyFrame(
5062 2, kPushedData, strlen(kPushedData), true));
5063 MockRead reads[] = {
5064 CreateMockRead(*stream1_reply, 1),
5065 CreateMockRead(*stream2_syn, 2),
5066 CreateMockRead(*stream1_body, 3),
5067 CreateMockRead(*stream2_headers, 4),
5068 CreateMockRead(*stream2_body, 5),
5069 MockRead(ASYNC, 0, 6), // EOF
5072 HttpResponseInfo response;
5073 HttpResponseInfo response2;
5074 std::string expected_push_result("pushed");
5075 DeterministicSocketData data(reads, arraysize(reads),
5076 writes, arraysize(writes));
5078 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5079 BoundNetLog(), GetParam(), NULL);
5080 helper.SetDeterministic();
5081 helper.AddDeterministicData(&data);
5082 helper.RunPreTestSetup();
5084 HttpNetworkTransaction* trans = helper.trans();
5086 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5087 // and the body of the primary stream, but before we've received the HEADERS
5088 // for the pushed stream.
5089 data.SetStop(3);
5091 // Start the transaction.
5092 TestCompletionCallback callback;
5093 int rv = trans->Start(
5094 &CreateGetRequest(), callback.callback(), BoundNetLog());
5095 EXPECT_EQ(ERR_IO_PENDING, rv);
5096 data.Run();
5097 rv = callback.WaitForResult();
5098 EXPECT_EQ(0, rv);
5100 // Request the pushed path. At this point, we've received the push, but the
5101 // headers are not yet complete.
5102 scoped_ptr<HttpNetworkTransaction> trans2(
5103 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5104 rv = trans2->Start(
5105 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5106 EXPECT_EQ(ERR_IO_PENDING, rv);
5107 data.RunFor(3);
5108 base::RunLoop().RunUntilIdle();
5110 // Read the server push body.
5111 std::string result2;
5112 ReadResult(trans2.get(), &data, &result2);
5113 // Read the response body.
5114 std::string result;
5115 ReadResult(trans, &data, &result);
5117 // Verify that the received push data is same as the expected push data.
5118 EXPECT_EQ(result2.compare(expected_push_result), 0)
5119 << "Received data: "
5120 << result2
5121 << "||||| Expected data: "
5122 << expected_push_result;
5124 // Verify the SYN_REPLY.
5125 // Copy the response info, because trans goes away.
5126 response = *trans->GetResponseInfo();
5127 response2 = *trans2->GetResponseInfo();
5129 VerifyStreamsClosed(helper);
5131 // Verify the SYN_REPLY.
5132 EXPECT_TRUE(response.headers.get() != NULL);
5133 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5135 // Verify the pushed stream.
5136 EXPECT_TRUE(response2.headers.get() != NULL);
5137 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5139 // Read the final EOF (which will close the session)
5140 data.RunFor(1);
5142 // Verify that we consumed all test data.
5143 EXPECT_TRUE(data.at_read_eof());
5144 EXPECT_TRUE(data.at_write_eof());
5147 TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
5148 // We push a stream and attempt to claim it before the headers come down.
5149 scoped_ptr<SpdyFrame> stream1_syn(
5150 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5151 scoped_ptr<SpdyFrame> stream1_body(
5152 spdy_util_.ConstructSpdyBodyFrame(1, true));
5153 MockWrite writes[] = {
5154 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5157 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5158 spdy_util_.AddUrlToHeaderBlock(
5159 "http://www.google.com/foo.dat", initial_headers.get());
5160 scoped_ptr<SpdyFrame> stream2_syn(
5161 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
5162 false,
5164 LOWEST,
5165 SYN_STREAM,
5166 CONTROL_FLAG_NONE,
5167 1));
5169 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5170 (*middle_headers)["hello"] = "bye";
5171 scoped_ptr<SpdyFrame> stream2_headers1(
5172 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5173 false,
5175 LOWEST,
5176 HEADERS,
5177 CONTROL_FLAG_NONE,
5178 0));
5180 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5181 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5182 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5183 scoped_ptr<SpdyFrame> stream2_headers2(
5184 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5185 false,
5187 LOWEST,
5188 HEADERS,
5189 CONTROL_FLAG_NONE,
5190 0));
5192 scoped_ptr<SpdyFrame>
5193 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5194 const char kPushedData[] = "pushed";
5195 scoped_ptr<SpdyFrame> stream2_body(
5196 spdy_util_.ConstructSpdyBodyFrame(
5197 2, kPushedData, strlen(kPushedData), true));
5198 MockRead reads[] = {
5199 CreateMockRead(*stream1_reply, 1),
5200 CreateMockRead(*stream2_syn, 2),
5201 CreateMockRead(*stream1_body, 3),
5202 CreateMockRead(*stream2_headers1, 4),
5203 CreateMockRead(*stream2_headers2, 5),
5204 CreateMockRead(*stream2_body, 6),
5205 MockRead(ASYNC, 0, 7), // EOF
5208 HttpResponseInfo response;
5209 HttpResponseInfo response2;
5210 std::string expected_push_result("pushed");
5211 DeterministicSocketData data(reads, arraysize(reads),
5212 writes, arraysize(writes));
5214 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5215 BoundNetLog(), GetParam(), NULL);
5216 helper.SetDeterministic();
5217 helper.AddDeterministicData(&data);
5218 helper.RunPreTestSetup();
5220 HttpNetworkTransaction* trans = helper.trans();
5222 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5223 // the first HEADERS frame, and the body of the primary stream, but before
5224 // we've received the final HEADERS for the pushed stream.
5225 data.SetStop(4);
5227 // Start the transaction.
5228 TestCompletionCallback callback;
5229 int rv = trans->Start(
5230 &CreateGetRequest(), callback.callback(), BoundNetLog());
5231 EXPECT_EQ(ERR_IO_PENDING, rv);
5232 data.Run();
5233 rv = callback.WaitForResult();
5234 EXPECT_EQ(0, rv);
5236 // Request the pushed path. At this point, we've received the push, but the
5237 // headers are not yet complete.
5238 scoped_ptr<HttpNetworkTransaction> trans2(
5239 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5240 rv = trans2->Start(
5241 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5242 EXPECT_EQ(ERR_IO_PENDING, rv);
5243 data.RunFor(3);
5244 base::RunLoop().RunUntilIdle();
5246 // Read the server push body.
5247 std::string result2;
5248 ReadResult(trans2.get(), &data, &result2);
5249 // Read the response body.
5250 std::string result;
5251 ReadResult(trans, &data, &result);
5253 // Verify that the received push data is same as the expected push data.
5254 EXPECT_EQ(expected_push_result, result2);
5256 // Verify the SYN_REPLY.
5257 // Copy the response info, because trans goes away.
5258 response = *trans->GetResponseInfo();
5259 response2 = *trans2->GetResponseInfo();
5261 VerifyStreamsClosed(helper);
5263 // Verify the SYN_REPLY.
5264 EXPECT_TRUE(response.headers.get() != NULL);
5265 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5267 // Verify the pushed stream.
5268 EXPECT_TRUE(response2.headers.get() != NULL);
5269 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5271 // Verify we got all the headers
5272 if (spdy_util_.spdy_version() < SPDY3) {
5273 EXPECT_TRUE(response2.headers->HasHeaderValue(
5274 "url",
5275 "http://www.google.com/foo.dat"));
5276 } else {
5277 EXPECT_TRUE(response2.headers->HasHeaderValue(
5278 "scheme", "http"));
5279 EXPECT_TRUE(response2.headers->HasHeaderValue(
5280 "host", "www.google.com"));
5281 EXPECT_TRUE(response2.headers->HasHeaderValue(
5282 "path", "/foo.dat"));
5284 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5285 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
5286 EXPECT_TRUE(response2.headers->HasHeaderValue("version", "HTTP/1.1"));
5288 // Read the final EOF (which will close the session)
5289 data.RunFor(1);
5291 // Verify that we consumed all test data.
5292 EXPECT_TRUE(data.at_read_eof());
5293 EXPECT_TRUE(data.at_write_eof());
5296 TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
5297 // We push a stream and attempt to claim it before the headers come down.
5298 scoped_ptr<SpdyFrame> stream1_syn(
5299 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5300 scoped_ptr<SpdyFrame> stream1_body(
5301 spdy_util_.ConstructSpdyBodyFrame(1, true));
5302 MockWrite writes[] = {
5303 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5306 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5307 spdy_util_.AddUrlToHeaderBlock(
5308 "http://www.google.com/foo.dat", initial_headers.get());
5309 scoped_ptr<SpdyFrame> stream2_syn(
5310 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
5311 false,
5313 LOWEST,
5314 SYN_STREAM,
5315 CONTROL_FLAG_NONE,
5316 1));
5318 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5319 (*middle_headers)["hello"] = "bye";
5320 scoped_ptr<SpdyFrame> stream2_headers1(
5321 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5322 false,
5324 LOWEST,
5325 HEADERS,
5326 CONTROL_FLAG_NONE,
5327 0));
5329 scoped_ptr<SpdyFrame>
5330 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5331 const char kPushedData[] = "pushed";
5332 scoped_ptr<SpdyFrame> stream2_body(
5333 spdy_util_.ConstructSpdyBodyFrame(
5334 2, kPushedData, strlen(kPushedData), true));
5335 MockRead reads[] = {
5336 CreateMockRead(*stream1_reply, 1),
5337 CreateMockRead(*stream2_syn, 2),
5338 CreateMockRead(*stream1_body, 3),
5339 CreateMockRead(*stream2_headers1, 4),
5340 CreateMockRead(*stream2_body, 5),
5341 MockRead(ASYNC, 0, 6), // EOF
5344 DeterministicSocketData data(reads, arraysize(reads),
5345 writes, arraysize(writes));
5347 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5348 BoundNetLog(), GetParam(), NULL);
5349 helper.SetDeterministic();
5350 helper.AddDeterministicData(&data);
5351 helper.RunPreTestSetup();
5353 HttpNetworkTransaction* trans = helper.trans();
5355 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5356 // the first HEADERS frame, and the body of the primary stream, but before
5357 // we've received the final HEADERS for the pushed stream.
5358 data.SetStop(4);
5360 // Start the transaction.
5361 TestCompletionCallback callback;
5362 int rv = trans->Start(
5363 &CreateGetRequest(), callback.callback(), BoundNetLog());
5364 EXPECT_EQ(ERR_IO_PENDING, rv);
5365 data.Run();
5366 rv = callback.WaitForResult();
5367 EXPECT_EQ(0, rv);
5369 // Request the pushed path. At this point, we've received the push, but the
5370 // headers are not yet complete.
5371 scoped_ptr<HttpNetworkTransaction> trans2(
5372 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5373 rv = trans2->Start(
5374 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5375 EXPECT_EQ(ERR_IO_PENDING, rv);
5376 data.RunFor(2);
5377 base::RunLoop().RunUntilIdle();
5379 // Read the server push body.
5380 std::string result2;
5381 ReadResult(trans2.get(), &data, &result2);
5382 // Read the response body.
5383 std::string result;
5384 ReadResult(trans, &data, &result);
5385 EXPECT_EQ("hello!", result);
5387 // Verify that we haven't received any push data.
5388 EXPECT_EQ("", result2);
5390 // Verify the SYN_REPLY.
5391 // Copy the response info, because trans goes away.
5392 HttpResponseInfo response = *trans->GetResponseInfo();
5393 ASSERT_TRUE(trans2->GetResponseInfo() == NULL);
5395 VerifyStreamsClosed(helper);
5397 // Verify the SYN_REPLY.
5398 EXPECT_TRUE(response.headers.get() != NULL);
5399 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5401 // Read the final EOF (which will close the session).
5402 data.RunFor(1);
5404 // Verify that we consumed all test data.
5405 EXPECT_TRUE(data.at_read_eof());
5406 EXPECT_TRUE(data.at_write_eof());
5409 TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
5410 scoped_ptr<SpdyFrame> req(
5411 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5412 scoped_ptr<SpdyFrame> rst(
5413 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5414 MockWrite writes[] = {
5415 CreateMockWrite(*req),
5416 CreateMockWrite(*rst),
5419 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5420 (*initial_headers)[spdy_util_.GetStatusKey()] = "200 OK";
5421 (*initial_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5422 scoped_ptr<SpdyFrame> stream1_reply(
5423 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
5424 false,
5426 LOWEST,
5427 SYN_REPLY,
5428 CONTROL_FLAG_NONE,
5429 0));
5431 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5432 (*late_headers)["hello"] = "bye";
5433 scoped_ptr<SpdyFrame> stream1_headers(
5434 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5435 false,
5437 LOWEST,
5438 HEADERS,
5439 CONTROL_FLAG_NONE,
5440 0));
5441 scoped_ptr<SpdyFrame> stream1_body(
5442 spdy_util_.ConstructSpdyBodyFrame(1, true));
5443 MockRead reads[] = {
5444 CreateMockRead(*stream1_reply),
5445 CreateMockRead(*stream1_headers),
5446 CreateMockRead(*stream1_body),
5447 MockRead(ASYNC, 0, 0) // EOF
5450 DelayedSocketData data(1, reads, arraysize(reads),
5451 writes, arraysize(writes));
5452 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5453 BoundNetLog(), GetParam(), NULL);
5454 helper.RunToCompletion(&data);
5455 TransactionHelperResult out = helper.output();
5456 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5459 TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
5460 scoped_ptr<SpdyFrame> req(
5461 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5462 scoped_ptr<SpdyFrame> rst(
5463 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5464 MockWrite writes[] = {
5465 CreateMockWrite(*req),
5466 CreateMockWrite(*rst),
5469 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5470 (*initial_headers)[spdy_util_.GetStatusKey()] = "200 OK";
5471 (*initial_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5472 scoped_ptr<SpdyFrame> stream1_reply(
5473 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
5474 false,
5476 LOWEST,
5477 SYN_REPLY,
5478 CONTROL_FLAG_NONE,
5479 0));
5481 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5482 (*late_headers)["hello"] = "bye";
5483 scoped_ptr<SpdyFrame> stream1_headers(
5484 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5485 false,
5487 LOWEST,
5488 HEADERS,
5489 CONTROL_FLAG_NONE,
5490 0));
5491 scoped_ptr<SpdyFrame> stream1_body(
5492 spdy_util_.ConstructSpdyBodyFrame(1, false));
5493 scoped_ptr<SpdyFrame> stream1_body2(
5494 spdy_util_.ConstructSpdyBodyFrame(1, true));
5495 MockRead reads[] = {
5496 CreateMockRead(*stream1_reply),
5497 CreateMockRead(*stream1_body),
5498 CreateMockRead(*stream1_headers),
5499 CreateMockRead(*stream1_body2),
5500 MockRead(ASYNC, 0, 0) // EOF
5503 DelayedSocketData data(1, reads, arraysize(reads),
5504 writes, arraysize(writes));
5505 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5506 BoundNetLog(), GetParam(), NULL);
5507 helper.RunToCompletion(&data);
5508 TransactionHelperResult out = helper.output();
5509 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5512 TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
5513 // In this test we want to verify that we can't accidentally push content
5514 // which can't be pushed by this content server.
5515 // This test assumes that:
5516 // - if we're requesting http://www.foo.com/barbaz
5517 // - the browser has made a connection to "www.foo.com".
5519 // A list of the URL to fetch, followed by the URL being pushed.
5520 static const char* const kTestCases[] = {
5521 "http://www.google.com/foo.html",
5522 "http://www.google.com:81/foo.js", // Bad port
5524 "http://www.google.com/foo.html",
5525 "https://www.google.com/foo.js", // Bad protocol
5527 "http://www.google.com/foo.html",
5528 "ftp://www.google.com/foo.js", // Invalid Protocol
5530 "http://www.google.com/foo.html",
5531 "http://blat.www.google.com/foo.js", // Cross subdomain
5533 "http://www.google.com/foo.html",
5534 "http://www.foo.com/foo.js", // Cross domain
5537 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
5538 const char* url_to_fetch = kTestCases[index];
5539 const char* url_to_push = kTestCases[index + 1];
5541 scoped_ptr<SpdyFrame> stream1_syn(
5542 spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
5543 scoped_ptr<SpdyFrame> stream1_body(
5544 spdy_util_.ConstructSpdyBodyFrame(1, true));
5545 scoped_ptr<SpdyFrame> push_rst(
5546 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
5547 MockWrite writes[] = {
5548 CreateMockWrite(*stream1_syn, 1),
5549 CreateMockWrite(*push_rst, 4),
5552 scoped_ptr<SpdyFrame>
5553 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5554 scoped_ptr<SpdyFrame>
5555 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
5559 url_to_push));
5560 const char kPushedData[] = "pushed";
5561 scoped_ptr<SpdyFrame> stream2_body(
5562 spdy_util_.ConstructSpdyBodyFrame(
5563 2, kPushedData, strlen(kPushedData), true));
5564 scoped_ptr<SpdyFrame> rst(
5565 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
5567 MockRead reads[] = {
5568 CreateMockRead(*stream1_reply, 2),
5569 CreateMockRead(*stream2_syn, 3),
5570 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5571 CreateMockRead(*stream2_body, 6),
5572 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5575 HttpResponseInfo response;
5576 OrderedSocketData data(reads, arraysize(reads),
5577 writes, arraysize(writes));
5579 HttpRequestInfo request;
5580 request.method = "GET";
5581 request.url = GURL(url_to_fetch);
5582 request.load_flags = 0;
5584 // Enable cross-origin push. Since we are not using a proxy, this should
5585 // not actually enable cross-origin SPDY push.
5586 scoped_ptr<SpdySessionDependencies> session_deps(
5587 CreateSpdySessionDependencies(GetParam()));
5588 session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
5589 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5590 BoundNetLog(), GetParam(),
5591 session_deps.release());
5592 helper.RunPreTestSetup();
5593 helper.AddData(&data);
5595 HttpNetworkTransaction* trans = helper.trans();
5597 // Start the transaction with basic parameters.
5598 TestCompletionCallback callback;
5600 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5601 EXPECT_EQ(ERR_IO_PENDING, rv);
5602 rv = callback.WaitForResult();
5604 // Read the response body.
5605 std::string result;
5606 ReadResult(trans, &data, &result);
5608 // Verify that we consumed all test data.
5609 EXPECT_TRUE(data.at_read_eof());
5610 EXPECT_TRUE(data.at_write_eof());
5612 // Verify the SYN_REPLY.
5613 // Copy the response info, because trans goes away.
5614 response = *trans->GetResponseInfo();
5616 VerifyStreamsClosed(helper);
5618 // Verify the SYN_REPLY.
5619 EXPECT_TRUE(response.headers.get() != NULL);
5620 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5624 TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
5625 // Construct the request.
5626 scoped_ptr<SpdyFrame> req(
5627 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5628 scoped_ptr<SpdyFrame> req2(
5629 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
5630 MockWrite writes[] = {
5631 CreateMockWrite(*req, 1),
5632 CreateMockWrite(*req2, 3),
5635 scoped_ptr<SpdyFrame> refused(
5636 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
5637 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5638 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true));
5639 MockRead reads[] = {
5640 CreateMockRead(*refused, 2),
5641 CreateMockRead(*resp, 4),
5642 CreateMockRead(*body, 5),
5643 MockRead(ASYNC, 0, 6) // EOF
5646 OrderedSocketData data(reads, arraysize(reads),
5647 writes, arraysize(writes));
5648 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5649 BoundNetLog(), GetParam(), NULL);
5651 helper.RunPreTestSetup();
5652 helper.AddData(&data);
5654 HttpNetworkTransaction* trans = helper.trans();
5656 // Start the transaction with basic parameters.
5657 TestCompletionCallback callback;
5658 int rv = trans->Start(
5659 &CreateGetRequest(), callback.callback(), BoundNetLog());
5660 EXPECT_EQ(ERR_IO_PENDING, rv);
5661 rv = callback.WaitForResult();
5662 EXPECT_EQ(OK, rv);
5664 // Verify that we consumed all test data.
5665 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
5666 << data.read_count()
5667 << " Read index: "
5668 << data.read_index();
5669 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
5670 << data.write_count()
5671 << " Write index: "
5672 << data.write_index();
5674 // Verify the SYN_REPLY.
5675 HttpResponseInfo response = *trans->GetResponseInfo();
5676 EXPECT_TRUE(response.headers.get() != NULL);
5677 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5680 TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) {
5681 // This first request will start to establish the SpdySession.
5682 // Then we will start the second (MEDIUM priority) and then third
5683 // (HIGHEST priority) request in such a way that the third will actually
5684 // start before the second, causing the second to be numbered differently
5685 // than the order they were created.
5686 scoped_ptr<SpdyFrame> req1(
5687 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5688 scoped_ptr<SpdyFrame> req2(
5689 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true));
5690 scoped_ptr<SpdyFrame> req3(
5691 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true));
5692 MockWrite writes[] = {
5693 CreateMockWrite(*req1, 0),
5694 CreateMockWrite(*req2, 3),
5695 CreateMockWrite(*req3, 4),
5698 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5699 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
5700 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5701 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
5702 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
5703 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
5704 MockRead reads[] = {
5705 CreateMockRead(*resp1, 1),
5706 CreateMockRead(*body1, 2),
5707 CreateMockRead(*resp2, 5),
5708 CreateMockRead(*body2, 6),
5709 CreateMockRead(*resp3, 7),
5710 CreateMockRead(*body3, 8),
5711 MockRead(ASYNC, 0, 9) // EOF
5714 DeterministicSocketData data(reads, arraysize(reads),
5715 writes, arraysize(writes));
5716 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
5717 BoundNetLog(), GetParam(), NULL);
5718 helper.SetDeterministic();
5719 helper.RunPreTestSetup();
5720 helper.AddDeterministicData(&data);
5722 // Start the first transaction to set up the SpdySession
5723 HttpNetworkTransaction* trans = helper.trans();
5724 TestCompletionCallback callback;
5725 HttpRequestInfo info1 = CreateGetRequest();
5726 int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
5727 EXPECT_EQ(ERR_IO_PENDING, rv);
5729 // Run the message loop, but do not allow the write to complete.
5730 // This leaves the SpdySession with a write pending, which prevents
5731 // SpdySession from attempting subsequent writes until this write completes.
5732 base::RunLoop().RunUntilIdle();
5734 // Now, start both new transactions
5735 HttpRequestInfo info2 = CreateGetRequest();
5736 TestCompletionCallback callback2;
5737 scoped_ptr<HttpNetworkTransaction> trans2(
5738 new HttpNetworkTransaction(MEDIUM, helper.session().get()));
5739 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog());
5740 EXPECT_EQ(ERR_IO_PENDING, rv);
5741 base::RunLoop().RunUntilIdle();
5743 HttpRequestInfo info3 = CreateGetRequest();
5744 TestCompletionCallback callback3;
5745 scoped_ptr<HttpNetworkTransaction> trans3(
5746 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
5747 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog());
5748 EXPECT_EQ(ERR_IO_PENDING, rv);
5749 base::RunLoop().RunUntilIdle();
5751 // We now have two SYN_STREAM frames queued up which will be
5752 // dequeued only once the first write completes, which we
5753 // now allow to happen.
5754 data.RunFor(2);
5755 EXPECT_EQ(OK, callback.WaitForResult());
5757 // And now we can allow everything else to run to completion.
5758 data.SetStop(10);
5759 data.Run();
5760 EXPECT_EQ(OK, callback2.WaitForResult());
5761 EXPECT_EQ(OK, callback3.WaitForResult());
5763 helper.VerifyDataConsumed();
5766 // The tests below are only for SPDY/3 and above.
5768 // Test that sent data frames and received WINDOW_UPDATE frames change
5769 // the send_window_size_ correctly.
5771 // WINDOW_UPDATE is different than most other frames in that it can arrive
5772 // while the client is still sending the request body. In order to enforce
5773 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
5774 // socket data provider, so that initial read that is done as soon as the
5775 // stream is created, succeeds and schedules another read. This way reads
5776 // and writes are interleaved; after doing a full frame write, SpdyStream
5777 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
5778 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5779 // since request has not been completely written, therefore we feed
5780 // enough number of WINDOW_UPDATEs to finish the first read and cause a
5781 // write, leading to a complete write of request body; after that we send
5782 // a reply with a body, to cause a graceful shutdown.
5784 // TODO(agayev): develop a socket data provider where both, reads and
5785 // writes are ordered so that writing tests like these are easy and rewrite
5786 // all these tests using it. Right now we are working around the
5787 // limitations as described above and it's not deterministic, tests may
5788 // fail under specific circumstances.
5789 TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
5790 if (GetParam().protocol < kProtoSPDY3)
5791 return;
5793 static int kFrameCount = 2;
5794 scoped_ptr<std::string> content(
5795 new std::string(kMaxSpdyFrameChunkSize, 'a'));
5796 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
5797 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
5798 scoped_ptr<SpdyFrame> body(
5799 spdy_util_.ConstructSpdyBodyFrame(
5800 1, content->c_str(), content->size(), false));
5801 scoped_ptr<SpdyFrame> body_end(
5802 spdy_util_.ConstructSpdyBodyFrame(
5803 1, content->c_str(), content->size(), true));
5805 MockWrite writes[] = {
5806 CreateMockWrite(*req, 0),
5807 CreateMockWrite(*body, 1),
5808 CreateMockWrite(*body_end, 2),
5811 static const int32 kDeltaWindowSize = 0xff;
5812 static const int kDeltaCount = 4;
5813 scoped_ptr<SpdyFrame> window_update(
5814 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5815 scoped_ptr<SpdyFrame> window_update_dummy(
5816 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
5817 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
5818 MockRead reads[] = {
5819 CreateMockRead(*window_update_dummy, 3),
5820 CreateMockRead(*window_update_dummy, 4),
5821 CreateMockRead(*window_update_dummy, 5),
5822 CreateMockRead(*window_update, 6), // Four updates, therefore window
5823 CreateMockRead(*window_update, 7), // size should increase by
5824 CreateMockRead(*window_update, 8), // kDeltaWindowSize * 4
5825 CreateMockRead(*window_update, 9),
5826 CreateMockRead(*resp, 10),
5827 CreateMockRead(*body_end, 11),
5828 MockRead(ASYNC, 0, 0, 12) // EOF
5831 DeterministicSocketData data(reads, arraysize(reads),
5832 writes, arraysize(writes));
5834 ScopedVector<UploadElementReader> element_readers;
5835 for (int i = 0; i < kFrameCount; ++i) {
5836 element_readers.push_back(
5837 new UploadBytesElementReader(content->c_str(), content->size()));
5839 UploadDataStream upload_data_stream(&element_readers, 0);
5841 // Setup the request
5842 HttpRequestInfo request;
5843 request.method = "POST";
5844 request.url = GURL(kDefaultURL);
5845 request.upload_data_stream = &upload_data_stream;
5847 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5848 BoundNetLog(), GetParam(), NULL);
5849 helper.SetDeterministic();
5850 helper.AddDeterministicData(&data);
5851 helper.RunPreTestSetup();
5853 HttpNetworkTransaction* trans = helper.trans();
5855 TestCompletionCallback callback;
5856 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5858 EXPECT_EQ(ERR_IO_PENDING, rv);
5860 data.RunFor(11);
5862 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
5863 ASSERT_TRUE(stream != NULL);
5864 ASSERT_TRUE(stream->stream() != NULL);
5865 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize) +
5866 kDeltaWindowSize * kDeltaCount -
5867 kMaxSpdyFrameChunkSize * kFrameCount,
5868 stream->stream()->send_window_size());
5870 data.RunFor(1);
5872 rv = callback.WaitForResult();
5873 EXPECT_EQ(OK, rv);
5875 helper.VerifyDataConsumed();
5878 // Test that received data frames and sent WINDOW_UPDATE frames change
5879 // the recv_window_size_ correctly.
5880 TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
5881 if (GetParam().protocol < kProtoSPDY3)
5882 return;
5884 // Set the data in the body frame large enough to trigger sending a
5885 // WINDOW_UPDATE by the stream.
5886 const std::string body_data(kSpdyStreamInitialWindowSize / 2 + 1, 'x');
5888 scoped_ptr<SpdyFrame> req(
5889 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5890 scoped_ptr<SpdyFrame> session_window_update(
5891 spdy_util_.ConstructSpdyWindowUpdate(0, body_data.size()));
5892 scoped_ptr<SpdyFrame> window_update(
5893 spdy_util_.ConstructSpdyWindowUpdate(1, body_data.size()));
5895 std::vector<MockWrite> writes;
5896 writes.push_back(CreateMockWrite(*req));
5897 if (GetParam().protocol >= kProtoSPDY31)
5898 writes.push_back(CreateMockWrite(*session_window_update));
5899 writes.push_back(CreateMockWrite(*window_update));
5901 scoped_ptr<SpdyFrame> resp(
5902 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5903 scoped_ptr<SpdyFrame> body_no_fin(
5904 spdy_util_.ConstructSpdyBodyFrame(
5905 1, body_data.data(), body_data.size(), false));
5906 scoped_ptr<SpdyFrame> body_fin(
5907 spdy_util_.ConstructSpdyBodyFrame(1, NULL, 0, true));
5908 MockRead reads[] = {
5909 CreateMockRead(*resp),
5910 CreateMockRead(*body_no_fin),
5911 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause
5912 CreateMockRead(*body_fin),
5913 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause
5914 MockRead(ASYNC, 0, 0) // EOF
5917 DelayedSocketData data(1, reads, arraysize(reads),
5918 vector_as_array(&writes), writes.size());
5920 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5921 BoundNetLog(), GetParam(), NULL);
5922 helper.AddData(&data);
5923 helper.RunPreTestSetup();
5924 HttpNetworkTransaction* trans = helper.trans();
5926 TestCompletionCallback callback;
5927 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5929 EXPECT_EQ(ERR_IO_PENDING, rv);
5930 rv = callback.WaitForResult();
5931 EXPECT_EQ(OK, rv);
5933 SpdyHttpStream* stream =
5934 static_cast<SpdyHttpStream*>(trans->stream_.get());
5935 ASSERT_TRUE(stream != NULL);
5936 ASSERT_TRUE(stream->stream() != NULL);
5938 EXPECT_EQ(
5939 static_cast<int>(kSpdyStreamInitialWindowSize - body_data.size()),
5940 stream->stream()->recv_window_size());
5942 const HttpResponseInfo* response = trans->GetResponseInfo();
5943 ASSERT_TRUE(response != NULL);
5944 ASSERT_TRUE(response->headers.get() != NULL);
5945 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5946 EXPECT_TRUE(response->was_fetched_via_spdy);
5948 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
5949 // size increased to default.
5950 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(body_data.size()));
5951 rv = trans->Read(buf.get(), body_data.size(), CompletionCallback());
5952 EXPECT_EQ(static_cast<int>(body_data.size()), rv);
5953 std::string content(buf->data(), buf->data() + body_data.size());
5954 EXPECT_EQ(body_data, content);
5956 // Schedule the reading of empty data frame with FIN
5957 data.CompleteRead();
5959 // Force write of WINDOW_UPDATE which was scheduled during the above
5960 // read.
5961 base::RunLoop().RunUntilIdle();
5963 // Read EOF.
5964 data.CompleteRead();
5966 helper.VerifyDataConsumed();
5969 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
5970 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
5971 if (GetParam().protocol < kProtoSPDY3)
5972 return;
5974 // Number of full frames we hope to write (but will not, used to
5975 // set content-length header correctly)
5976 static int kFrameCount = 3;
5978 scoped_ptr<std::string> content(
5979 new std::string(kMaxSpdyFrameChunkSize, 'a'));
5980 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
5981 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
5982 scoped_ptr<SpdyFrame> body(
5983 spdy_util_.ConstructSpdyBodyFrame(
5984 1, content->c_str(), content->size(), false));
5985 scoped_ptr<SpdyFrame> rst(
5986 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
5988 // We're not going to write a data frame with FIN, we'll receive a bad
5989 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
5990 MockWrite writes[] = {
5991 CreateMockWrite(*req, 0),
5992 CreateMockWrite(*body, 2),
5993 CreateMockWrite(*rst, 3),
5996 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow
5997 scoped_ptr<SpdyFrame> window_update(
5998 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5999 MockRead reads[] = {
6000 CreateMockRead(*window_update, 1),
6001 MockRead(ASYNC, 0, 4) // EOF
6004 DeterministicSocketData data(reads, arraysize(reads),
6005 writes, arraysize(writes));
6007 ScopedVector<UploadElementReader> element_readers;
6008 for (int i = 0; i < kFrameCount; ++i) {
6009 element_readers.push_back(
6010 new UploadBytesElementReader(content->c_str(), content->size()));
6012 UploadDataStream upload_data_stream(&element_readers, 0);
6014 // Setup the request
6015 HttpRequestInfo request;
6016 request.method = "POST";
6017 request.url = GURL("http://www.google.com/");
6018 request.upload_data_stream = &upload_data_stream;
6020 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6021 BoundNetLog(), GetParam(), NULL);
6022 helper.SetDeterministic();
6023 helper.RunPreTestSetup();
6024 helper.AddDeterministicData(&data);
6025 HttpNetworkTransaction* trans = helper.trans();
6027 TestCompletionCallback callback;
6028 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6029 ASSERT_EQ(ERR_IO_PENDING, rv);
6031 data.RunFor(5);
6032 ASSERT_TRUE(callback.have_result());
6033 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
6034 helper.VerifyDataConsumed();
6037 // Test that after hitting a send window size of 0, the write process
6038 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
6040 // This test constructs a POST request followed by enough data frames
6041 // containing 'a' that would make the window size 0, followed by another
6042 // data frame containing default content (which is "hello!") and this frame
6043 // also contains a FIN flag. DelayedSocketData is used to enforce all
6044 // writes go through before a read could happen. However, the last frame
6045 // ("hello!") is not supposed to go through since by the time its turn
6046 // arrives, window size is 0. At this point MessageLoop::Run() called via
6047 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
6048 // which returns after performing all possible writes. We use DCHECKS to
6049 // ensure that last data frame is still there and stream has stalled.
6050 // After that, next read is artifically enforced, which causes a
6051 // WINDOW_UPDATE to be read and I/O process resumes.
6052 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
6053 if (GetParam().protocol < kProtoSPDY3)
6054 return;
6056 // Number of frames we need to send to zero out the window size: data
6057 // frames plus SYN_STREAM plus the last data frame; also we need another
6058 // data frame that we will send once the WINDOW_UPDATE is received,
6059 // therefore +3.
6060 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
6062 // Calculate last frame's size; 0 size data frame is legal.
6063 size_t last_frame_size =
6064 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6066 // Construct content for a data frame of maximum size.
6067 std::string content(kMaxSpdyFrameChunkSize, 'a');
6069 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6070 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6071 LOWEST, NULL, 0));
6073 // Full frames.
6074 scoped_ptr<SpdyFrame> body1(
6075 spdy_util_.ConstructSpdyBodyFrame(
6076 1, content.c_str(), content.size(), false));
6078 // Last frame to zero out the window size.
6079 scoped_ptr<SpdyFrame> body2(
6080 spdy_util_.ConstructSpdyBodyFrame(
6081 1, content.c_str(), last_frame_size, false));
6083 // Data frame to be sent once WINDOW_UPDATE frame is received.
6084 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6086 // Fill in mock writes.
6087 scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
6088 size_t i = 0;
6089 writes[i] = CreateMockWrite(*req);
6090 for (i = 1; i < num_writes - 2; i++)
6091 writes[i] = CreateMockWrite(*body1);
6092 writes[i++] = CreateMockWrite(*body2);
6093 writes[i] = CreateMockWrite(*body3);
6095 // Construct read frame, give enough space to upload the rest of the
6096 // data.
6097 scoped_ptr<SpdyFrame> session_window_update(
6098 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6099 scoped_ptr<SpdyFrame> window_update(
6100 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
6101 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6102 MockRead reads[] = {
6103 CreateMockRead(*session_window_update),
6104 CreateMockRead(*session_window_update),
6105 CreateMockRead(*window_update),
6106 CreateMockRead(*window_update),
6107 CreateMockRead(*reply),
6108 CreateMockRead(*body2),
6109 CreateMockRead(*body3),
6110 MockRead(ASYNC, 0, 0) // EOF
6113 // Skip the session window updates unless we're using SPDY/3.1 and
6114 // above.
6115 size_t read_offset = (GetParam().protocol >= kProtoSPDY31) ? 0 : 2;
6116 size_t num_reads = arraysize(reads) - read_offset;
6118 // Force all writes to happen before any read, last write will not
6119 // actually queue a frame, due to window size being 0.
6120 DelayedSocketData data(num_writes, reads + read_offset, num_reads,
6121 writes.get(), num_writes);
6123 ScopedVector<UploadElementReader> element_readers;
6124 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6125 upload_data_string.append(kUploadData, kUploadDataSize);
6126 element_readers.push_back(new UploadBytesElementReader(
6127 upload_data_string.c_str(), upload_data_string.size()));
6128 UploadDataStream upload_data_stream(&element_readers, 0);
6130 HttpRequestInfo request;
6131 request.method = "POST";
6132 request.url = GURL("http://www.google.com/");
6133 request.upload_data_stream = &upload_data_stream;
6134 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6135 BoundNetLog(), GetParam(), NULL);
6136 helper.AddData(&data);
6137 helper.RunPreTestSetup();
6139 HttpNetworkTransaction* trans = helper.trans();
6141 TestCompletionCallback callback;
6142 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6143 EXPECT_EQ(ERR_IO_PENDING, rv);
6145 base::RunLoop().RunUntilIdle(); // Write as much as we can.
6147 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6148 ASSERT_TRUE(stream != NULL);
6149 ASSERT_TRUE(stream->stream() != NULL);
6150 EXPECT_EQ(0, stream->stream()->send_window_size());
6151 // All the body data should have been read.
6152 // TODO(satorux): This is because of the weirdness in reading the request
6153 // body in OnSendBodyComplete(). See crbug.com/113107.
6154 EXPECT_TRUE(upload_data_stream.IsEOF());
6155 // But the body is not yet fully sent (kUploadData is not yet sent)
6156 // since we're send-stalled.
6157 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6159 data.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6160 rv = callback.WaitForResult();
6161 helper.VerifyDataConsumed();
6164 // Test we correctly handle the case where the SETTINGS frame results in
6165 // unstalling the send window.
6166 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
6167 if (GetParam().protocol < kProtoSPDY3)
6168 return;
6170 // Number of frames we need to send to zero out the window size: data
6171 // frames plus SYN_STREAM plus the last data frame; also we need another
6172 // data frame that we will send once the SETTING is received, therefore +3.
6173 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
6175 // Calculate last frame's size; 0 size data frame is legal.
6176 size_t last_frame_size =
6177 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6179 // Construct content for a data frame of maximum size.
6180 std::string content(kMaxSpdyFrameChunkSize, 'a');
6182 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6183 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6184 LOWEST, NULL, 0));
6186 // Full frames.
6187 scoped_ptr<SpdyFrame> body1(
6188 spdy_util_.ConstructSpdyBodyFrame(
6189 1, content.c_str(), content.size(), false));
6191 // Last frame to zero out the window size.
6192 scoped_ptr<SpdyFrame> body2(
6193 spdy_util_.ConstructSpdyBodyFrame(
6194 1, content.c_str(), last_frame_size, false));
6196 // Data frame to be sent once SETTINGS frame is received.
6197 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6199 // Fill in mock reads/writes.
6200 std::vector<MockRead> reads;
6201 std::vector<MockWrite> writes;
6202 size_t i = 0;
6203 writes.push_back(CreateMockWrite(*req, i++));
6204 while (i < num_writes - 2)
6205 writes.push_back(CreateMockWrite(*body1, i++));
6206 writes.push_back(CreateMockWrite(*body2, i++));
6208 // Construct read frame for SETTINGS that gives enough space to upload the
6209 // rest of the data.
6210 SettingsMap settings;
6211 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6212 SettingsFlagsAndValue(
6213 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize * 2);
6214 scoped_ptr<SpdyFrame> settings_frame_large(
6215 spdy_util_.ConstructSpdySettings(settings));
6217 reads.push_back(CreateMockRead(*settings_frame_large, i++));
6219 scoped_ptr<SpdyFrame> session_window_update(
6220 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6221 if (GetParam().protocol >= kProtoSPDY31)
6222 reads.push_back(CreateMockRead(*session_window_update, i++));
6224 writes.push_back(CreateMockWrite(*body3, i++));
6226 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6227 reads.push_back(CreateMockRead(*reply, i++));
6228 reads.push_back(CreateMockRead(*body2, i++));
6229 reads.push_back(CreateMockRead(*body3, i++));
6230 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6232 // Force all writes to happen before any read, last write will not
6233 // actually queue a frame, due to window size being 0.
6234 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6235 vector_as_array(&writes), writes.size());
6237 ScopedVector<UploadElementReader> element_readers;
6238 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6239 upload_data_string.append(kUploadData, kUploadDataSize);
6240 element_readers.push_back(new UploadBytesElementReader(
6241 upload_data_string.c_str(), upload_data_string.size()));
6242 UploadDataStream upload_data_stream(&element_readers, 0);
6244 HttpRequestInfo request;
6245 request.method = "POST";
6246 request.url = GURL("http://www.google.com/");
6247 request.upload_data_stream = &upload_data_stream;
6248 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6249 BoundNetLog(), GetParam(), NULL);
6250 helper.SetDeterministic();
6251 helper.RunPreTestSetup();
6252 helper.AddDeterministicData(&data);
6254 HttpNetworkTransaction* trans = helper.trans();
6256 TestCompletionCallback callback;
6257 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6258 EXPECT_EQ(ERR_IO_PENDING, rv);
6260 data.RunFor(num_writes - 1); // Write as much as we can.
6262 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6263 ASSERT_TRUE(stream != NULL);
6264 ASSERT_TRUE(stream->stream() != NULL);
6265 EXPECT_EQ(0, stream->stream()->send_window_size());
6267 // All the body data should have been read.
6268 // TODO(satorux): This is because of the weirdness in reading the request
6269 // body in OnSendBodyComplete(). See crbug.com/113107.
6270 EXPECT_TRUE(upload_data_stream.IsEOF());
6271 // But the body is not yet fully sent (kUploadData is not yet sent)
6272 // since we're send-stalled.
6273 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6275 data.RunFor(6); // Read in SETTINGS frame to unstall.
6276 rv = callback.WaitForResult();
6277 helper.VerifyDataConsumed();
6278 // If stream is NULL, that means it was unstalled and closed.
6279 EXPECT_TRUE(stream->stream() == NULL);
6282 // Test we correctly handle the case where the SETTINGS frame results in a
6283 // negative send window size.
6284 TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
6285 if (GetParam().protocol < kProtoSPDY3)
6286 return;
6288 // Number of frames we need to send to zero out the window size: data
6289 // frames plus SYN_STREAM plus the last data frame; also we need another
6290 // data frame that we will send once the SETTING is received, therefore +3.
6291 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
6293 // Calculate last frame's size; 0 size data frame is legal.
6294 size_t last_frame_size =
6295 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6297 // Construct content for a data frame of maximum size.
6298 std::string content(kMaxSpdyFrameChunkSize, 'a');
6300 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6301 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6302 LOWEST, NULL, 0));
6304 // Full frames.
6305 scoped_ptr<SpdyFrame> body1(
6306 spdy_util_.ConstructSpdyBodyFrame(
6307 1, content.c_str(), content.size(), false));
6309 // Last frame to zero out the window size.
6310 scoped_ptr<SpdyFrame> body2(
6311 spdy_util_.ConstructSpdyBodyFrame(
6312 1, content.c_str(), last_frame_size, false));
6314 // Data frame to be sent once SETTINGS frame is received.
6315 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6317 // Fill in mock reads/writes.
6318 std::vector<MockRead> reads;
6319 std::vector<MockWrite> writes;
6320 size_t i = 0;
6321 writes.push_back(CreateMockWrite(*req, i++));
6322 while (i < num_writes - 2)
6323 writes.push_back(CreateMockWrite(*body1, i++));
6324 writes.push_back(CreateMockWrite(*body2, i++));
6326 // Construct read frame for SETTINGS that makes the send_window_size
6327 // negative.
6328 SettingsMap new_settings;
6329 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6330 SettingsFlagsAndValue(
6331 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize / 2);
6332 scoped_ptr<SpdyFrame> settings_frame_small(
6333 spdy_util_.ConstructSpdySettings(new_settings));
6334 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6335 // positive.
6336 scoped_ptr<SpdyFrame> session_window_update_init_size(
6337 spdy_util_.ConstructSpdyWindowUpdate(0, kSpdyStreamInitialWindowSize));
6338 scoped_ptr<SpdyFrame> window_update_init_size(
6339 spdy_util_.ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize));
6341 reads.push_back(CreateMockRead(*settings_frame_small, i++));
6343 if (GetParam().protocol >= kProtoSPDY3)
6344 reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
6346 reads.push_back(CreateMockRead(*window_update_init_size, i++));
6348 writes.push_back(CreateMockWrite(*body3, i++));
6350 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6351 reads.push_back(CreateMockRead(*reply, i++));
6352 reads.push_back(CreateMockRead(*body2, i++));
6353 reads.push_back(CreateMockRead(*body3, i++));
6354 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6356 // Force all writes to happen before any read, last write will not
6357 // actually queue a frame, due to window size being 0.
6358 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6359 vector_as_array(&writes), writes.size());
6361 ScopedVector<UploadElementReader> element_readers;
6362 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6363 upload_data_string.append(kUploadData, kUploadDataSize);
6364 element_readers.push_back(new UploadBytesElementReader(
6365 upload_data_string.c_str(), upload_data_string.size()));
6366 UploadDataStream upload_data_stream(&element_readers, 0);
6368 HttpRequestInfo request;
6369 request.method = "POST";
6370 request.url = GURL("http://www.google.com/");
6371 request.upload_data_stream = &upload_data_stream;
6372 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6373 BoundNetLog(), GetParam(), NULL);
6374 helper.SetDeterministic();
6375 helper.RunPreTestSetup();
6376 helper.AddDeterministicData(&data);
6378 HttpNetworkTransaction* trans = helper.trans();
6380 TestCompletionCallback callback;
6381 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6382 EXPECT_EQ(ERR_IO_PENDING, rv);
6384 data.RunFor(num_writes - 1); // Write as much as we can.
6386 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6387 ASSERT_TRUE(stream != NULL);
6388 ASSERT_TRUE(stream->stream() != NULL);
6389 EXPECT_EQ(0, stream->stream()->send_window_size());
6391 // All the body data should have been read.
6392 // TODO(satorux): This is because of the weirdness in reading the request
6393 // body in OnSendBodyComplete(). See crbug.com/113107.
6394 EXPECT_TRUE(upload_data_stream.IsEOF());
6395 // But the body is not yet fully sent (kUploadData is not yet sent)
6396 // since we're send-stalled.
6397 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6399 // Read in WINDOW_UPDATE or SETTINGS frame.
6400 data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 8 : 7);
6401 rv = callback.WaitForResult();
6402 helper.VerifyDataConsumed();
6405 } // namespace net