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.
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 //-----------------------------------------------------------------------------
42 const char kRequestUrl[] = "http://www.google.com/";
44 enum SpdyNetworkTransactionTestSSLType {
50 struct SpdyNetworkTransactionTestParams {
51 SpdyNetworkTransactionTestParams()
52 : protocol(kProtoSPDY3),
55 SpdyNetworkTransactionTestParams(
57 SpdyNetworkTransactionTestSSLType ssl_type)
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);
78 class SpdyNetworkTransactionTest
79 : public ::testing::TestWithParam<SpdyNetworkTransactionTestParams> {
81 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol) {
84 virtual ~SpdyNetworkTransactionTest() {
85 // UploadDataStream posts deletion tasks back to the message loop on
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 {
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 {
108 NormalSpdyTransactionHelper(const HttpRequestInfo& request,
109 RequestPriority priority,
110 const BoundNetLog& log,
111 SpdyNetworkTransactionTestParams test_params,
112 SpdySessionDependencies* session_deps)
115 session_deps_(session_deps == NULL ?
116 CreateSpdySessionDependencies(test_params) :
118 session_(SpdySessionDependencies::SpdyCreateSession(
119 session_deps_.get())),
121 test_params_(test_params),
122 deterministic_(false),
123 spdy_enabled_(true) {
124 switch (test_params_.ssl_type) {
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;
160 void RunPreTestSetup() {
161 if (!session_deps_.get())
162 session_deps_.reset(CreateSpdySessionDependencies(test_params_));
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) {
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);
181 HttpStreamFactory::set_force_spdy_over_ssl(false);
182 HttpStreamFactory::set_force_spdy_always(true);
185 HttpStreamFactory::set_force_spdy_over_ssl(true);
186 HttpStreamFactory::set_force_spdy_always(true);
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())
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);
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()) {
226 HttpResponseInfo::ConnectionInfoFromNextProto(
227 test_params_.protocol),
228 response->connection_info);
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);
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()
260 << (*it)->read_index();
261 EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
262 << (*it)->write_count()
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
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()
277 << (*it)->read_index();
278 EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
279 << (*it)->write_count()
281 << (*it)->write_index();
285 void RunToCompletion(StaticSocketDataProvider* data) {
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) {
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 {
355 scoped_ptr<SpdySessionDependencies>& session_deps() {
356 return session_deps_;
358 int port() const { return port_; }
359 SpdyNetworkTransactionTestParams test_params() const {
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_;
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(
427 new UploadDataStream(element_readers.Pass(), 0));
429 google_post_request_.method = "POST";
430 google_post_request_.url = GURL(kDefaultURL);
431 google_post_request_.upload_data_stream = upload_data_stream_.get();
432 google_post_request_initialized_ = true;
434 return google_post_request_;
437 const HttpRequestInfo& CreateFilePostRequest() {
438 if (!google_post_request_initialized_) {
439 base::FilePath file_path;
440 CHECK(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
441 CHECK_EQ(static_cast<int>(kUploadDataSize),
442 file_util::WriteFile(file_path, kUploadData, kUploadDataSize));
444 ScopedVector<UploadElementReader> element_readers;
445 element_readers.push_back(
446 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
451 upload_data_stream_.reset(
452 new UploadDataStream(element_readers.Pass(), 0));
454 google_post_request_.method = "POST";
455 google_post_request_.url = GURL(kDefaultURL);
456 google_post_request_.upload_data_stream = upload_data_stream_.get();
457 google_post_request_initialized_ = true;
459 return google_post_request_;
462 const HttpRequestInfo& CreateComplexPostRequest() {
463 if (!google_post_request_initialized_) {
464 const int kFileRangeOffset = 1;
465 const int kFileRangeLength = 3;
466 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
468 base::FilePath file_path;
469 CHECK(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
470 CHECK_EQ(static_cast<int>(kUploadDataSize),
471 file_util::WriteFile(file_path, kUploadData, kUploadDataSize));
473 ScopedVector<UploadElementReader> element_readers;
474 element_readers.push_back(
475 new UploadBytesElementReader(kUploadData, kFileRangeOffset));
476 element_readers.push_back(
477 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
482 element_readers.push_back(new UploadBytesElementReader(
483 kUploadData + kFileRangeOffset + kFileRangeLength,
484 kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
485 upload_data_stream_.reset(
486 new UploadDataStream(element_readers.Pass(), 0));
488 google_post_request_.method = "POST";
489 google_post_request_.url = GURL(kDefaultURL);
490 google_post_request_.upload_data_stream = upload_data_stream_.get();
491 google_post_request_initialized_ = true;
493 return google_post_request_;
496 const HttpRequestInfo& CreateChunkedPostRequest() {
497 if (!google_chunked_post_request_initialized_) {
498 upload_data_stream_.reset(
499 new UploadDataStream(UploadDataStream::CHUNKED, 0));
500 google_chunked_post_request_.method = "POST";
501 google_chunked_post_request_.url = GURL(kDefaultURL);
502 google_chunked_post_request_.upload_data_stream =
503 upload_data_stream_.get();
504 google_chunked_post_request_initialized_ = true;
506 return google_chunked_post_request_;
509 // Read the result of a particular transaction, knowing that we've got
510 // multiple transactions in the read pipeline; so as we read, we may have
511 // to skip over data destined for other transactions while we consume
512 // the data for |trans|.
513 int ReadResult(HttpNetworkTransaction* trans,
514 StaticSocketDataProvider* data,
515 std::string* result) {
516 const int kSize = 3000;
519 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
520 TestCompletionCallback callback;
522 int rv = trans->Read(buf.get(), kSize, callback.callback());
523 if (rv == ERR_IO_PENDING) {
524 // Multiple transactions may be in the data set. Keep pulling off
525 // reads until we complete our callback.
526 while (!callback.have_result()) {
527 data->CompleteRead();
528 base::RunLoop().RunUntilIdle();
530 rv = callback.WaitForResult();
531 } else if (rv <= 0) {
534 result->append(buf->data(), rv);
540 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
541 // This lengthy block is reaching into the pool to dig out the active
542 // session. Once we have the session, we verify that the streams are
543 // all closed and not leaked at this point.
544 const GURL& url = helper.request().url;
545 int port = helper.test_params().ssl_type == SPDYNPN ? 443 : 80;
546 HostPortPair host_port_pair(url.host(), port);
547 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
548 kPrivacyModeDisabled);
550 const scoped_refptr<HttpNetworkSession>& session = helper.session();
551 base::WeakPtr<SpdySession> spdy_session =
552 session->spdy_session_pool()->FindAvailableSession(key, log);
553 ASSERT_TRUE(spdy_session != NULL);
554 EXPECT_EQ(0u, spdy_session->num_active_streams());
555 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
558 void RunServerPushTest(OrderedSocketData* data,
559 HttpResponseInfo* response,
560 HttpResponseInfo* push_response,
561 const std::string& expected) {
562 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
563 BoundNetLog(), GetParam(), NULL);
564 helper.RunPreTestSetup();
565 helper.AddData(data);
567 HttpNetworkTransaction* trans = helper.trans();
569 // Start the transaction with basic parameters.
570 TestCompletionCallback callback;
571 int rv = trans->Start(
572 &CreateGetRequest(), callback.callback(), BoundNetLog());
573 EXPECT_EQ(ERR_IO_PENDING, rv);
574 rv = callback.WaitForResult();
576 // Request the pushed path.
577 scoped_ptr<HttpNetworkTransaction> trans2(
578 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
580 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
581 EXPECT_EQ(ERR_IO_PENDING, rv);
582 base::RunLoop().RunUntilIdle();
584 // The data for the pushed path may be coming in more than 1 frame. Compile
585 // the results into a single string.
587 // Read the server push body.
589 ReadResult(trans2.get(), data, &result2);
590 // Read the response body.
592 ReadResult(trans, data, &result);
594 // Verify that we consumed all test data.
595 EXPECT_TRUE(data->at_read_eof());
596 EXPECT_TRUE(data->at_write_eof());
598 // Verify that the received push data is same as the expected push data.
599 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
601 << "||||| Expected data: "
604 // Verify the SYN_REPLY.
605 // Copy the response info, because trans goes away.
606 *response = *trans->GetResponseInfo();
607 *push_response = *trans2->GetResponseInfo();
609 VerifyStreamsClosed(helper);
612 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
614 helper->ResetTrans();
617 static void StartTransactionCallback(
618 const scoped_refptr<HttpNetworkSession>& session,
620 scoped_ptr<HttpNetworkTransaction> trans(
621 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
622 TestCompletionCallback callback;
623 HttpRequestInfo request;
624 request.method = "GET";
625 request.url = GURL("http://www.google.com/");
626 request.load_flags = 0;
627 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
628 EXPECT_EQ(ERR_IO_PENDING, rv);
629 callback.WaitForResult();
632 SpdyTestUtil spdy_util_;
635 scoped_ptr<UploadDataStream> upload_data_stream_;
636 bool google_get_request_initialized_;
637 bool google_post_request_initialized_;
638 bool google_chunked_post_request_initialized_;
639 HttpRequestInfo google_get_request_;
640 HttpRequestInfo google_post_request_;
641 HttpRequestInfo google_chunked_post_request_;
642 HttpRequestInfo google_get_push_request_;
643 base::ScopedTempDir temp_dir_;
646 //-----------------------------------------------------------------------------
647 // All tests are run with three different connection types: SPDY after NPN
648 // negotiation, SPDY without SSL, and SPDY with SSL.
650 // TODO(akalin): Use ::testing::Combine() when we are able to use
652 INSTANTIATE_TEST_CASE_P(
654 SpdyNetworkTransactionTest,
656 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNOSSL),
657 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYSSL),
658 SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNPN),
659 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNOSSL),
660 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYSSL),
661 SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNPN),
662 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNOSSL),
663 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYSSL),
664 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN),
665 SpdyNetworkTransactionTestParams(kProtoSPDY4a2, SPDYNOSSL),
666 SpdyNetworkTransactionTestParams(kProtoSPDY4a2, SPDYSSL),
667 SpdyNetworkTransactionTestParams(kProtoSPDY4a2, SPDYNPN),
668 SpdyNetworkTransactionTestParams(kProtoHTTP2Draft04, SPDYNOSSL),
669 SpdyNetworkTransactionTestParams(kProtoHTTP2Draft04, SPDYSSL),
670 SpdyNetworkTransactionTestParams(kProtoHTTP2Draft04, SPDYNPN)));
672 // Verify HttpNetworkTransaction constructor.
673 TEST_P(SpdyNetworkTransactionTest, Constructor) {
674 scoped_ptr<SpdySessionDependencies> session_deps(
675 CreateSpdySessionDependencies(GetParam()));
676 scoped_refptr<HttpNetworkSession> session(
677 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
678 scoped_ptr<HttpTransaction> trans(
679 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
682 TEST_P(SpdyNetworkTransactionTest, Get) {
683 // Construct the request.
684 scoped_ptr<SpdyFrame> req(
685 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
686 MockWrite writes[] = { CreateMockWrite(*req) };
688 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
689 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
691 CreateMockRead(*resp),
692 CreateMockRead(*body),
693 MockRead(ASYNC, 0, 0) // EOF
696 DelayedSocketData data(1, reads, arraysize(reads),
697 writes, arraysize(writes));
698 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
699 BoundNetLog(), GetParam(), NULL);
700 helper.RunToCompletion(&data);
701 TransactionHelperResult out = helper.output();
702 EXPECT_EQ(OK, out.rv);
703 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
704 EXPECT_EQ("hello!", out.response_data);
707 TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
708 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
709 p = RequestPriority(p + 1)) {
710 // Construct the request.
711 scoped_ptr<SpdyFrame> req(
712 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true));
713 MockWrite writes[] = { CreateMockWrite(*req) };
715 SpdyPriority spdy_prio = 0;
716 EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio));
717 // this repeats the RequestPriority-->SpdyPriority mapping from
718 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
719 // sure it's being done right.
720 if (spdy_util_.spdy_version() < SPDY3) {
723 EXPECT_EQ(0, spdy_prio);
726 EXPECT_EQ(1, spdy_prio);
730 EXPECT_EQ(2, spdy_prio);
733 EXPECT_EQ(3, spdy_prio);
741 EXPECT_EQ(0, spdy_prio);
744 EXPECT_EQ(1, spdy_prio);
747 EXPECT_EQ(2, spdy_prio);
750 EXPECT_EQ(3, spdy_prio);
753 EXPECT_EQ(4, spdy_prio);
760 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
761 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
763 CreateMockRead(*resp),
764 CreateMockRead(*body),
765 MockRead(ASYNC, 0, 0) // EOF
768 DelayedSocketData data(1, reads, arraysize(reads),
769 writes, arraysize(writes));
770 HttpRequestInfo http_req = CreateGetRequest();
772 NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(),
774 helper.RunToCompletion(&data);
775 TransactionHelperResult out = helper.output();
776 EXPECT_EQ(OK, out.rv);
777 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
778 EXPECT_EQ("hello!", out.response_data);
782 // Start three gets simultaniously; making sure that multiplexed
783 // streams work properly.
785 // This can't use the TransactionHelper method, since it only
786 // handles a single transaction, and finishes them as soon
787 // as it launches them.
789 // TODO(gavinp): create a working generalized TransactionHelper that
790 // can allow multiple streams in flight.
792 TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
793 scoped_ptr<SpdyFrame> req(
794 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
795 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
796 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
797 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
799 scoped_ptr<SpdyFrame> req2(
800 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
801 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
802 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
803 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
805 scoped_ptr<SpdyFrame> req3(
806 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
807 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
808 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
809 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
811 MockWrite writes[] = {
812 CreateMockWrite(*req),
813 CreateMockWrite(*req2),
814 CreateMockWrite(*req3),
817 CreateMockRead(*resp, 1),
818 CreateMockRead(*body),
819 CreateMockRead(*resp2, 4),
820 CreateMockRead(*body2),
821 CreateMockRead(*resp3, 7),
822 CreateMockRead(*body3),
824 CreateMockRead(*fbody),
825 CreateMockRead(*fbody2),
826 CreateMockRead(*fbody3),
828 MockRead(ASYNC, 0, 0), // EOF
830 OrderedSocketData data(reads, arraysize(reads),
831 writes, arraysize(writes));
832 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
835 TransactionHelperResult out;
836 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
837 BoundNetLog(), GetParam(), NULL);
838 helper.RunPreTestSetup();
839 helper.AddData(&data);
840 // We require placeholder data because three get requests are sent out, so
841 // there needs to be three sets of SSL connection data.
842 helper.AddData(&data_placeholder);
843 helper.AddData(&data_placeholder);
844 scoped_ptr<HttpNetworkTransaction> trans1(
845 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
846 scoped_ptr<HttpNetworkTransaction> trans2(
847 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
848 scoped_ptr<HttpNetworkTransaction> trans3(
849 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
851 TestCompletionCallback callback1;
852 TestCompletionCallback callback2;
853 TestCompletionCallback callback3;
855 HttpRequestInfo httpreq1 = CreateGetRequest();
856 HttpRequestInfo httpreq2 = CreateGetRequest();
857 HttpRequestInfo httpreq3 = CreateGetRequest();
859 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
860 ASSERT_EQ(ERR_IO_PENDING, out.rv);
861 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
862 ASSERT_EQ(ERR_IO_PENDING, out.rv);
863 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
864 ASSERT_EQ(ERR_IO_PENDING, out.rv);
866 out.rv = callback1.WaitForResult();
867 ASSERT_EQ(OK, out.rv);
868 out.rv = callback3.WaitForResult();
869 ASSERT_EQ(OK, out.rv);
871 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
872 EXPECT_TRUE(response1->headers.get() != NULL);
873 EXPECT_TRUE(response1->was_fetched_via_spdy);
874 out.status_line = response1->headers->GetStatusLine();
875 out.response_info = *response1;
877 trans2->GetResponseInfo();
879 out.rv = ReadTransaction(trans1.get(), &out.response_data);
880 helper.VerifyDataConsumed();
881 EXPECT_EQ(OK, out.rv);
883 EXPECT_EQ(OK, out.rv);
884 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
885 EXPECT_EQ("hello!hello!", out.response_data);
888 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
889 scoped_ptr<SpdyFrame> req(
890 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
891 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
892 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
893 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
895 scoped_ptr<SpdyFrame> req2(
896 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
897 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
898 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
899 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
901 MockWrite writes[] = {
902 CreateMockWrite(*req),
903 CreateMockWrite(*req2),
906 CreateMockRead(*resp, 1),
907 CreateMockRead(*body),
908 CreateMockRead(*resp2, 4),
909 CreateMockRead(*body2),
910 CreateMockRead(*fbody),
911 CreateMockRead(*fbody2),
912 MockRead(ASYNC, 0, 0), // EOF
914 OrderedSocketData data(reads, arraysize(reads),
915 writes, arraysize(writes));
917 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
919 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
920 data_placeholder.set_connect_data(never_finishing_connect);
923 TransactionHelperResult out;
924 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
925 BoundNetLog(), GetParam(), NULL);
926 helper.RunPreTestSetup();
927 helper.AddData(&data);
928 // We require placeholder data because two get requests are sent out, so
929 // there needs to be two sets of SSL connection data.
930 helper.AddData(&data_placeholder);
931 scoped_ptr<HttpNetworkTransaction> trans1(
932 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
933 scoped_ptr<HttpNetworkTransaction> trans2(
934 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
936 TestCompletionCallback callback1;
937 TestCompletionCallback callback2;
939 HttpRequestInfo httpreq1 = CreateGetRequest();
940 HttpRequestInfo httpreq2 = CreateGetRequest();
942 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
943 ASSERT_EQ(ERR_IO_PENDING, out.rv);
944 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
945 ASSERT_EQ(ERR_IO_PENDING, out.rv);
947 out.rv = callback1.WaitForResult();
948 ASSERT_EQ(OK, out.rv);
949 out.rv = callback2.WaitForResult();
950 ASSERT_EQ(OK, out.rv);
952 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
953 EXPECT_TRUE(response1->headers.get() != NULL);
954 EXPECT_TRUE(response1->was_fetched_via_spdy);
955 out.status_line = response1->headers->GetStatusLine();
956 out.response_info = *response1;
957 out.rv = ReadTransaction(trans1.get(), &out.response_data);
958 EXPECT_EQ(OK, out.rv);
959 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
960 EXPECT_EQ("hello!hello!", out.response_data);
962 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
963 EXPECT_TRUE(response2->headers.get() != NULL);
964 EXPECT_TRUE(response2->was_fetched_via_spdy);
965 out.status_line = response2->headers->GetStatusLine();
966 out.response_info = *response2;
967 out.rv = ReadTransaction(trans2.get(), &out.response_data);
968 EXPECT_EQ(OK, out.rv);
969 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
970 EXPECT_EQ("hello!hello!", out.response_data);
972 helper.VerifyDataConsumed();
975 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
976 scoped_ptr<SpdyFrame> req(
977 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
978 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
979 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
980 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
982 scoped_ptr<SpdyFrame> req2(
983 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
984 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
985 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
986 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
988 MockWrite writes[] = {
989 CreateMockWrite(*req),
990 CreateMockWrite(*req2),
993 CreateMockRead(*resp, 1),
994 CreateMockRead(*body),
995 CreateMockRead(*resp2, 4),
996 CreateMockRead(*body2),
997 CreateMockRead(*fbody),
998 CreateMockRead(*fbody2),
999 MockRead(ASYNC, 0, 0), // EOF
1001 OrderedSocketData preconnect_data(reads, arraysize(reads),
1002 writes, arraysize(writes));
1004 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
1006 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1007 data_placeholder.set_connect_data(never_finishing_connect);
1010 TransactionHelperResult out;
1011 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1012 BoundNetLog(), GetParam(), NULL);
1013 helper.RunPreTestSetup();
1014 helper.AddData(&preconnect_data);
1015 // We require placeholder data because 3 connections are attempted (first is
1016 // the preconnect, 2nd and 3rd are the never finished connections.
1017 helper.AddData(&data_placeholder);
1018 helper.AddData(&data_placeholder);
1020 scoped_ptr<HttpNetworkTransaction> trans1(
1021 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1022 scoped_ptr<HttpNetworkTransaction> trans2(
1023 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1025 TestCompletionCallback callback1;
1026 TestCompletionCallback callback2;
1028 HttpRequestInfo httpreq = CreateGetRequest();
1030 // Preconnect the first.
1031 SSLConfig preconnect_ssl_config;
1032 helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
1033 HttpStreamFactory* http_stream_factory =
1034 helper.session()->http_stream_factory();
1035 if (http_stream_factory->has_next_protos()) {
1036 preconnect_ssl_config.next_protos = http_stream_factory->next_protos();
1039 http_stream_factory->PreconnectStreams(
1040 1, httpreq, DEFAULT_PRIORITY,
1041 preconnect_ssl_config, preconnect_ssl_config);
1043 out.rv = trans1->Start(&httpreq, callback1.callback(), log);
1044 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1045 out.rv = trans2->Start(&httpreq, callback2.callback(), log);
1046 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1048 out.rv = callback1.WaitForResult();
1049 ASSERT_EQ(OK, out.rv);
1050 out.rv = callback2.WaitForResult();
1051 ASSERT_EQ(OK, out.rv);
1053 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1054 EXPECT_TRUE(response1->headers.get() != NULL);
1055 EXPECT_TRUE(response1->was_fetched_via_spdy);
1056 out.status_line = response1->headers->GetStatusLine();
1057 out.response_info = *response1;
1058 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1059 EXPECT_EQ(OK, out.rv);
1060 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1061 EXPECT_EQ("hello!hello!", out.response_data);
1063 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1064 EXPECT_TRUE(response2->headers.get() != NULL);
1065 EXPECT_TRUE(response2->was_fetched_via_spdy);
1066 out.status_line = response2->headers->GetStatusLine();
1067 out.response_info = *response2;
1068 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1069 EXPECT_EQ(OK, out.rv);
1070 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1071 EXPECT_EQ("hello!hello!", out.response_data);
1073 helper.VerifyDataConsumed();
1076 // Similar to ThreeGets above, however this test adds a SETTINGS
1077 // frame. The SETTINGS frame is read during the IO loop waiting on
1078 // the first transaction completion, and sets a maximum concurrent
1079 // stream limit of 1. This means that our IO loop exists after the
1080 // second transaction completes, so we can assert on read_index().
1081 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
1082 // Construct the request.
1083 scoped_ptr<SpdyFrame> req(
1084 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1085 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1086 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1087 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1089 scoped_ptr<SpdyFrame> req2(
1090 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1091 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1092 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1093 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1095 scoped_ptr<SpdyFrame> req3(
1096 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
1097 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1098 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
1099 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
1101 SettingsMap settings;
1102 const uint32 max_concurrent_streams = 1;
1103 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1104 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1105 scoped_ptr<SpdyFrame> settings_frame(
1106 spdy_util_.ConstructSpdySettings(settings));
1108 MockWrite writes[] = {
1109 CreateMockWrite(*req),
1110 CreateMockWrite(*req2),
1111 CreateMockWrite(*req3),
1114 MockRead reads[] = {
1115 CreateMockRead(*settings_frame, 1),
1116 CreateMockRead(*resp),
1117 CreateMockRead(*body),
1118 CreateMockRead(*fbody),
1119 CreateMockRead(*resp2, 7),
1120 CreateMockRead(*body2),
1121 CreateMockRead(*fbody2),
1122 CreateMockRead(*resp3, 12),
1123 CreateMockRead(*body3),
1124 CreateMockRead(*fbody3),
1126 MockRead(ASYNC, 0, 0), // EOF
1129 OrderedSocketData data(reads, arraysize(reads),
1130 writes, arraysize(writes));
1131 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1134 TransactionHelperResult out;
1136 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1137 BoundNetLog(), GetParam(), NULL);
1138 helper.RunPreTestSetup();
1139 helper.AddData(&data);
1140 // We require placeholder data because three get requests are sent out, so
1141 // there needs to be three sets of SSL connection data.
1142 helper.AddData(&data_placeholder);
1143 helper.AddData(&data_placeholder);
1144 scoped_ptr<HttpNetworkTransaction> trans1(
1145 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1146 scoped_ptr<HttpNetworkTransaction> trans2(
1147 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1148 scoped_ptr<HttpNetworkTransaction> trans3(
1149 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1151 TestCompletionCallback callback1;
1152 TestCompletionCallback callback2;
1153 TestCompletionCallback callback3;
1155 HttpRequestInfo httpreq1 = CreateGetRequest();
1156 HttpRequestInfo httpreq2 = CreateGetRequest();
1157 HttpRequestInfo httpreq3 = CreateGetRequest();
1159 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1160 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1161 // Run transaction 1 through quickly to force a read of our SETTINGS
1163 out.rv = callback1.WaitForResult();
1164 ASSERT_EQ(OK, out.rv);
1166 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1167 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1168 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1169 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1170 out.rv = callback2.WaitForResult();
1171 ASSERT_EQ(OK, out.rv);
1172 EXPECT_EQ(7U, data.read_index()); // i.e. the third trans was queued
1174 out.rv = callback3.WaitForResult();
1175 ASSERT_EQ(OK, out.rv);
1177 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1178 ASSERT_TRUE(response1 != NULL);
1179 EXPECT_TRUE(response1->headers.get() != NULL);
1180 EXPECT_TRUE(response1->was_fetched_via_spdy);
1181 out.status_line = response1->headers->GetStatusLine();
1182 out.response_info = *response1;
1183 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1184 EXPECT_EQ(OK, out.rv);
1185 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1186 EXPECT_EQ("hello!hello!", out.response_data);
1188 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1189 out.status_line = response2->headers->GetStatusLine();
1190 out.response_info = *response2;
1191 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1192 EXPECT_EQ(OK, out.rv);
1193 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1194 EXPECT_EQ("hello!hello!", out.response_data);
1196 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1197 out.status_line = response3->headers->GetStatusLine();
1198 out.response_info = *response3;
1199 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1200 EXPECT_EQ(OK, out.rv);
1201 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1202 EXPECT_EQ("hello!hello!", out.response_data);
1204 helper.VerifyDataConsumed();
1206 EXPECT_EQ(OK, out.rv);
1209 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1210 // a fourth transaction. The third and fourth transactions have
1211 // different data ("hello!" vs "hello!hello!") and because of the
1212 // user specified priority, we expect to see them inverted in
1213 // the response from the server.
1214 TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
1215 // Construct the request.
1216 scoped_ptr<SpdyFrame> req(
1217 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1218 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1219 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1220 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1222 scoped_ptr<SpdyFrame> req2(
1223 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1224 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1225 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1226 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1228 scoped_ptr<SpdyFrame> req4(
1229 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true));
1230 scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1231 scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true));
1233 scoped_ptr<SpdyFrame> req3(
1234 spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true));
1235 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
1236 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false));
1237 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true));
1239 SettingsMap settings;
1240 const uint32 max_concurrent_streams = 1;
1241 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1242 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1243 scoped_ptr<SpdyFrame> settings_frame(
1244 spdy_util_.ConstructSpdySettings(settings));
1246 MockWrite writes[] = { CreateMockWrite(*req),
1247 CreateMockWrite(*req2),
1248 CreateMockWrite(*req4),
1249 CreateMockWrite(*req3),
1251 MockRead reads[] = {
1252 CreateMockRead(*settings_frame, 1),
1253 CreateMockRead(*resp),
1254 CreateMockRead(*body),
1255 CreateMockRead(*fbody),
1256 CreateMockRead(*resp2, 7),
1257 CreateMockRead(*body2),
1258 CreateMockRead(*fbody2),
1259 CreateMockRead(*resp4, 13),
1260 CreateMockRead(*fbody4),
1261 CreateMockRead(*resp3, 16),
1262 CreateMockRead(*body3),
1263 CreateMockRead(*fbody3),
1265 MockRead(ASYNC, 0, 0), // EOF
1268 OrderedSocketData data(reads, arraysize(reads),
1269 writes, arraysize(writes));
1270 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1273 TransactionHelperResult out;
1274 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1275 BoundNetLog(), GetParam(), NULL);
1276 helper.RunPreTestSetup();
1277 helper.AddData(&data);
1278 // We require placeholder data because four get requests are sent out, so
1279 // there needs to be four sets of SSL connection data.
1280 helper.AddData(&data_placeholder);
1281 helper.AddData(&data_placeholder);
1282 helper.AddData(&data_placeholder);
1283 scoped_ptr<HttpNetworkTransaction> trans1(
1284 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1285 scoped_ptr<HttpNetworkTransaction> trans2(
1286 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1287 scoped_ptr<HttpNetworkTransaction> trans3(
1288 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1289 scoped_ptr<HttpNetworkTransaction> trans4(
1290 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
1292 TestCompletionCallback callback1;
1293 TestCompletionCallback callback2;
1294 TestCompletionCallback callback3;
1295 TestCompletionCallback callback4;
1297 HttpRequestInfo httpreq1 = CreateGetRequest();
1298 HttpRequestInfo httpreq2 = CreateGetRequest();
1299 HttpRequestInfo httpreq3 = CreateGetRequest();
1300 HttpRequestInfo httpreq4 = CreateGetRequest();
1302 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1303 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1304 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1305 out.rv = callback1.WaitForResult();
1306 ASSERT_EQ(OK, out.rv);
1308 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1309 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1310 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1311 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1312 out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
1313 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1315 out.rv = callback2.WaitForResult();
1316 ASSERT_EQ(OK, out.rv);
1317 EXPECT_EQ(data.read_index(), 7U); // i.e. the third & fourth trans queued
1319 out.rv = callback3.WaitForResult();
1320 ASSERT_EQ(OK, out.rv);
1322 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1323 EXPECT_TRUE(response1->headers.get() != NULL);
1324 EXPECT_TRUE(response1->was_fetched_via_spdy);
1325 out.status_line = response1->headers->GetStatusLine();
1326 out.response_info = *response1;
1327 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1328 EXPECT_EQ(OK, out.rv);
1329 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1330 EXPECT_EQ("hello!hello!", out.response_data);
1332 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1333 out.status_line = response2->headers->GetStatusLine();
1334 out.response_info = *response2;
1335 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1336 EXPECT_EQ(OK, out.rv);
1337 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1338 EXPECT_EQ("hello!hello!", out.response_data);
1340 // notice: response3 gets two hellos, response4 gets one
1341 // hello, so we know dequeuing priority was respected.
1342 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1343 out.status_line = response3->headers->GetStatusLine();
1344 out.response_info = *response3;
1345 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1346 EXPECT_EQ(OK, out.rv);
1347 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1348 EXPECT_EQ("hello!hello!", out.response_data);
1350 out.rv = callback4.WaitForResult();
1351 EXPECT_EQ(OK, out.rv);
1352 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
1353 out.status_line = response4->headers->GetStatusLine();
1354 out.response_info = *response4;
1355 out.rv = ReadTransaction(trans4.get(), &out.response_data);
1356 EXPECT_EQ(OK, out.rv);
1357 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1358 EXPECT_EQ("hello!", out.response_data);
1359 helper.VerifyDataConsumed();
1360 EXPECT_EQ(OK, out.rv);
1363 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1364 // deletes a session in the middle of the transaction to insure
1365 // that we properly remove pendingcreatestream objects from
1367 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
1368 // Construct the request.
1369 scoped_ptr<SpdyFrame> req(
1370 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1371 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1372 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1373 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1375 scoped_ptr<SpdyFrame> req2(
1376 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1377 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1378 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1379 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1381 SettingsMap settings;
1382 const uint32 max_concurrent_streams = 1;
1383 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1384 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1385 scoped_ptr<SpdyFrame> settings_frame(
1386 spdy_util_.ConstructSpdySettings(settings));
1388 MockWrite writes[] = { CreateMockWrite(*req),
1389 CreateMockWrite(*req2),
1391 MockRead reads[] = {
1392 CreateMockRead(*settings_frame, 1),
1393 CreateMockRead(*resp),
1394 CreateMockRead(*body),
1395 CreateMockRead(*fbody),
1396 CreateMockRead(*resp2, 7),
1397 CreateMockRead(*body2),
1398 CreateMockRead(*fbody2),
1399 MockRead(ASYNC, 0, 0), // EOF
1402 OrderedSocketData data(reads, arraysize(reads),
1403 writes, arraysize(writes));
1404 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1407 TransactionHelperResult out;
1408 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1409 BoundNetLog(), GetParam(), NULL);
1410 helper.RunPreTestSetup();
1411 helper.AddData(&data);
1412 // We require placeholder data because three get requests are sent out, so
1413 // there needs to be three sets of SSL connection data.
1414 helper.AddData(&data_placeholder);
1415 helper.AddData(&data_placeholder);
1416 scoped_ptr<HttpNetworkTransaction> trans1(
1417 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1418 scoped_ptr<HttpNetworkTransaction> trans2(
1419 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1420 scoped_ptr<HttpNetworkTransaction> trans3(
1421 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1423 TestCompletionCallback callback1;
1424 TestCompletionCallback callback2;
1425 TestCompletionCallback callback3;
1427 HttpRequestInfo httpreq1 = CreateGetRequest();
1428 HttpRequestInfo httpreq2 = CreateGetRequest();
1429 HttpRequestInfo httpreq3 = CreateGetRequest();
1431 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1432 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1433 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1434 out.rv = callback1.WaitForResult();
1435 ASSERT_EQ(OK, out.rv);
1437 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1438 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1439 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1440 delete trans3.release();
1441 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1442 out.rv = callback2.WaitForResult();
1443 ASSERT_EQ(OK, out.rv);
1445 EXPECT_EQ(8U, data.read_index());
1447 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1448 ASSERT_TRUE(response1 != NULL);
1449 EXPECT_TRUE(response1->headers.get() != NULL);
1450 EXPECT_TRUE(response1->was_fetched_via_spdy);
1451 out.status_line = response1->headers->GetStatusLine();
1452 out.response_info = *response1;
1453 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1454 EXPECT_EQ(OK, out.rv);
1455 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1456 EXPECT_EQ("hello!hello!", out.response_data);
1458 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1459 ASSERT_TRUE(response2 != NULL);
1460 out.status_line = response2->headers->GetStatusLine();
1461 out.response_info = *response2;
1462 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1463 EXPECT_EQ(OK, out.rv);
1464 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1465 EXPECT_EQ("hello!hello!", out.response_data);
1466 helper.VerifyDataConsumed();
1467 EXPECT_EQ(OK, out.rv);
1472 // The KillerCallback will delete the transaction on error as part of the
1474 class KillerCallback : public TestCompletionCallbackBase {
1476 explicit KillerCallback(HttpNetworkTransaction* transaction)
1477 : transaction_(transaction),
1478 callback_(base::Bind(&KillerCallback::OnComplete,
1479 base::Unretained(this))) {
1482 virtual ~KillerCallback() {}
1484 const CompletionCallback& callback() const { return callback_; }
1487 void OnComplete(int result) {
1489 delete transaction_;
1494 HttpNetworkTransaction* transaction_;
1495 CompletionCallback callback_;
1500 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1501 // closes the socket while we have a pending transaction waiting for
1502 // a pending stream creation. http://crbug.com/52901
1503 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
1504 // Construct the request.
1505 scoped_ptr<SpdyFrame> req(
1506 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1507 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1508 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1509 scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1511 scoped_ptr<SpdyFrame> req2(
1512 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1513 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1515 SettingsMap settings;
1516 const uint32 max_concurrent_streams = 1;
1517 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1518 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1519 scoped_ptr<SpdyFrame> settings_frame(
1520 spdy_util_.ConstructSpdySettings(settings));
1522 MockWrite writes[] = { CreateMockWrite(*req),
1523 CreateMockWrite(*req2),
1525 MockRead reads[] = {
1526 CreateMockRead(*settings_frame, 1),
1527 CreateMockRead(*resp),
1528 CreateMockRead(*body),
1529 CreateMockRead(*fin_body),
1530 CreateMockRead(*resp2, 7),
1531 MockRead(ASYNC, ERR_CONNECTION_RESET, 0), // Abort!
1534 OrderedSocketData data(reads, arraysize(reads),
1535 writes, arraysize(writes));
1536 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1539 TransactionHelperResult out;
1540 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1541 BoundNetLog(), GetParam(), NULL);
1542 helper.RunPreTestSetup();
1543 helper.AddData(&data);
1544 // We require placeholder data because three get requests are sent out, so
1545 // there needs to be three sets of SSL connection data.
1546 helper.AddData(&data_placeholder);
1547 helper.AddData(&data_placeholder);
1548 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session().get());
1549 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session().get());
1550 HttpNetworkTransaction* trans3(
1551 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1553 TestCompletionCallback callback1;
1554 TestCompletionCallback callback2;
1555 KillerCallback callback3(trans3);
1557 HttpRequestInfo httpreq1 = CreateGetRequest();
1558 HttpRequestInfo httpreq2 = CreateGetRequest();
1559 HttpRequestInfo httpreq3 = CreateGetRequest();
1561 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
1562 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1563 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1564 out.rv = callback1.WaitForResult();
1565 ASSERT_EQ(OK, out.rv);
1567 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
1568 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1569 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1570 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1571 out.rv = callback3.WaitForResult();
1572 ASSERT_EQ(ERR_ABORTED, out.rv);
1574 EXPECT_EQ(6U, data.read_index());
1576 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1577 ASSERT_TRUE(response1 != NULL);
1578 EXPECT_TRUE(response1->headers.get() != NULL);
1579 EXPECT_TRUE(response1->was_fetched_via_spdy);
1580 out.status_line = response1->headers->GetStatusLine();
1581 out.response_info = *response1;
1582 out.rv = ReadTransaction(&trans1, &out.response_data);
1583 EXPECT_EQ(OK, out.rv);
1585 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1586 ASSERT_TRUE(response2 != NULL);
1587 out.status_line = response2->headers->GetStatusLine();
1588 out.response_info = *response2;
1589 out.rv = ReadTransaction(&trans2, &out.response_data);
1590 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1592 helper.VerifyDataConsumed();
1595 // Test that a simple PUT request works.
1596 TEST_P(SpdyNetworkTransactionTest, Put) {
1597 // Setup the request
1598 HttpRequestInfo request;
1599 request.method = "PUT";
1600 request.url = GURL("http://www.google.com/");
1602 const SpdyHeaderInfo kSynStartHeader = {
1603 SYN_STREAM, // Kind = Syn
1605 0, // Associated stream ID
1606 ConvertRequestPriorityToSpdyPriority(
1607 LOWEST, spdy_util_.spdy_version()),
1608 kSpdyCredentialSlotUnused,
1609 CONTROL_FLAG_FIN, // Control Flags
1610 false, // Compressed
1611 RST_STREAM_INVALID, // Status
1614 DATA_FLAG_NONE // Data Flags
1616 scoped_ptr<SpdyHeaderBlock> put_headers(
1617 spdy_util_.ConstructPutHeaderBlock("http://www.google.com", 0));
1618 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyFrame(
1619 kSynStartHeader, put_headers.Pass()));
1620 MockWrite writes[] = {
1621 CreateMockWrite(*req),
1624 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1625 const SpdyHeaderInfo kSynReplyHeader = {
1626 SYN_REPLY, // Kind = SynReply
1628 0, // Associated stream ID
1629 ConvertRequestPriorityToSpdyPriority(
1630 LOWEST, spdy_util_.spdy_version()),
1631 kSpdyCredentialSlotUnused,
1632 CONTROL_FLAG_NONE, // Control Flags
1633 false, // Compressed
1634 RST_STREAM_INVALID, // Status
1637 DATA_FLAG_NONE // Data Flags
1639 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
1640 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
1641 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
1642 (*reply_headers)["content-length"] = "1234";
1643 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyFrame(
1644 kSynReplyHeader, reply_headers.Pass()));
1645 MockRead reads[] = {
1646 CreateMockRead(*resp),
1647 CreateMockRead(*body),
1648 MockRead(ASYNC, 0, 0) // EOF
1651 DelayedSocketData data(1, reads, arraysize(reads),
1652 writes, arraysize(writes));
1653 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1654 BoundNetLog(), GetParam(), NULL);
1655 helper.RunToCompletion(&data);
1656 TransactionHelperResult out = helper.output();
1658 EXPECT_EQ(OK, out.rv);
1659 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1662 // Test that a simple HEAD request works.
1663 TEST_P(SpdyNetworkTransactionTest, Head) {
1664 // Setup the request
1665 HttpRequestInfo request;
1666 request.method = "HEAD";
1667 request.url = GURL("http://www.google.com/");
1669 const SpdyHeaderInfo kSynStartHeader = {
1670 SYN_STREAM, // Kind = Syn
1672 0, // Associated stream ID
1673 ConvertRequestPriorityToSpdyPriority(
1674 LOWEST, spdy_util_.spdy_version()),
1675 kSpdyCredentialSlotUnused,
1676 CONTROL_FLAG_FIN, // Control Flags
1677 false, // Compressed
1678 RST_STREAM_INVALID, // Status
1681 DATA_FLAG_NONE // Data Flags
1683 scoped_ptr<SpdyHeaderBlock> head_headers(
1684 spdy_util_.ConstructHeadHeaderBlock("http://www.google.com", 0));
1685 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyFrame(
1686 kSynStartHeader, head_headers.Pass()));
1687 MockWrite writes[] = {
1688 CreateMockWrite(*req),
1691 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1692 const SpdyHeaderInfo kSynReplyHeader = {
1693 SYN_REPLY, // Kind = SynReply
1695 0, // Associated stream ID
1696 ConvertRequestPriorityToSpdyPriority(
1697 LOWEST, spdy_util_.spdy_version()),
1698 kSpdyCredentialSlotUnused,
1699 CONTROL_FLAG_NONE, // Control Flags
1700 false, // Compressed
1701 RST_STREAM_INVALID, // Status
1704 DATA_FLAG_NONE // Data Flags
1706 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
1707 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
1708 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
1709 (*reply_headers)["content-length"] = "1234";
1710 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyFrame(
1712 reply_headers.Pass()));
1713 MockRead reads[] = {
1714 CreateMockRead(*resp),
1715 CreateMockRead(*body),
1716 MockRead(ASYNC, 0, 0) // EOF
1719 DelayedSocketData data(1, reads, arraysize(reads),
1720 writes, arraysize(writes));
1721 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1722 BoundNetLog(), GetParam(), NULL);
1723 helper.RunToCompletion(&data);
1724 TransactionHelperResult out = helper.output();
1726 EXPECT_EQ(OK, out.rv);
1727 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1730 // Test that a simple POST works.
1731 TEST_P(SpdyNetworkTransactionTest, Post) {
1732 scoped_ptr<SpdyFrame> req(
1733 spdy_util_.ConstructSpdyPost(
1734 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1735 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1736 MockWrite writes[] = {
1737 CreateMockWrite(*req),
1738 CreateMockWrite(*body), // POST upload frame
1741 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1742 MockRead reads[] = {
1743 CreateMockRead(*resp),
1744 CreateMockRead(*body),
1745 MockRead(ASYNC, 0, 0) // EOF
1748 DelayedSocketData data(2, reads, arraysize(reads),
1749 writes, arraysize(writes));
1750 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
1751 BoundNetLog(), GetParam(), NULL);
1752 helper.RunToCompletion(&data);
1753 TransactionHelperResult out = helper.output();
1754 EXPECT_EQ(OK, out.rv);
1755 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1756 EXPECT_EQ("hello!", out.response_data);
1759 // Test that a POST with a file works.
1760 TEST_P(SpdyNetworkTransactionTest, FilePost) {
1761 scoped_ptr<SpdyFrame> req(
1762 spdy_util_.ConstructSpdyPost(
1763 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1764 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1765 MockWrite writes[] = {
1766 CreateMockWrite(*req),
1767 CreateMockWrite(*body), // POST upload frame
1770 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1771 MockRead reads[] = {
1772 CreateMockRead(*resp),
1773 CreateMockRead(*body),
1774 MockRead(ASYNC, 0, 0) // EOF
1777 DelayedSocketData data(2, reads, arraysize(reads),
1778 writes, arraysize(writes));
1779 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
1780 BoundNetLog(), GetParam(), NULL);
1781 helper.RunToCompletion(&data);
1782 TransactionHelperResult out = helper.output();
1783 EXPECT_EQ(OK, out.rv);
1784 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1785 EXPECT_EQ("hello!", out.response_data);
1788 // Test that a complex POST works.
1789 TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
1790 scoped_ptr<SpdyFrame> req(
1791 spdy_util_.ConstructSpdyPost(
1792 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1793 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1794 MockWrite writes[] = {
1795 CreateMockWrite(*req),
1796 CreateMockWrite(*body), // POST upload frame
1799 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1800 MockRead reads[] = {
1801 CreateMockRead(*resp),
1802 CreateMockRead(*body),
1803 MockRead(ASYNC, 0, 0) // EOF
1806 DelayedSocketData data(2, reads, arraysize(reads),
1807 writes, arraysize(writes));
1808 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
1810 BoundNetLog(), GetParam(), NULL);
1811 helper.RunToCompletion(&data);
1812 TransactionHelperResult out = helper.output();
1813 EXPECT_EQ(OK, out.rv);
1814 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1815 EXPECT_EQ("hello!", out.response_data);
1818 // Test that a chunked POST works.
1819 TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
1820 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1821 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1822 MockWrite writes[] = {
1823 CreateMockWrite(*req),
1824 CreateMockWrite(*body),
1827 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1828 MockRead reads[] = {
1829 CreateMockRead(*resp),
1830 CreateMockRead(*body),
1831 MockRead(ASYNC, 0, 0) // EOF
1834 DelayedSocketData data(2, reads, arraysize(reads),
1835 writes, arraysize(writes));
1836 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1838 BoundNetLog(), GetParam(), NULL);
1840 // These chunks get merged into a single frame when being sent.
1841 const int kFirstChunkSize = kUploadDataSize/2;
1842 helper.request().upload_data_stream->AppendChunk(
1843 kUploadData, kFirstChunkSize, false);
1844 helper.request().upload_data_stream->AppendChunk(
1845 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1847 helper.RunToCompletion(&data);
1848 TransactionHelperResult out = helper.output();
1849 EXPECT_EQ(OK, out.rv);
1850 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1851 EXPECT_EQ(kUploadData, out.response_data);
1854 // Test that a chunked POST works with chunks appended after transaction starts.
1855 TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
1856 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1857 scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
1858 scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false));
1859 scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
1860 MockWrite writes[] = {
1861 CreateMockWrite(*req),
1862 CreateMockWrite(*chunk1),
1863 CreateMockWrite(*chunk2),
1864 CreateMockWrite(*chunk3),
1867 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1868 MockRead reads[] = {
1869 CreateMockRead(*resp),
1870 CreateMockRead(*chunk1),
1871 CreateMockRead(*chunk2),
1872 CreateMockRead(*chunk3),
1873 MockRead(ASYNC, 0, 0) // EOF
1876 DelayedSocketData data(4, reads, arraysize(reads),
1877 writes, arraysize(writes));
1878 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1880 BoundNetLog(), GetParam(), NULL);
1882 helper.request().upload_data_stream->AppendChunk(
1883 kUploadData, kUploadDataSize, false);
1885 helper.RunPreTestSetup();
1886 helper.AddData(&data);
1887 ASSERT_TRUE(helper.StartDefaultTest());
1889 base::RunLoop().RunUntilIdle();
1890 helper.request().upload_data_stream->AppendChunk(
1891 kUploadData, kUploadDataSize, false);
1892 base::RunLoop().RunUntilIdle();
1893 helper.request().upload_data_stream->AppendChunk(
1894 kUploadData, kUploadDataSize, true);
1896 helper.FinishDefaultTest();
1897 helper.VerifyDataConsumed();
1899 std::string expected_response;
1900 expected_response += kUploadData;
1901 expected_response += kUploadData;
1902 expected_response += kUploadData;
1904 TransactionHelperResult out = helper.output();
1905 EXPECT_EQ(OK, out.rv);
1906 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1907 EXPECT_EQ(expected_response, out.response_data);
1910 // Test that a POST without any post data works.
1911 TEST_P(SpdyNetworkTransactionTest, NullPost) {
1912 // Setup the request
1913 HttpRequestInfo request;
1914 request.method = "POST";
1915 request.url = GURL(kRequestUrl);
1916 // Create an empty UploadData.
1917 request.upload_data_stream = NULL;
1919 // When request.upload_data_stream is NULL for post, content-length is
1920 // expected to be 0.
1921 scoped_ptr<SpdyFrame> req(
1922 spdy_util_.ConstructSpdyPost(kRequestUrl, 1, 0, LOWEST, NULL, 0));
1923 // Set the FIN bit since there will be no body.
1924 test::SetFrameFlags(req.get(), CONTROL_FLAG_FIN, spdy_util_.spdy_version());
1925 MockWrite writes[] = {
1926 CreateMockWrite(*req),
1929 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1930 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1931 MockRead reads[] = {
1932 CreateMockRead(*resp),
1933 CreateMockRead(*body),
1934 MockRead(ASYNC, 0, 0) // EOF
1937 DelayedSocketData data(1, reads, arraysize(reads),
1938 writes, arraysize(writes));
1940 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1941 BoundNetLog(), GetParam(), NULL);
1942 helper.RunToCompletion(&data);
1943 TransactionHelperResult out = helper.output();
1944 EXPECT_EQ(OK, out.rv);
1945 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1946 EXPECT_EQ("hello!", out.response_data);
1949 // Test that a simple POST works.
1950 TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
1951 // Create an empty UploadDataStream.
1952 ScopedVector<UploadElementReader> element_readers;
1953 UploadDataStream stream(element_readers.Pass(), 0);
1955 // Setup the request
1956 HttpRequestInfo request;
1957 request.method = "POST";
1958 request.url = GURL(kRequestUrl);
1959 request.upload_data_stream = &stream;
1961 const uint64 kContentLength = 0;
1962 scoped_ptr<SpdyFrame> req(
1963 spdy_util_.ConstructSpdyPost(
1964 kRequestUrl, 1, kContentLength, LOWEST, NULL, 0));
1965 // Set the FIN bit since there will be no body.
1966 test::SetFrameFlags(req.get(), CONTROL_FLAG_FIN, spdy_util_.spdy_version());
1967 MockWrite writes[] = {
1968 CreateMockWrite(*req),
1971 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1972 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1973 MockRead reads[] = {
1974 CreateMockRead(*resp),
1975 CreateMockRead(*body),
1976 MockRead(ASYNC, 0, 0) // EOF
1979 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
1981 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1982 BoundNetLog(), GetParam(), NULL);
1983 helper.RunToCompletion(&data);
1984 TransactionHelperResult out = helper.output();
1985 EXPECT_EQ(OK, out.rv);
1986 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1987 EXPECT_EQ("hello!", out.response_data);
1990 // While we're doing a post, the server sends back a SYN_REPLY.
1991 TEST_P(SpdyNetworkTransactionTest, PostWithEarlySynReply) {
1992 static const char upload[] = { "hello!" };
1993 ScopedVector<UploadElementReader> element_readers;
1994 element_readers.push_back(
1995 new UploadBytesElementReader(upload, sizeof(upload)));
1996 UploadDataStream stream(element_readers.Pass(), 0);
1998 // Setup the request
1999 HttpRequestInfo request;
2000 request.method = "POST";
2001 request.url = GURL(kRequestUrl);
2002 request.upload_data_stream = &stream;
2004 scoped_ptr<SpdyFrame> stream_reply(
2005 spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
2006 MockRead reads[] = {
2007 CreateMockRead(*stream_reply, 1),
2008 MockRead(ASYNC, 0, 4) // EOF
2011 scoped_ptr<SpdyFrame> req(
2012 spdy_util_.ConstructSpdyPost(
2013 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
2014 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2015 scoped_ptr<SpdyFrame> rst(
2016 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2017 MockWrite writes[] = {
2018 CreateMockWrite(*req, 0),
2019 CreateMockWrite(*body, 2),
2020 CreateMockWrite(*rst, 3)
2023 DeterministicSocketData data(reads, arraysize(reads),
2024 writes, arraysize(writes));
2025 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
2026 BoundNetLog(), GetParam(), NULL);
2027 helper.SetDeterministic();
2028 helper.RunPreTestSetup();
2029 helper.AddDeterministicData(&data);
2030 HttpNetworkTransaction* trans = helper.trans();
2032 TestCompletionCallback callback;
2033 int rv = trans->Start(
2034 &CreatePostRequest(), callback.callback(), BoundNetLog());
2035 EXPECT_EQ(ERR_IO_PENDING, rv);
2038 rv = callback.WaitForResult();
2039 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
2043 // The client upon cancellation tries to send a RST_STREAM frame. The mock
2044 // socket causes the TCP write to return zero. This test checks that the client
2045 // tries to queue up the RST_STREAM frame again.
2046 TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
2047 scoped_ptr<SpdyFrame> req(
2048 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2049 scoped_ptr<SpdyFrame> rst(
2050 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2051 MockWrite writes[] = {
2052 CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
2053 MockWrite(SYNCHRONOUS, 0, 0, 2),
2054 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
2057 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2058 MockRead reads[] = {
2059 CreateMockRead(*resp.get(), 1, ASYNC),
2060 MockRead(ASYNC, 0, 0, 4) // EOF
2063 DeterministicSocketData data(reads, arraysize(reads),
2064 writes, arraysize(writes));
2065 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2066 BoundNetLog(), GetParam(), NULL);
2067 helper.SetDeterministic();
2068 helper.RunPreTestSetup();
2069 helper.AddDeterministicData(&data);
2070 HttpNetworkTransaction* trans = helper.trans();
2072 TestCompletionCallback callback;
2073 int rv = trans->Start(
2074 &CreateGetRequest(), callback.callback(), BoundNetLog());
2075 EXPECT_EQ(ERR_IO_PENDING, rv);
2079 helper.ResetTrans();
2083 helper.VerifyDataConsumed();
2086 // Test that the transaction doesn't crash when we don't have a reply.
2087 TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
2088 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2089 MockRead reads[] = {
2090 CreateMockRead(*body),
2091 MockRead(ASYNC, 0, 0) // EOF
2094 DelayedSocketData data(1, reads, arraysize(reads), NULL, 0);
2095 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2096 BoundNetLog(), GetParam(), NULL);
2097 helper.RunToCompletion(&data);
2098 TransactionHelperResult out = helper.output();
2099 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2102 // Test that the transaction doesn't crash when we get two replies on the same
2103 // stream ID. See http://crbug.com/45639.
2104 TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
2105 scoped_ptr<SpdyFrame> req(
2106 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2107 scoped_ptr<SpdyFrame> rst(
2108 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_STREAM_IN_USE));
2109 MockWrite writes[] = {
2110 CreateMockWrite(*req),
2111 CreateMockWrite(*rst),
2114 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2115 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2116 MockRead reads[] = {
2117 CreateMockRead(*resp),
2118 CreateMockRead(*resp),
2119 CreateMockRead(*body),
2120 MockRead(ASYNC, 0, 0) // EOF
2123 DelayedSocketData data(1, reads, arraysize(reads),
2124 writes, arraysize(writes));
2126 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2127 BoundNetLog(), GetParam(), NULL);
2128 helper.RunPreTestSetup();
2129 helper.AddData(&data);
2131 HttpNetworkTransaction* trans = helper.trans();
2133 TestCompletionCallback callback;
2134 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2135 EXPECT_EQ(ERR_IO_PENDING, rv);
2136 rv = callback.WaitForResult();
2139 const HttpResponseInfo* response = trans->GetResponseInfo();
2140 ASSERT_TRUE(response != NULL);
2141 EXPECT_TRUE(response->headers.get() != NULL);
2142 EXPECT_TRUE(response->was_fetched_via_spdy);
2143 std::string response_data;
2144 rv = ReadTransaction(trans, &response_data);
2145 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
2147 helper.VerifyDataConsumed();
2150 TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
2151 // Construct the request.
2152 scoped_ptr<SpdyFrame> req(
2153 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2154 scoped_ptr<SpdyFrame> rst(
2155 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2156 MockWrite writes[] = {
2157 CreateMockWrite(*req),
2158 CreateMockWrite(*rst),
2161 const char* const headers[] = {
2162 "transfer-encoding", "chunked"
2164 scoped_ptr<SpdyFrame> resp(
2165 spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1));
2166 scoped_ptr<SpdyFrame> body(
2167 spdy_util_.ConstructSpdyBodyFrame(1, true));
2168 MockRead reads[] = {
2169 CreateMockRead(*resp),
2170 CreateMockRead(*body),
2171 MockRead(ASYNC, 0, 0) // EOF
2174 DelayedSocketData data(1, reads, arraysize(reads),
2175 writes, arraysize(writes));
2176 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2177 BoundNetLog(), GetParam(), NULL);
2178 helper.RunToCompletion(&data);
2179 TransactionHelperResult out = helper.output();
2180 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2182 helper.session()->spdy_session_pool()->CloseAllSessions();
2183 helper.VerifyDataConsumed();
2186 TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
2187 // Construct the request.
2188 scoped_ptr<SpdyFrame> req(
2189 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2190 scoped_ptr<SpdyFrame> rst(
2191 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
2192 MockWrite writes[] = {
2193 CreateMockWrite(*req),
2194 CreateMockWrite(*rst),
2197 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2198 const char* const headers[] = {
2199 "transfer-encoding", "chunked"
2201 scoped_ptr<SpdyFrame> push(
2202 spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2,
2203 2, 1, "http://www.google.com/1"));
2204 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2205 MockRead reads[] = {
2206 CreateMockRead(*resp),
2207 CreateMockRead(*push),
2208 CreateMockRead(*body),
2209 MockRead(ASYNC, 0, 0) // EOF
2212 DelayedSocketData data(1, reads, arraysize(reads),
2213 writes, arraysize(writes));
2214 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2215 BoundNetLog(), GetParam(), NULL);
2216 helper.RunToCompletion(&data);
2217 TransactionHelperResult out = helper.output();
2218 EXPECT_EQ(OK, out.rv);
2219 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2220 EXPECT_EQ("hello!", out.response_data);
2222 helper.session()->spdy_session_pool()->CloseAllSessions();
2223 helper.VerifyDataConsumed();
2226 TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
2227 // Construct the request.
2228 scoped_ptr<SpdyFrame> req(
2229 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2230 MockWrite writes[] = {
2231 CreateMockWrite(*req),
2234 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2235 MockRead reads[] = {
2236 CreateMockRead(*resp),
2237 // This following read isn't used by the test, except during the
2238 // RunUntilIdle() call at the end since the SpdySession survives the
2239 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2240 // MockRead will do here.
2241 MockRead(ASYNC, 0, 0) // EOF
2244 StaticSocketDataProvider data(reads, arraysize(reads),
2245 writes, arraysize(writes));
2247 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2248 BoundNetLog(), GetParam(), NULL);
2249 helper.RunPreTestSetup();
2250 helper.AddData(&data);
2251 HttpNetworkTransaction* trans = helper.trans();
2253 TestCompletionCallback callback;
2254 int rv = trans->Start(
2255 &CreateGetRequest(), callback.callback(), BoundNetLog());
2256 EXPECT_EQ(ERR_IO_PENDING, rv);
2257 helper.ResetTrans(); // Cancel the transaction.
2259 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2260 // MockClientSocketFactory) are still alive.
2261 base::RunLoop().RunUntilIdle();
2262 helper.VerifyDataNotConsumed();
2265 // Verify that the client sends a Rst Frame upon cancelling the stream.
2266 TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
2267 scoped_ptr<SpdyFrame> req(
2268 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2269 scoped_ptr<SpdyFrame> rst(
2270 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2271 MockWrite writes[] = {
2272 CreateMockWrite(*req, 0, SYNCHRONOUS),
2273 CreateMockWrite(*rst, 2, SYNCHRONOUS),
2276 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2277 MockRead reads[] = {
2278 CreateMockRead(*resp, 1, ASYNC),
2279 MockRead(ASYNC, 0, 0, 3) // EOF
2282 DeterministicSocketData data(reads, arraysize(reads),
2283 writes, arraysize(writes));
2285 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2288 helper.SetDeterministic();
2289 helper.RunPreTestSetup();
2290 helper.AddDeterministicData(&data);
2291 HttpNetworkTransaction* trans = helper.trans();
2293 TestCompletionCallback callback;
2295 int rv = trans->Start(
2296 &CreateGetRequest(), callback.callback(), BoundNetLog());
2297 EXPECT_EQ(ERR_IO_PENDING, rv);
2301 helper.ResetTrans();
2305 helper.VerifyDataConsumed();
2308 // Verify that the client can correctly deal with the user callback attempting
2309 // to start another transaction on a session that is closing down. See
2310 // http://crbug.com/47455
2311 TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
2312 scoped_ptr<SpdyFrame> req(
2313 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2314 MockWrite writes[] = { CreateMockWrite(*req) };
2315 MockWrite writes2[] = { CreateMockWrite(*req) };
2317 // The indicated length of this frame is longer than its actual length. When
2318 // the session receives an empty frame after this one, it shuts down the
2319 // session, and calls the read callback with the incomplete data.
2320 const uint8 kGetBodyFrame2[] = {
2321 0x00, 0x00, 0x00, 0x01,
2322 0x01, 0x00, 0x00, 0x07,
2323 'h', 'e', 'l', 'l', 'o', '!',
2326 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2327 MockRead reads[] = {
2328 CreateMockRead(*resp, 2),
2329 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2330 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2331 arraysize(kGetBodyFrame2), 4),
2332 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2333 MockRead(ASYNC, 0, 0, 6), // EOF
2335 MockRead reads2[] = {
2336 CreateMockRead(*resp, 2),
2337 MockRead(ASYNC, 0, 0, 3), // EOF
2340 OrderedSocketData data(reads, arraysize(reads),
2341 writes, arraysize(writes));
2342 DelayedSocketData data2(1, reads2, arraysize(reads2),
2343 writes2, arraysize(writes2));
2345 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2346 BoundNetLog(), GetParam(), NULL);
2347 helper.RunPreTestSetup();
2348 helper.AddData(&data);
2349 helper.AddData(&data2);
2350 HttpNetworkTransaction* trans = helper.trans();
2352 // Start the transaction with basic parameters.
2353 TestCompletionCallback callback;
2354 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2355 EXPECT_EQ(ERR_IO_PENDING, rv);
2356 rv = callback.WaitForResult();
2358 const int kSize = 3000;
2359 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2363 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
2365 // This forces an err_IO_pending, which sets the callback.
2366 data.CompleteRead();
2367 // This finishes the read.
2368 data.CompleteRead();
2369 helper.VerifyDataConsumed();
2372 // Verify that the client can correctly deal with the user callback deleting the
2373 // transaction. Failures will usually be valgrind errors. See
2374 // http://crbug.com/46925
2375 TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
2376 scoped_ptr<SpdyFrame> req(
2377 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2378 MockWrite writes[] = { CreateMockWrite(*req) };
2380 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2381 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2382 MockRead reads[] = {
2383 CreateMockRead(*resp.get(), 2),
2384 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2385 CreateMockRead(*body.get(), 4),
2386 MockRead(ASYNC, 0, 0, 5), // EOF
2389 OrderedSocketData data(reads, arraysize(reads),
2390 writes, arraysize(writes));
2392 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2393 BoundNetLog(), GetParam(), NULL);
2394 helper.RunPreTestSetup();
2395 helper.AddData(&data);
2396 HttpNetworkTransaction* trans = helper.trans();
2398 // Start the transaction with basic parameters.
2399 TestCompletionCallback callback;
2400 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2401 EXPECT_EQ(ERR_IO_PENDING, rv);
2402 rv = callback.WaitForResult();
2404 // Setup a user callback which will delete the session, and clear out the
2405 // memory holding the stream object. Note that the callback deletes trans.
2406 const int kSize = 3000;
2407 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2411 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
2412 base::Unretained(&helper)));
2413 ASSERT_EQ(ERR_IO_PENDING, rv);
2414 data.CompleteRead();
2416 // Finish running rest of tasks.
2417 base::RunLoop().RunUntilIdle();
2418 helper.VerifyDataConsumed();
2421 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2422 TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
2423 const SpdyHeaderInfo kSynStartHeader = spdy_util_.MakeSpdyHeader(SYN_STREAM);
2424 scoped_ptr<SpdyHeaderBlock> headers(
2425 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2426 (*headers)["user-agent"] = "";
2427 (*headers)["accept-encoding"] = "gzip,deflate";
2428 scoped_ptr<SpdyHeaderBlock> headers2(
2429 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2430 (*headers2)["user-agent"] = "";
2431 (*headers2)["accept-encoding"] = "gzip,deflate";
2433 // Setup writes/reads to www.google.com
2434 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyFrame(
2435 kSynStartHeader, headers.Pass()));
2436 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyFrame(
2437 kSynStartHeader, headers2.Pass()));
2438 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
2439 MockWrite writes[] = {
2440 CreateMockWrite(*req, 1),
2442 MockRead reads[] = {
2443 CreateMockRead(*resp, 2),
2444 MockRead(ASYNC, 0, 0, 3) // EOF
2447 // Setup writes/reads to www.foo.com
2448 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2449 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2450 MockWrite writes2[] = {
2451 CreateMockWrite(*req2, 1),
2453 MockRead reads2[] = {
2454 CreateMockRead(*resp2, 2),
2455 CreateMockRead(*body2, 3),
2456 MockRead(ASYNC, 0, 0, 4) // EOF
2458 OrderedSocketData data(reads, arraysize(reads),
2459 writes, arraysize(writes));
2460 OrderedSocketData data2(reads2, arraysize(reads2),
2461 writes2, arraysize(writes2));
2463 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2464 HttpStreamFactory::set_force_spdy_over_ssl(false);
2465 HttpStreamFactory::set_force_spdy_always(true);
2468 SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
2469 net::URLRequest r(GURL("http://www.google.com/"),
2472 &spdy_url_request_context);
2473 spdy_url_request_context.socket_factory().
2474 AddSocketDataProvider(&data);
2475 spdy_url_request_context.socket_factory().
2476 AddSocketDataProvider(&data2);
2478 d.set_quit_on_redirect(true);
2480 base::RunLoop().Run();
2482 EXPECT_EQ(1, d.received_redirect_count());
2484 r.FollowDeferredRedirect();
2485 base::RunLoop().Run();
2486 EXPECT_EQ(1, d.response_started_count());
2487 EXPECT_FALSE(d.received_data_before_response());
2488 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r.status().status());
2489 std::string contents("hello!");
2490 EXPECT_EQ(contents, d.data_received());
2492 EXPECT_TRUE(data.at_read_eof());
2493 EXPECT_TRUE(data.at_write_eof());
2494 EXPECT_TRUE(data2.at_read_eof());
2495 EXPECT_TRUE(data2.at_write_eof());
2498 // Send a spdy request to www.google.com. Get a pushed stream that redirects to
2500 TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
2501 const SpdyHeaderInfo kSynStartHeader = spdy_util_.MakeSpdyHeader(SYN_STREAM);
2503 scoped_ptr<SpdyHeaderBlock> headers(
2504 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2505 (*headers)["user-agent"] = "";
2506 (*headers)["accept-encoding"] = "gzip,deflate";
2508 // Setup writes/reads to www.google.com
2509 scoped_ptr<SpdyFrame> req(
2510 spdy_util_.ConstructSpdyFrame(kSynStartHeader, headers.Pass()));
2511 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2512 scoped_ptr<SpdyFrame> rep(
2513 spdy_util_.ConstructSpdyPush(NULL,
2517 "http://www.google.com/foo.dat",
2518 "301 Moved Permanently",
2519 "http://www.foo.com/index.php"));
2520 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2521 scoped_ptr<SpdyFrame> rst(
2522 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
2523 MockWrite writes[] = {
2524 CreateMockWrite(*req, 1),
2525 CreateMockWrite(*rst, 6),
2527 MockRead reads[] = {
2528 CreateMockRead(*resp, 2),
2529 CreateMockRead(*rep, 3),
2530 CreateMockRead(*body, 4),
2531 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2532 MockRead(ASYNC, 0, 0, 7) // EOF
2535 // Setup writes/reads to www.foo.com
2536 scoped_ptr<SpdyHeaderBlock> headers2(
2537 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2538 (*headers2)["user-agent"] = "";
2539 (*headers2)["accept-encoding"] = "gzip,deflate";
2540 scoped_ptr<SpdyFrame> req2(
2541 spdy_util_.ConstructSpdyFrame(kSynStartHeader, headers2.Pass()));
2542 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2543 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2544 MockWrite writes2[] = {
2545 CreateMockWrite(*req2, 1),
2547 MockRead reads2[] = {
2548 CreateMockRead(*resp2, 2),
2549 CreateMockRead(*body2, 3),
2550 MockRead(ASYNC, 0, 0, 5) // EOF
2552 OrderedSocketData data(reads, arraysize(reads),
2553 writes, arraysize(writes));
2554 OrderedSocketData data2(reads2, arraysize(reads2),
2555 writes2, arraysize(writes2));
2557 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2558 HttpStreamFactory::set_force_spdy_over_ssl(false);
2559 HttpStreamFactory::set_force_spdy_always(true);
2562 SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
2564 net::URLRequest r(GURL("http://www.google.com/"),
2567 &spdy_url_request_context);
2568 spdy_url_request_context.socket_factory().
2569 AddSocketDataProvider(&data);
2572 base::RunLoop().Run();
2574 EXPECT_EQ(0, d.received_redirect_count());
2575 std::string contents("hello!");
2576 EXPECT_EQ(contents, d.data_received());
2578 net::URLRequest r2(GURL("http://www.google.com/foo.dat"),
2581 &spdy_url_request_context);
2582 spdy_url_request_context.socket_factory().
2583 AddSocketDataProvider(&data2);
2585 d2.set_quit_on_redirect(true);
2587 base::RunLoop().Run();
2588 EXPECT_EQ(1, d2.received_redirect_count());
2590 r2.FollowDeferredRedirect();
2591 base::RunLoop().Run();
2592 EXPECT_EQ(1, d2.response_started_count());
2593 EXPECT_FALSE(d2.received_data_before_response());
2594 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2.status().status());
2595 std::string contents2("hello!");
2596 EXPECT_EQ(contents2, d2.data_received());
2598 data.CompleteRead();
2599 data2.CompleteRead();
2600 EXPECT_TRUE(data.at_read_eof());
2601 EXPECT_TRUE(data.at_write_eof());
2602 EXPECT_TRUE(data2.at_read_eof());
2603 EXPECT_TRUE(data2.at_write_eof());
2606 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
2607 scoped_ptr<SpdyFrame> stream1_syn(
2608 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2609 scoped_ptr<SpdyFrame> stream1_body(
2610 spdy_util_.ConstructSpdyBodyFrame(1, true));
2611 MockWrite writes[] = {
2612 CreateMockWrite(*stream1_syn, 1),
2615 scoped_ptr<SpdyFrame>
2616 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2617 scoped_ptr<SpdyFrame>
2618 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2622 "http://www.google.com/foo.dat"));
2623 const char kPushedData[] = "pushed";
2624 scoped_ptr<SpdyFrame> stream2_body(
2625 spdy_util_.ConstructSpdyBodyFrame(
2626 2, kPushedData, strlen(kPushedData), true));
2627 MockRead reads[] = {
2628 CreateMockRead(*stream1_reply, 2),
2629 CreateMockRead(*stream2_syn, 3),
2630 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2631 CreateMockRead(*stream2_body, 5),
2632 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2635 HttpResponseInfo response;
2636 HttpResponseInfo response2;
2637 std::string expected_push_result("pushed");
2638 OrderedSocketData data(reads, arraysize(reads),
2639 writes, arraysize(writes));
2640 RunServerPushTest(&data,
2643 expected_push_result);
2645 // Verify the SYN_REPLY.
2646 EXPECT_TRUE(response.headers.get() != NULL);
2647 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2649 // Verify the pushed stream.
2650 EXPECT_TRUE(response2.headers.get() != NULL);
2651 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2654 TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
2655 scoped_ptr<SpdyFrame> stream1_syn(
2656 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2657 scoped_ptr<SpdyFrame> stream1_body(
2658 spdy_util_.ConstructSpdyBodyFrame(1, true));
2659 MockWrite writes[] = {
2660 CreateMockWrite(*stream1_syn, 1),
2663 scoped_ptr<SpdyFrame>
2664 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2665 scoped_ptr<SpdyFrame>
2666 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2670 "http://www.google.com/foo.dat"));
2671 const char kPushedData[] = "pushed";
2672 scoped_ptr<SpdyFrame> stream2_body(
2673 spdy_util_.ConstructSpdyBodyFrame(
2674 2, kPushedData, strlen(kPushedData), true));
2675 MockRead reads[] = {
2676 CreateMockRead(*stream2_syn, 2),
2677 CreateMockRead(*stream1_reply, 3),
2678 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2679 CreateMockRead(*stream2_body, 5),
2680 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2683 HttpResponseInfo response;
2684 HttpResponseInfo response2;
2685 std::string expected_push_result("pushed");
2686 OrderedSocketData data(reads, arraysize(reads),
2687 writes, arraysize(writes));
2688 RunServerPushTest(&data,
2691 expected_push_result);
2693 // Verify the SYN_REPLY.
2694 EXPECT_TRUE(response.headers.get() != NULL);
2695 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2697 // Verify the pushed stream.
2698 EXPECT_TRUE(response2.headers.get() != NULL);
2699 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2702 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
2703 scoped_ptr<SpdyFrame> stream1_syn(
2704 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2705 MockWrite writes[] = { CreateMockWrite(*stream1_syn, 1), };
2707 scoped_ptr<SpdyFrame>
2708 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2709 scoped_ptr<SpdyFrame>
2710 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2714 "http://www.google.com/foo.dat"));
2715 const char kPushedData[] = "pushed";
2716 scoped_ptr<SpdyFrame> stream2_body(
2717 spdy_util_.ConstructSpdyBodyFrame(
2718 2, kPushedData, strlen(kPushedData), true));
2719 scoped_ptr<SpdyFrame>
2720 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2721 MockRead reads[] = {
2722 CreateMockRead(*stream1_reply, 2),
2723 CreateMockRead(*stream2_syn, 3),
2724 CreateMockRead(*stream2_body, 4),
2725 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2726 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2729 HttpResponseInfo response;
2730 HttpResponseInfo response2;
2731 std::string expected_push_result("pushed");
2732 OrderedSocketData data(reads, arraysize(reads),
2733 writes, arraysize(writes));
2734 RunServerPushTest(&data,
2737 expected_push_result);
2739 // Verify the SYN_REPLY.
2740 EXPECT_TRUE(response.headers.get() != NULL);
2741 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2743 // Verify the pushed stream.
2744 EXPECT_TRUE(response2.headers.get() != NULL);
2745 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2748 TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
2749 scoped_ptr<SpdyFrame> stream1_syn(
2750 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2751 scoped_ptr<SpdyFrame> stream1_body(
2752 spdy_util_.ConstructSpdyBodyFrame(1, true));
2753 MockWrite writes[] = {
2754 CreateMockWrite(*stream1_syn, 1),
2757 scoped_ptr<SpdyFrame>
2758 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2759 scoped_ptr<SpdyFrame>
2760 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2764 "http://www.google.com/foo.dat"));
2765 scoped_ptr<SpdyFrame> stream2_rst(
2766 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
2767 MockRead reads[] = {
2768 CreateMockRead(*stream1_reply, 2),
2769 CreateMockRead(*stream2_syn, 3),
2770 CreateMockRead(*stream2_rst, 4),
2771 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2772 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2775 OrderedSocketData data(reads, arraysize(reads),
2776 writes, arraysize(writes));
2777 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2778 BoundNetLog(), GetParam(), NULL);
2780 helper.RunPreTestSetup();
2781 helper.AddData(&data);
2783 HttpNetworkTransaction* trans = helper.trans();
2785 // Start the transaction with basic parameters.
2786 TestCompletionCallback callback;
2787 int rv = trans->Start(
2788 &CreateGetRequest(), callback.callback(), BoundNetLog());
2789 EXPECT_EQ(ERR_IO_PENDING, rv);
2790 rv = callback.WaitForResult();
2793 // Verify that we consumed all test data.
2794 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
2795 << data.read_count()
2797 << data.read_index();
2798 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
2799 << data.write_count()
2801 << data.write_index();
2803 // Verify the SYN_REPLY.
2804 HttpResponseInfo response = *trans->GetResponseInfo();
2805 EXPECT_TRUE(response.headers.get() != NULL);
2806 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2809 // Verify that we don't leak streams and that we properly send a reset
2810 // if the server pushes the same stream twice.
2811 TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
2812 scoped_ptr<SpdyFrame> stream1_syn(
2813 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2814 scoped_ptr<SpdyFrame> stream1_body(
2815 spdy_util_.ConstructSpdyBodyFrame(1, true));
2816 scoped_ptr<SpdyFrame> stream3_rst(
2817 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
2818 MockWrite writes[] = {
2819 CreateMockWrite(*stream1_syn, 1),
2820 CreateMockWrite(*stream3_rst, 5),
2823 scoped_ptr<SpdyFrame>
2824 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2825 scoped_ptr<SpdyFrame>
2826 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2830 "http://www.google.com/foo.dat"));
2831 const char kPushedData[] = "pushed";
2832 scoped_ptr<SpdyFrame> stream2_body(
2833 spdy_util_.ConstructSpdyBodyFrame(
2834 2, kPushedData, strlen(kPushedData), true));
2835 scoped_ptr<SpdyFrame>
2836 stream3_syn(spdy_util_.ConstructSpdyPush(NULL,
2840 "http://www.google.com/foo.dat"));
2841 MockRead reads[] = {
2842 CreateMockRead(*stream1_reply, 2),
2843 CreateMockRead(*stream2_syn, 3),
2844 CreateMockRead(*stream3_syn, 4),
2845 CreateMockRead(*stream1_body, 6, SYNCHRONOUS),
2846 CreateMockRead(*stream2_body, 7),
2847 MockRead(ASYNC, ERR_IO_PENDING, 8), // Force a pause
2850 HttpResponseInfo response;
2851 HttpResponseInfo response2;
2852 std::string expected_push_result("pushed");
2853 OrderedSocketData data(reads, arraysize(reads),
2854 writes, arraysize(writes));
2855 RunServerPushTest(&data,
2858 expected_push_result);
2860 // Verify the SYN_REPLY.
2861 EXPECT_TRUE(response.headers.get() != NULL);
2862 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2864 // Verify the pushed stream.
2865 EXPECT_TRUE(response2.headers.get() != NULL);
2866 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2869 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
2870 scoped_ptr<SpdyFrame> stream1_syn(
2871 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2872 scoped_ptr<SpdyFrame> stream1_body(
2873 spdy_util_.ConstructSpdyBodyFrame(1, true));
2874 MockWrite writes[] = {
2875 CreateMockWrite(*stream1_syn, 1),
2878 scoped_ptr<SpdyFrame>
2879 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2880 scoped_ptr<SpdyFrame>
2881 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2885 "http://www.google.com/foo.dat"));
2886 static const char kPushedData[] = "pushed my darling hello my baby";
2887 scoped_ptr<SpdyFrame> stream2_body_base(
2888 spdy_util_.ConstructSpdyBodyFrame(
2889 2, kPushedData, strlen(kPushedData), true));
2890 const size_t kChunkSize = strlen(kPushedData) / 4;
2891 scoped_ptr<SpdyFrame> stream2_body1(
2892 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2893 scoped_ptr<SpdyFrame> stream2_body2(
2894 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2895 scoped_ptr<SpdyFrame> stream2_body3(
2896 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2897 kChunkSize, false));
2898 scoped_ptr<SpdyFrame> stream2_body4(
2899 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2900 stream2_body_base->size() - 3 * kChunkSize, false));
2901 MockRead reads[] = {
2902 CreateMockRead(*stream1_reply, 2),
2903 CreateMockRead(*stream2_syn, 3),
2904 CreateMockRead(*stream2_body1, 4),
2905 CreateMockRead(*stream2_body2, 5),
2906 CreateMockRead(*stream2_body3, 6),
2907 CreateMockRead(*stream2_body4, 7),
2908 CreateMockRead(*stream1_body, 8, SYNCHRONOUS),
2909 MockRead(ASYNC, ERR_IO_PENDING, 9), // Force a pause
2912 HttpResponseInfo response;
2913 HttpResponseInfo response2;
2914 std::string expected_push_result("pushed my darling hello my baby");
2915 OrderedSocketData data(reads, arraysize(reads),
2916 writes, arraysize(writes));
2917 RunServerPushTest(&data, &response, &response2, kPushedData);
2919 // Verify the SYN_REPLY.
2920 EXPECT_TRUE(response.headers.get() != NULL);
2921 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2923 // Verify the pushed stream.
2924 EXPECT_TRUE(response2.headers.get() != NULL);
2925 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2928 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
2929 scoped_ptr<SpdyFrame> stream1_syn(
2930 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2931 scoped_ptr<SpdyFrame> stream1_body(
2932 spdy_util_.ConstructSpdyBodyFrame(1, true));
2933 MockWrite writes[] = {
2934 CreateMockWrite(*stream1_syn, 1),
2937 scoped_ptr<SpdyFrame>
2938 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2939 scoped_ptr<SpdyFrame>
2940 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2944 "http://www.google.com/foo.dat"));
2945 static const char kPushedData[] = "pushed my darling hello my baby";
2946 scoped_ptr<SpdyFrame> stream2_body_base(
2947 spdy_util_.ConstructSpdyBodyFrame(
2948 2, kPushedData, strlen(kPushedData), true));
2949 const size_t kChunkSize = strlen(kPushedData) / 4;
2950 scoped_ptr<SpdyFrame> stream2_body1(
2951 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2952 scoped_ptr<SpdyFrame> stream2_body2(
2953 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2954 scoped_ptr<SpdyFrame> stream2_body3(
2955 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2956 kChunkSize, false));
2957 scoped_ptr<SpdyFrame> stream2_body4(
2958 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2959 stream2_body_base->size() - 3 * kChunkSize, false));
2960 MockRead reads[] = {
2961 CreateMockRead(*stream1_reply, 2),
2962 CreateMockRead(*stream2_syn, 3),
2963 CreateMockRead(*stream2_body1, 4),
2964 CreateMockRead(*stream2_body2, 5),
2965 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2966 CreateMockRead(*stream2_body3, 7),
2967 CreateMockRead(*stream2_body4, 8),
2968 CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS),
2969 MockRead(ASYNC, ERR_IO_PENDING, 10) // Force a pause.
2972 HttpResponseInfo response;
2973 HttpResponseInfo response2;
2974 OrderedSocketData data(reads, arraysize(reads),
2975 writes, arraysize(writes));
2976 RunServerPushTest(&data, &response, &response2, kPushedData);
2978 // Verify the SYN_REPLY.
2979 EXPECT_TRUE(response.headers.get() != NULL);
2980 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2982 // Verify the pushed stream.
2983 EXPECT_TRUE(response2.headers.get() != NULL);
2984 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2987 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
2988 scoped_ptr<SpdyFrame> stream1_syn(
2989 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2990 scoped_ptr<SpdyFrame> stream1_body(
2991 spdy_util_.ConstructSpdyBodyFrame(1, true));
2992 scoped_ptr<SpdyFrame> stream2_rst(
2993 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
2994 MockWrite writes[] = {
2995 CreateMockWrite(*stream1_syn, 1),
2996 CreateMockWrite(*stream2_rst, 4),
2999 scoped_ptr<SpdyFrame>
3000 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3001 scoped_ptr<SpdyFrame>
3002 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3006 "http://www.google.com/foo.dat"));
3007 MockRead reads[] = {
3008 CreateMockRead(*stream1_reply, 2),
3009 CreateMockRead(*stream2_syn, 3),
3010 CreateMockRead(*stream1_body, 4),
3011 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3014 OrderedSocketData data(reads, arraysize(reads),
3015 writes, arraysize(writes));
3016 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3017 BoundNetLog(), GetParam(), NULL);
3019 helper.RunPreTestSetup();
3020 helper.AddData(&data);
3022 HttpNetworkTransaction* trans = helper.trans();
3024 // Start the transaction with basic parameters.
3025 TestCompletionCallback callback;
3026 int rv = trans->Start(
3027 &CreateGetRequest(), callback.callback(), BoundNetLog());
3028 EXPECT_EQ(ERR_IO_PENDING, rv);
3029 rv = callback.WaitForResult();
3032 // Verify that we consumed all test data.
3033 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3034 << data.read_count()
3036 << data.read_index();
3037 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3038 << data.write_count()
3040 << data.write_index();
3042 // Verify the SYN_REPLY.
3043 HttpResponseInfo response = *trans->GetResponseInfo();
3044 EXPECT_TRUE(response.headers.get() != NULL);
3045 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3048 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
3049 scoped_ptr<SpdyFrame> stream1_syn(
3050 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3051 scoped_ptr<SpdyFrame> stream1_body(
3052 spdy_util_.ConstructSpdyBodyFrame(1, true));
3053 scoped_ptr<SpdyFrame> stream2_rst(
3054 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
3055 MockWrite writes[] = {
3056 CreateMockWrite(*stream1_syn, 1),
3057 CreateMockWrite(*stream2_rst, 4),
3060 scoped_ptr<SpdyFrame>
3061 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3062 scoped_ptr<SpdyFrame>
3063 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3067 "http://www.google.com/foo.dat"));
3068 MockRead reads[] = {
3069 CreateMockRead(*stream1_reply, 2),
3070 CreateMockRead(*stream2_syn, 3),
3071 CreateMockRead(*stream1_body, 4),
3072 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
3075 OrderedSocketData data(reads, arraysize(reads),
3076 writes, arraysize(writes));
3077 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3078 BoundNetLog(), GetParam(), NULL);
3080 helper.RunPreTestSetup();
3081 helper.AddData(&data);
3083 HttpNetworkTransaction* trans = helper.trans();
3085 // Start the transaction with basic parameters.
3086 TestCompletionCallback callback;
3087 int rv = trans->Start(
3088 &CreateGetRequest(), callback.callback(), BoundNetLog());
3089 EXPECT_EQ(ERR_IO_PENDING, rv);
3090 rv = callback.WaitForResult();
3093 // Verify that we consumed all test data.
3094 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3095 << data.read_count()
3097 << data.read_index();
3098 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3099 << data.write_count()
3101 << data.write_index();
3103 // Verify the SYN_REPLY.
3104 HttpResponseInfo response = *trans->GetResponseInfo();
3105 EXPECT_TRUE(response.headers.get() != NULL);
3106 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3109 TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
3110 scoped_ptr<SpdyFrame> stream1_syn(
3111 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3112 scoped_ptr<SpdyFrame> stream1_body(
3113 spdy_util_.ConstructSpdyBodyFrame(1, true));
3114 scoped_ptr<SpdyFrame> stream2_rst(
3115 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
3116 MockWrite writes[] = {
3117 CreateMockWrite(*stream1_syn, 1),
3118 CreateMockWrite(*stream2_rst, 4),
3121 scoped_ptr<SpdyFrame>
3122 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3123 scoped_ptr<SpdyHeaderBlock> incomplete_headers(new SpdyHeaderBlock());
3124 (*incomplete_headers)["hello"] = "bye";
3125 (*incomplete_headers)[spdy_util_.GetStatusKey()] = "200 OK";
3126 (*incomplete_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
3127 scoped_ptr<SpdyFrame> stream2_syn(
3128 spdy_util_.ConstructSpdyControlFrame(incomplete_headers.Pass(),
3134 // Associated stream ID
3136 MockRead reads[] = {
3137 CreateMockRead(*stream1_reply, 2),
3138 CreateMockRead(*stream2_syn, 3),
3139 CreateMockRead(*stream1_body, 4),
3140 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3143 OrderedSocketData data(reads, arraysize(reads),
3144 writes, arraysize(writes));
3145 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3146 BoundNetLog(), GetParam(), NULL);
3148 helper.RunPreTestSetup();
3149 helper.AddData(&data);
3151 HttpNetworkTransaction* trans = helper.trans();
3153 // Start the transaction with basic parameters.
3154 TestCompletionCallback callback;
3155 int rv = trans->Start(
3156 &CreateGetRequest(), callback.callback(), BoundNetLog());
3157 EXPECT_EQ(ERR_IO_PENDING, rv);
3158 rv = callback.WaitForResult();
3160 // Verify that we consumed all test data.
3161 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3162 << data.read_count()
3164 << data.read_index();
3165 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3166 << data.write_count()
3168 << data.write_index();
3170 // Verify the SYN_REPLY.
3171 HttpResponseInfo response = *trans->GetResponseInfo();
3172 EXPECT_TRUE(response.headers.get() != NULL);
3173 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3176 // Verify that various SynReply headers parse correctly through the
3178 TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
3179 struct SynReplyHeadersTests {
3181 const char* extra_headers[5];
3182 SpdyHeaderBlock expected_headers;
3184 // This uses a multi-valued cookie header.
3187 "cookie", "val2", // will get appended separated by NULL
3191 // This is the minimalist set of headers.
3195 // Headers with a comma separated list.
3197 { "cookie", "val1,val2",
3203 test_cases[0].expected_headers["cookie"] = "val1";
3204 test_cases[0].expected_headers["cookie"] += '\0';
3205 test_cases[0].expected_headers["cookie"] += "val2";
3206 test_cases[0].expected_headers["hello"] = "bye";
3207 test_cases[0].expected_headers["status"] = "200";
3208 test_cases[0].expected_headers["version"] = "HTTP/1.1";
3210 test_cases[1].expected_headers["hello"] = "bye";
3211 test_cases[1].expected_headers["status"] = "200";
3212 test_cases[1].expected_headers["version"] = "HTTP/1.1";
3214 test_cases[2].expected_headers["cookie"] = "val1,val2";
3215 test_cases[2].expected_headers["hello"] = "bye";
3216 test_cases[2].expected_headers["status"] = "200";
3217 test_cases[2].expected_headers["version"] = "HTTP/1.1";
3219 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3220 scoped_ptr<SpdyFrame> req(
3221 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3222 MockWrite writes[] = { CreateMockWrite(*req) };
3224 scoped_ptr<SpdyFrame> resp(
3225 spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
3226 test_cases[i].num_headers,
3228 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3229 MockRead reads[] = {
3230 CreateMockRead(*resp),
3231 CreateMockRead(*body),
3232 MockRead(ASYNC, 0, 0) // EOF
3235 DelayedSocketData data(1, reads, arraysize(reads),
3236 writes, arraysize(writes));
3237 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3238 BoundNetLog(), GetParam(), NULL);
3239 helper.RunToCompletion(&data);
3240 TransactionHelperResult out = helper.output();
3242 EXPECT_EQ(OK, out.rv);
3243 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3244 EXPECT_EQ("hello!", out.response_data);
3246 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3247 EXPECT_TRUE(headers.get() != NULL);
3249 std::string name, value;
3250 SpdyHeaderBlock header_block;
3251 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3252 if (header_block[name].empty()) {
3253 header_block[name] = value;
3255 header_block[name] += '\0';
3256 header_block[name] += value;
3259 EXPECT_EQ(test_cases[i].expected_headers, header_block);
3263 // Verify that various SynReply headers parse vary fields correctly
3264 // through the HTTP layer, and the response matches the request.
3265 TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
3266 static const SpdyHeaderInfo syn_reply_info = {
3267 SYN_REPLY, // Syn Reply
3269 0, // Associated Stream ID
3270 ConvertRequestPriorityToSpdyPriority(
3271 LOWEST, spdy_util_.spdy_version()),
3272 kSpdyCredentialSlotUnused,
3273 CONTROL_FLAG_NONE, // Control Flags
3274 false, // Compressed
3275 RST_STREAM_INVALID, // Status
3278 DATA_FLAG_NONE // Data Flags
3280 // Modify the following data to change/add test cases:
3281 struct SynReplyTests {
3282 const SpdyHeaderInfo* syn_reply;
3285 const char* extra_headers[2][16];
3287 // Test the case of a multi-valued cookie. When the value is delimited
3288 // with NUL characters, it needs to be unfolded into multiple headers.
3293 { { "cookie", "val1,val2",
3297 spdy_util_.GetStatusKey(), "200",
3298 spdy_util_.GetPathKey(), "/index.php",
3299 spdy_util_.GetVersionKey(), "HTTP/1.1",
3303 }, { // Multiple vary fields.
3307 { { "friend", "barney",
3308 "enemy", "snaggletooth",
3313 spdy_util_.GetStatusKey(), "200",
3314 spdy_util_.GetPathKey(), "/index.php",
3315 spdy_util_.GetVersionKey(), "HTTP/1.1",
3319 }, { // Test a '*' vary field.
3323 { { "cookie", "val1,val2",
3327 spdy_util_.GetStatusKey(), "200",
3328 spdy_util_.GetPathKey(), "/index.php",
3329 spdy_util_.GetVersionKey(), "HTTP/1.1",
3333 }, { // Multiple comma-separated vary fields.
3337 { { "friend", "barney",
3338 "enemy", "snaggletooth",
3341 { "vary", "friend,enemy",
3342 spdy_util_.GetStatusKey(), "200",
3343 spdy_util_.GetPathKey(), "/index.php",
3344 spdy_util_.GetVersionKey(), "HTTP/1.1",
3351 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3352 // Construct the request.
3353 scoped_ptr<SpdyFrame> frame_req(
3354 spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
3355 test_cases[i].num_headers[0],
3356 false, 1, LOWEST, true));
3358 MockWrite writes[] = {
3359 CreateMockWrite(*frame_req),
3362 // Construct the reply.
3363 scoped_ptr<SpdyFrame> frame_reply(
3364 spdy_util_.ConstructSpdyFrame(*test_cases[i].syn_reply,
3365 test_cases[i].extra_headers[1],
3366 test_cases[i].num_headers[1],
3370 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3371 MockRead reads[] = {
3372 CreateMockRead(*frame_reply),
3373 CreateMockRead(*body),
3374 MockRead(ASYNC, 0, 0) // EOF
3377 // Attach the headers to the request.
3378 int header_count = test_cases[i].num_headers[0];
3380 HttpRequestInfo request = CreateGetRequest();
3381 for (int ct = 0; ct < header_count; ct++) {
3382 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3383 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3384 request.extra_headers.SetHeader(header_key, header_value);
3387 DelayedSocketData data(1, reads, arraysize(reads),
3388 writes, arraysize(writes));
3389 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
3390 BoundNetLog(), GetParam(), NULL);
3391 helper.RunToCompletion(&data);
3392 TransactionHelperResult out = helper.output();
3394 EXPECT_EQ(OK, out.rv) << i;
3395 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
3396 EXPECT_EQ("hello!", out.response_data) << i;
3398 // Test the response information.
3399 EXPECT_TRUE(out.response_info.response_time >
3400 out.response_info.request_time) << i;
3401 base::TimeDelta test_delay = out.response_info.response_time -
3402 out.response_info.request_time;
3403 base::TimeDelta min_expected_delay;
3404 min_expected_delay.FromMilliseconds(10);
3405 EXPECT_GT(test_delay.InMillisecondsF(),
3406 min_expected_delay.InMillisecondsF()) << i;
3407 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3408 test_cases[i].vary_matches) << i;
3410 // Check the headers.
3411 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3412 ASSERT_TRUE(headers.get() != NULL) << i;
3414 std::string name, value, lines;
3415 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3418 lines.append(value);
3422 // Construct the expected header reply string.
3423 SpdyHeaderBlock reply_headers;
3424 AppendToHeaderBlock(test_cases[i].extra_headers[1],
3425 test_cases[i].num_headers[1],
3427 std::string expected_reply =
3428 spdy_util_.ConstructSpdyReplyString(reply_headers);
3429 EXPECT_EQ(expected_reply, lines) << i;
3433 // Verify that we don't crash on invalid SynReply responses.
3434 TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
3435 const SpdyHeaderInfo kSynStartHeader = {
3436 SYN_REPLY, // Kind = SynReply
3438 0, // Associated stream ID
3439 ConvertRequestPriorityToSpdyPriority(
3440 LOWEST, spdy_util_.spdy_version()),
3441 kSpdyCredentialSlotUnused,
3442 CONTROL_FLAG_NONE, // Control Flags
3443 false, // Compressed
3444 RST_STREAM_INVALID, // Status
3447 DATA_FLAG_NONE // Data Flags
3450 struct InvalidSynReplyTests {
3452 const char* headers[10];
3454 // SYN_REPLY missing status header
3458 spdy_util_.GetPathKey(), "/index.php",
3459 spdy_util_.GetVersionKey(), "HTTP/1.1",
3463 // SYN_REPLY missing version header
3466 spdy_util_.GetPathKey(), "/index.php",
3470 // SYN_REPLY with no headers
3474 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3475 scoped_ptr<SpdyFrame> req(
3476 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3477 scoped_ptr<SpdyFrame> rst(
3478 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3479 MockWrite writes[] = {
3480 CreateMockWrite(*req),
3481 CreateMockWrite(*rst),
3484 scoped_ptr<SpdyFrame> resp(
3485 spdy_util_.ConstructSpdyFrame(kSynStartHeader,
3487 test_cases[i].headers,
3488 test_cases[i].num_headers));
3489 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3490 MockRead reads[] = {
3491 CreateMockRead(*resp),
3492 MockRead(ASYNC, 0, 0) // EOF
3495 DelayedSocketData data(1, reads, arraysize(reads),
3496 writes, arraysize(writes));
3497 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3498 BoundNetLog(), GetParam(), NULL);
3499 helper.RunToCompletion(&data);
3500 TransactionHelperResult out = helper.output();
3501 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3505 // Verify that we don't crash on some corrupt frames.
3506 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
3507 // This is the length field that's too short.
3508 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3509 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3510 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3512 (spdy_util_.spdy_version() < SPDY4) ?
3513 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize() :
3514 syn_reply_wrong_length->size();
3515 size_t wrong_size = right_size - 4;
3516 test::SetFrameLength(syn_reply_wrong_length.get(),
3518 spdy_util_.spdy_version());
3520 struct SynReplyTests {
3521 const SpdyFrame* syn_reply;
3523 { syn_reply_wrong_length.get(), },
3526 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3527 scoped_ptr<SpdyFrame> req(
3528 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3529 scoped_ptr<SpdyFrame> rst(
3530 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3531 MockWrite writes[] = {
3532 CreateMockWrite(*req),
3533 CreateMockWrite(*rst),
3536 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3537 MockRead reads[] = {
3538 MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size),
3539 CreateMockRead(*body),
3540 MockRead(ASYNC, 0, 0) // EOF
3543 DelayedSocketData data(1, reads, arraysize(reads),
3544 writes, arraysize(writes));
3545 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3546 BoundNetLog(), GetParam(), NULL);
3547 helper.RunToCompletion(&data);
3548 TransactionHelperResult out = helper.output();
3549 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3553 // Test that we shutdown correctly on write errors.
3554 TEST_P(SpdyNetworkTransactionTest, WriteError) {
3555 scoped_ptr<SpdyFrame> req(
3556 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3557 MockWrite writes[] = {
3558 // We'll write 10 bytes successfully
3559 MockWrite(ASYNC, req->data(), 10, 0),
3560 // Followed by ERROR!
3561 MockWrite(ASYNC, ERR_FAILED, 1),
3564 MockRead reads[] = {
3565 MockRead(ASYNC, 0, 2) // EOF
3568 DeterministicSocketData data(reads, arraysize(reads),
3569 writes, arraysize(writes));
3571 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3572 BoundNetLog(), GetParam(), NULL);
3573 helper.SetDeterministic();
3574 helper.RunPreTestSetup();
3575 helper.AddDeterministicData(&data);
3576 EXPECT_TRUE(helper.StartDefaultTest());
3578 helper.FinishDefaultTest();
3579 EXPECT_TRUE(data.at_write_eof());
3580 EXPECT_TRUE(!data.at_read_eof());
3581 TransactionHelperResult out = helper.output();
3582 EXPECT_EQ(ERR_FAILED, out.rv);
3585 // Test that partial writes work.
3586 TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
3587 // Chop the SYN_STREAM frame into 5 chunks.
3588 scoped_ptr<SpdyFrame> req(
3589 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3590 const int kChunks = 5;
3591 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
3593 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3594 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3595 MockRead reads[] = {
3596 CreateMockRead(*resp),
3597 CreateMockRead(*body),
3598 MockRead(ASYNC, 0, 0) // EOF
3601 DelayedSocketData data(kChunks, reads, arraysize(reads),
3602 writes.get(), kChunks);
3603 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3604 BoundNetLog(), GetParam(), NULL);
3605 helper.RunToCompletion(&data);
3606 TransactionHelperResult out = helper.output();
3607 EXPECT_EQ(OK, out.rv);
3608 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3609 EXPECT_EQ("hello!", out.response_data);
3612 // In this test, we enable compression, but get a uncompressed SynReply from
3613 // the server. Verify that teardown is all clean.
3614 TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
3615 scoped_ptr<SpdyFrame> compressed(
3616 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
3617 scoped_ptr<SpdyFrame> rst(
3618 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3619 MockWrite writes[] = {
3620 CreateMockWrite(*compressed),
3623 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3624 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3625 MockRead reads[] = {
3626 CreateMockRead(*resp),
3629 DelayedSocketData data(1, reads, arraysize(reads),
3630 writes, arraysize(writes));
3631 SpdySessionDependencies* session_deps =
3632 CreateSpdySessionDependencies(GetParam());
3633 session_deps->enable_compression = true;
3634 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3635 BoundNetLog(), GetParam(), session_deps);
3636 helper.RunToCompletion(&data);
3637 TransactionHelperResult out = helper.output();
3638 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3642 // Test that the NetLog contains good data for a simple GET request.
3643 TEST_P(SpdyNetworkTransactionTest, NetLog) {
3644 static const char* const kExtraHeaders[] = {
3645 "user-agent", "Chrome",
3647 scoped_ptr<SpdyFrame> req(
3648 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
3649 MockWrite writes[] = { CreateMockWrite(*req) };
3651 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3652 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3653 MockRead reads[] = {
3654 CreateMockRead(*resp),
3655 CreateMockRead(*body),
3656 MockRead(ASYNC, 0, 0) // EOF
3659 CapturingBoundNetLog log;
3661 DelayedSocketData data(1, reads, arraysize(reads),
3662 writes, arraysize(writes));
3663 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
3665 log.bound(), GetParam(), NULL);
3666 helper.RunToCompletion(&data);
3667 TransactionHelperResult out = helper.output();
3668 EXPECT_EQ(OK, out.rv);
3669 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3670 EXPECT_EQ("hello!", out.response_data);
3672 // Check that the NetLog was filled reasonably.
3673 // This test is intentionally non-specific about the exact ordering of the
3674 // log; instead we just check to make sure that certain events exist, and that
3675 // they are in the right order.
3676 net::CapturingNetLog::CapturedEntryList entries;
3677 log.GetEntries(&entries);
3679 EXPECT_LT(0u, entries.size());
3681 pos = net::ExpectLogContainsSomewhere(entries, 0,
3682 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3683 net::NetLog::PHASE_BEGIN);
3684 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3685 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3686 net::NetLog::PHASE_END);
3687 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3688 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3689 net::NetLog::PHASE_BEGIN);
3690 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3691 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3692 net::NetLog::PHASE_END);
3693 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3694 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3695 net::NetLog::PHASE_BEGIN);
3696 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3697 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3698 net::NetLog::PHASE_END);
3700 // Check that we logged all the headers correctly
3701 pos = net::ExpectLogContainsSomewhere(
3703 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
3704 net::NetLog::PHASE_NONE);
3706 base::ListValue* header_list;
3707 ASSERT_TRUE(entries[pos].params.get());
3708 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3710 std::vector<std::string> expected;
3711 expected.push_back(std::string(spdy_util_.GetHostKey()) + ": www.google.com");
3712 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
3713 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": http");
3714 expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
3715 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
3716 expected.push_back("user-agent: Chrome");
3717 EXPECT_EQ(expected.size(), header_list->GetSize());
3718 for (std::vector<std::string>::const_iterator it = expected.begin();
3719 it != expected.end();
3721 base::StringValue header(*it);
3722 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3723 "Header not found: " << *it;
3727 // Since we buffer the IO from the stream to the renderer, this test verifies
3728 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3729 // on the network, but issued a Read for only 5 of those bytes) that the data
3730 // flow still works correctly.
3731 TEST_P(SpdyNetworkTransactionTest, BufferFull) {
3732 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3734 scoped_ptr<SpdyFrame> req(
3735 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3736 MockWrite writes[] = { CreateMockWrite(*req) };
3738 // 2 data frames in a single read.
3739 scoped_ptr<SpdyFrame> data_frame_1(
3740 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
3741 scoped_ptr<SpdyFrame> data_frame_2(
3742 framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
3743 const SpdyFrame* data_frames[2] = {
3747 char combined_data_frames[100];
3748 int combined_data_frames_len =
3749 CombineFrames(data_frames, arraysize(data_frames),
3750 combined_data_frames, arraysize(combined_data_frames));
3751 scoped_ptr<SpdyFrame> last_frame(
3752 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
3754 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3755 MockRead reads[] = {
3756 CreateMockRead(*resp),
3757 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3758 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3759 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3760 CreateMockRead(*last_frame),
3761 MockRead(ASYNC, 0, 0) // EOF
3764 DelayedSocketData data(1, reads, arraysize(reads),
3765 writes, arraysize(writes));
3767 TestCompletionCallback callback;
3769 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3770 BoundNetLog(), GetParam(), NULL);
3771 helper.RunPreTestSetup();
3772 helper.AddData(&data);
3773 HttpNetworkTransaction* trans = helper.trans();
3774 int rv = trans->Start(
3775 &CreateGetRequest(), callback.callback(), BoundNetLog());
3776 EXPECT_EQ(ERR_IO_PENDING, rv);
3778 TransactionHelperResult out = helper.output();
3779 out.rv = callback.WaitForResult();
3780 EXPECT_EQ(out.rv, OK);
3782 const HttpResponseInfo* response = trans->GetResponseInfo();
3783 EXPECT_TRUE(response->headers.get() != NULL);
3784 EXPECT_TRUE(response->was_fetched_via_spdy);
3785 out.status_line = response->headers->GetStatusLine();
3786 out.response_info = *response; // Make a copy so we can verify.
3789 TestCompletionCallback read_callback;
3791 std::string content;
3793 // Read small chunks at a time.
3794 const int kSmallReadSize = 3;
3795 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3796 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3797 if (rv == net::ERR_IO_PENDING) {
3798 data.CompleteRead();
3799 rv = read_callback.WaitForResult();
3802 content.append(buf->data(), rv);
3803 } else if (rv < 0) {
3808 out.response_data.swap(content);
3810 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3811 // MockClientSocketFactory) are still alive.
3812 base::RunLoop().RunUntilIdle();
3814 // Verify that we consumed all test data.
3815 helper.VerifyDataConsumed();
3817 EXPECT_EQ(OK, out.rv);
3818 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3819 EXPECT_EQ("goodbye world", out.response_data);
3822 // Verify that basic buffering works; when multiple data frames arrive
3823 // at the same time, ensure that we don't notify a read completion for
3824 // each data frame individually.
3825 TEST_P(SpdyNetworkTransactionTest, Buffering) {
3826 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3828 scoped_ptr<SpdyFrame> req(
3829 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3830 MockWrite writes[] = { CreateMockWrite(*req) };
3832 // 4 data frames in a single read.
3833 scoped_ptr<SpdyFrame> data_frame(
3834 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3835 scoped_ptr<SpdyFrame> data_frame_fin(
3836 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3837 const SpdyFrame* data_frames[4] = {
3841 data_frame_fin.get()
3843 char combined_data_frames[100];
3844 int combined_data_frames_len =
3845 CombineFrames(data_frames, arraysize(data_frames),
3846 combined_data_frames, arraysize(combined_data_frames));
3848 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3849 MockRead reads[] = {
3850 CreateMockRead(*resp),
3851 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3852 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3853 MockRead(ASYNC, 0, 0) // EOF
3856 DelayedSocketData data(1, reads, arraysize(reads),
3857 writes, arraysize(writes));
3859 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3860 BoundNetLog(), GetParam(), NULL);
3861 helper.RunPreTestSetup();
3862 helper.AddData(&data);
3863 HttpNetworkTransaction* trans = helper.trans();
3865 TestCompletionCallback callback;
3866 int rv = trans->Start(
3867 &CreateGetRequest(), callback.callback(), BoundNetLog());
3868 EXPECT_EQ(ERR_IO_PENDING, rv);
3870 TransactionHelperResult out = helper.output();
3871 out.rv = callback.WaitForResult();
3872 EXPECT_EQ(out.rv, OK);
3874 const HttpResponseInfo* response = trans->GetResponseInfo();
3875 EXPECT_TRUE(response->headers.get() != NULL);
3876 EXPECT_TRUE(response->was_fetched_via_spdy);
3877 out.status_line = response->headers->GetStatusLine();
3878 out.response_info = *response; // Make a copy so we can verify.
3881 TestCompletionCallback read_callback;
3883 std::string content;
3884 int reads_completed = 0;
3886 // Read small chunks at a time.
3887 const int kSmallReadSize = 14;
3888 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3889 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3890 if (rv == net::ERR_IO_PENDING) {
3891 data.CompleteRead();
3892 rv = read_callback.WaitForResult();
3895 EXPECT_EQ(kSmallReadSize, rv);
3896 content.append(buf->data(), rv);
3897 } else if (rv < 0) {
3898 FAIL() << "Unexpected read error: " << rv;
3903 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3905 out.response_data.swap(content);
3907 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3908 // MockClientSocketFactory) are still alive.
3909 base::RunLoop().RunUntilIdle();
3911 // Verify that we consumed all test data.
3912 helper.VerifyDataConsumed();
3914 EXPECT_EQ(OK, out.rv);
3915 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3916 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3919 // Verify the case where we buffer data but read it after it has been buffered.
3920 TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
3921 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3923 scoped_ptr<SpdyFrame> req(
3924 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3925 MockWrite writes[] = { CreateMockWrite(*req) };
3927 // 5 data frames in a single read.
3928 scoped_ptr<SpdyFrame> syn_reply(
3929 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3931 test::SetFrameFlags(
3932 syn_reply.get(), CONTROL_FLAG_NONE, spdy_util_.spdy_version());
3933 scoped_ptr<SpdyFrame> data_frame(
3934 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3935 scoped_ptr<SpdyFrame> data_frame_fin(
3936 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3937 const SpdyFrame* frames[5] = {
3942 data_frame_fin.get()
3944 char combined_frames[200];
3945 int combined_frames_len =
3946 CombineFrames(frames, arraysize(frames),
3947 combined_frames, arraysize(combined_frames));
3949 MockRead reads[] = {
3950 MockRead(ASYNC, combined_frames, combined_frames_len),
3951 MockRead(ASYNC, 0, 0) // EOF
3954 DelayedSocketData data(1, reads, arraysize(reads),
3955 writes, arraysize(writes));
3957 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3958 BoundNetLog(), GetParam(), NULL);
3959 helper.RunPreTestSetup();
3960 helper.AddData(&data);
3961 HttpNetworkTransaction* trans = helper.trans();
3963 TestCompletionCallback callback;
3964 int rv = trans->Start(
3965 &CreateGetRequest(), callback.callback(), BoundNetLog());
3966 EXPECT_EQ(ERR_IO_PENDING, rv);
3968 TransactionHelperResult out = helper.output();
3969 out.rv = callback.WaitForResult();
3970 EXPECT_EQ(out.rv, OK);
3972 const HttpResponseInfo* response = trans->GetResponseInfo();
3973 EXPECT_TRUE(response->headers.get() != NULL);
3974 EXPECT_TRUE(response->was_fetched_via_spdy);
3975 out.status_line = response->headers->GetStatusLine();
3976 out.response_info = *response; // Make a copy so we can verify.
3979 TestCompletionCallback read_callback;
3981 std::string content;
3982 int reads_completed = 0;
3984 // Read small chunks at a time.
3985 const int kSmallReadSize = 14;
3986 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3987 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3989 EXPECT_EQ(kSmallReadSize, rv);
3990 content.append(buf->data(), rv);
3991 } else if (rv < 0) {
3992 FAIL() << "Unexpected read error: " << rv;
3997 EXPECT_EQ(3, reads_completed);
3999 out.response_data.swap(content);
4001 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4002 // MockClientSocketFactory) are still alive.
4003 base::RunLoop().RunUntilIdle();
4005 // Verify that we consumed all test data.
4006 helper.VerifyDataConsumed();
4008 EXPECT_EQ(OK, out.rv);
4009 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4010 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4013 // Verify the case where we buffer data and close the connection.
4014 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
4015 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4017 scoped_ptr<SpdyFrame> req(
4018 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4019 MockWrite writes[] = { CreateMockWrite(*req) };
4021 // All data frames in a single read.
4022 // NOTE: We don't FIN the stream.
4023 scoped_ptr<SpdyFrame> data_frame(
4024 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4025 const SpdyFrame* data_frames[4] = {
4031 char combined_data_frames[100];
4032 int combined_data_frames_len =
4033 CombineFrames(data_frames, arraysize(data_frames),
4034 combined_data_frames, arraysize(combined_data_frames));
4035 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4036 MockRead reads[] = {
4037 CreateMockRead(*resp),
4038 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4039 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4040 MockRead(ASYNC, 0, 0) // EOF
4043 DelayedSocketData data(1, reads, arraysize(reads),
4044 writes, arraysize(writes));
4046 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4047 BoundNetLog(), GetParam(), NULL);
4048 helper.RunPreTestSetup();
4049 helper.AddData(&data);
4050 HttpNetworkTransaction* trans = helper.trans();
4052 TestCompletionCallback callback;
4054 int rv = trans->Start(
4055 &CreateGetRequest(), callback.callback(), BoundNetLog());
4056 EXPECT_EQ(ERR_IO_PENDING, rv);
4058 TransactionHelperResult out = helper.output();
4059 out.rv = callback.WaitForResult();
4060 EXPECT_EQ(out.rv, OK);
4062 const HttpResponseInfo* response = trans->GetResponseInfo();
4063 EXPECT_TRUE(response->headers.get() != NULL);
4064 EXPECT_TRUE(response->was_fetched_via_spdy);
4065 out.status_line = response->headers->GetStatusLine();
4066 out.response_info = *response; // Make a copy so we can verify.
4069 TestCompletionCallback read_callback;
4071 std::string content;
4072 int reads_completed = 0;
4074 // Read small chunks at a time.
4075 const int kSmallReadSize = 14;
4076 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4077 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4078 if (rv == net::ERR_IO_PENDING) {
4079 data.CompleteRead();
4080 rv = read_callback.WaitForResult();
4083 content.append(buf->data(), rv);
4084 } else if (rv < 0) {
4085 // This test intentionally closes the connection, and will get an error.
4086 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
4092 EXPECT_EQ(0, reads_completed);
4094 out.response_data.swap(content);
4096 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4097 // MockClientSocketFactory) are still alive.
4098 base::RunLoop().RunUntilIdle();
4100 // Verify that we consumed all test data.
4101 helper.VerifyDataConsumed();
4104 // Verify the case where we buffer data and cancel the transaction.
4105 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
4106 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4108 scoped_ptr<SpdyFrame> req(
4109 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4110 MockWrite writes[] = { CreateMockWrite(*req) };
4112 // NOTE: We don't FIN the stream.
4113 scoped_ptr<SpdyFrame> data_frame(
4114 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4116 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4117 MockRead reads[] = {
4118 CreateMockRead(*resp),
4119 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4120 CreateMockRead(*data_frame),
4121 MockRead(ASYNC, 0, 0) // EOF
4124 DelayedSocketData data(1, reads, arraysize(reads),
4125 writes, arraysize(writes));
4127 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4128 BoundNetLog(), GetParam(), NULL);
4129 helper.RunPreTestSetup();
4130 helper.AddData(&data);
4131 HttpNetworkTransaction* trans = helper.trans();
4132 TestCompletionCallback callback;
4134 int rv = trans->Start(
4135 &CreateGetRequest(), callback.callback(), BoundNetLog());
4136 EXPECT_EQ(ERR_IO_PENDING, rv);
4138 TransactionHelperResult out = helper.output();
4139 out.rv = callback.WaitForResult();
4140 EXPECT_EQ(out.rv, OK);
4142 const HttpResponseInfo* response = trans->GetResponseInfo();
4143 EXPECT_TRUE(response->headers.get() != NULL);
4144 EXPECT_TRUE(response->was_fetched_via_spdy);
4145 out.status_line = response->headers->GetStatusLine();
4146 out.response_info = *response; // Make a copy so we can verify.
4149 TestCompletionCallback read_callback;
4152 const int kReadSize = 256;
4153 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
4154 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
4155 if (rv == net::ERR_IO_PENDING) {
4156 // Complete the read now, which causes buffering to start.
4157 data.CompleteRead();
4158 // Destroy the transaction, causing the stream to get cancelled
4159 // and orphaning the buffered IO task.
4160 helper.ResetTrans();
4163 // We shouldn't get here in this test.
4164 FAIL() << "Unexpected read: " << rv;
4167 // Flush the MessageLoop; this will cause the buffered IO task
4168 // to run for the final time.
4169 base::RunLoop().RunUntilIdle();
4171 // Verify that we consumed all test data.
4172 helper.VerifyDataConsumed();
4175 // Test that if the server requests persistence of settings, that we save
4176 // the settings in the HttpServerProperties.
4177 TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
4178 static const SpdyHeaderInfo kSynReplyInfo = {
4179 SYN_REPLY, // Syn Reply
4181 0, // Associated Stream ID
4182 ConvertRequestPriorityToSpdyPriority(
4183 LOWEST, spdy_util_.spdy_version()),
4184 kSpdyCredentialSlotUnused,
4185 CONTROL_FLAG_NONE, // Control Flags
4186 false, // Compressed
4187 RST_STREAM_INVALID, // Status
4190 DATA_FLAG_NONE // Data Flags
4193 BoundNetLog net_log;
4194 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4195 net_log, GetParam(), NULL);
4196 helper.RunPreTestSetup();
4198 // Verify that no settings exist initially.
4199 HostPortPair host_port_pair("www.google.com", helper.port());
4200 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4201 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4202 host_port_pair).empty());
4204 // Construct the request.
4205 scoped_ptr<SpdyFrame> req(
4206 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4207 MockWrite writes[] = { CreateMockWrite(*req) };
4209 // Construct the reply.
4210 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4211 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4212 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4213 scoped_ptr<SpdyFrame> reply(
4214 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4216 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
4217 unsigned int kSampleValue1 = 0x0a0a0a0a;
4218 const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
4219 unsigned int kSampleValue2 = 0x0b0b0b0b;
4220 const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
4221 unsigned int kSampleValue3 = 0x0c0c0c0c;
4222 scoped_ptr<SpdyFrame> settings_frame;
4224 // Construct the SETTINGS frame.
4225 SettingsMap settings;
4226 // First add a persisted setting.
4227 settings[kSampleId1] =
4228 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
4229 // Next add a non-persisted setting.
4230 settings[kSampleId2] =
4231 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
4232 // Next add another persisted setting.
4233 settings[kSampleId3] =
4234 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
4235 settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
4238 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4239 MockRead reads[] = {
4240 CreateMockRead(*reply),
4241 CreateMockRead(*body),
4242 CreateMockRead(*settings_frame),
4243 MockRead(ASYNC, 0, 0) // EOF
4246 DelayedSocketData data(1, reads, arraysize(reads),
4247 writes, arraysize(writes));
4248 helper.AddData(&data);
4249 helper.RunDefaultTest();
4250 helper.VerifyDataConsumed();
4251 TransactionHelperResult out = helper.output();
4252 EXPECT_EQ(OK, out.rv);
4253 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4254 EXPECT_EQ("hello!", out.response_data);
4257 // Verify we had two persisted settings.
4258 const SettingsMap& settings_map =
4259 spdy_session_pool->http_server_properties()->GetSpdySettings(
4261 ASSERT_EQ(2u, settings_map.size());
4263 // Verify the first persisted setting.
4264 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4265 EXPECT_TRUE(it1 != settings_map.end());
4266 SettingsFlagsAndValue flags_and_value1 = it1->second;
4267 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4268 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4270 // Verify the second persisted setting.
4271 SettingsMap::const_iterator it3 = settings_map.find(kSampleId3);
4272 EXPECT_TRUE(it3 != settings_map.end());
4273 SettingsFlagsAndValue flags_and_value3 = it3->second;
4274 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first);
4275 EXPECT_EQ(kSampleValue3, flags_and_value3.second);
4279 // Test that when there are settings saved that they are sent back to the
4280 // server upon session establishment.
4281 TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
4282 static const SpdyHeaderInfo kSynReplyInfo = {
4283 SYN_REPLY, // Syn Reply
4285 0, // Associated Stream ID
4286 ConvertRequestPriorityToSpdyPriority(
4287 LOWEST, spdy_util_.spdy_version()),
4288 kSpdyCredentialSlotUnused,
4289 CONTROL_FLAG_NONE, // Control Flags
4290 false, // Compressed
4291 RST_STREAM_INVALID, // Status
4294 DATA_FLAG_NONE // Data Flags
4297 BoundNetLog net_log;
4298 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4299 net_log, GetParam(), NULL);
4300 helper.RunPreTestSetup();
4302 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4304 SpdySessionPoolPeer pool_peer(spdy_session_pool);
4305 pool_peer.SetEnableSendingInitialData(true);
4307 // Verify that no settings exist initially.
4308 HostPortPair host_port_pair("www.google.com", helper.port());
4309 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4310 host_port_pair).empty());
4312 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
4313 unsigned int kSampleValue1 = 0x0a0a0a0a;
4314 const SpdySettingsIds kSampleId2 = SETTINGS_ROUND_TRIP_TIME;
4315 unsigned int kSampleValue2 = 0x0c0c0c0c;
4317 // First add a persisted setting.
4318 spdy_session_pool->http_server_properties()->SetSpdySetting(
4321 SETTINGS_FLAG_PLEASE_PERSIST,
4324 // Next add another persisted setting.
4325 spdy_session_pool->http_server_properties()->SetSpdySetting(
4328 SETTINGS_FLAG_PLEASE_PERSIST,
4331 EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4332 host_port_pair).size());
4334 // Construct the initial SETTINGS frame.
4335 SettingsMap initial_settings;
4336 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4337 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
4338 scoped_ptr<SpdyFrame> initial_settings_frame(
4339 spdy_util_.ConstructSpdySettings(initial_settings));
4341 // Construct the initial window update.
4342 scoped_ptr<SpdyFrame> initial_window_update(
4343 spdy_util_.ConstructSpdyWindowUpdate(
4344 kSessionFlowControlStreamId,
4345 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
4347 // Construct the persisted SETTINGS frame.
4348 const SettingsMap& settings =
4349 spdy_session_pool->http_server_properties()->GetSpdySettings(
4351 scoped_ptr<SpdyFrame> settings_frame(
4352 spdy_util_.ConstructSpdySettings(settings));
4354 // Construct the request.
4355 scoped_ptr<SpdyFrame> req(
4356 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4358 std::vector<MockWrite> writes;
4359 if (GetParam().protocol == kProtoHTTP2Draft04) {
4362 kHttp2ConnectionHeaderPrefix,
4363 kHttp2ConnectionHeaderPrefixSize));
4365 writes.push_back(CreateMockWrite(*initial_settings_frame));
4366 if (GetParam().protocol >= kProtoSPDY31) {
4367 writes.push_back(CreateMockWrite(*initial_window_update));
4369 writes.push_back(CreateMockWrite(*settings_frame));
4370 writes.push_back(CreateMockWrite(*req));
4372 // Construct the reply.
4373 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4374 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4375 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4376 scoped_ptr<SpdyFrame> reply(
4377 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4379 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4380 MockRead reads[] = {
4381 CreateMockRead(*reply),
4382 CreateMockRead(*body),
4383 MockRead(ASYNC, 0, 0) // EOF
4386 DelayedSocketData data(2, reads, arraysize(reads),
4387 vector_as_array(&writes), writes.size());
4388 helper.AddData(&data);
4389 helper.RunDefaultTest();
4390 helper.VerifyDataConsumed();
4391 TransactionHelperResult out = helper.output();
4392 EXPECT_EQ(OK, out.rv);
4393 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4394 EXPECT_EQ("hello!", out.response_data);
4397 // Verify we had two persisted settings.
4398 const SettingsMap& settings_map =
4399 spdy_session_pool->http_server_properties()->GetSpdySettings(
4401 ASSERT_EQ(2u, settings_map.size());
4403 // Verify the first persisted setting.
4404 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4405 EXPECT_TRUE(it1 != settings_map.end());
4406 SettingsFlagsAndValue flags_and_value1 = it1->second;
4407 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4408 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4410 // Verify the second persisted setting.
4411 SettingsMap::const_iterator it2 = settings_map.find(kSampleId2);
4412 EXPECT_TRUE(it2 != settings_map.end());
4413 SettingsFlagsAndValue flags_and_value2 = it2->second;
4414 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first);
4415 EXPECT_EQ(kSampleValue2, flags_and_value2.second);
4419 TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
4420 scoped_ptr<SpdyFrame> req(
4421 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4422 MockWrite writes[] = { CreateMockWrite(*req) };
4424 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
4425 MockRead reads[] = {
4426 CreateMockRead(*go_away),
4429 DelayedSocketData data(1, reads, arraysize(reads),
4430 writes, arraysize(writes));
4431 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4432 BoundNetLog(), GetParam(), NULL);
4433 helper.AddData(&data);
4434 helper.RunToCompletion(&data);
4435 TransactionHelperResult out = helper.output();
4436 EXPECT_EQ(ERR_ABORTED, out.rv);
4439 TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
4440 scoped_ptr<SpdyFrame> req(
4441 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4442 MockWrite writes[] = { CreateMockWrite(*req) };
4444 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4445 MockRead reads[] = {
4446 CreateMockRead(*resp),
4447 MockRead(SYNCHRONOUS, 0, 0) // EOF
4450 DelayedSocketData data(1, reads, arraysize(reads),
4451 writes, arraysize(writes));
4453 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4454 log, GetParam(), NULL);
4455 helper.RunPreTestSetup();
4456 helper.AddData(&data);
4457 HttpNetworkTransaction* trans = helper.trans();
4459 TestCompletionCallback callback;
4460 TransactionHelperResult out;
4461 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
4463 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4464 out.rv = callback.WaitForResult();
4465 EXPECT_EQ(out.rv, OK);
4467 const HttpResponseInfo* response = trans->GetResponseInfo();
4468 EXPECT_TRUE(response->headers.get() != NULL);
4469 EXPECT_TRUE(response->was_fetched_via_spdy);
4470 out.rv = ReadTransaction(trans, &out.response_data);
4471 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4473 // Verify that we consumed all test data.
4474 helper.VerifyDataConsumed();
4477 // Test to make sure we can correctly connect through a proxy.
4478 TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
4479 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4480 BoundNetLog(), GetParam(), NULL);
4481 helper.session_deps().reset(CreateSpdySessionDependencies(
4483 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4484 helper.SetSession(make_scoped_refptr(
4485 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4486 helper.RunPreTestSetup();
4487 HttpNetworkTransaction* trans = helper.trans();
4489 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4490 "Host: www.google.com\r\n"
4491 "Proxy-Connection: keep-alive\r\n\r\n"};
4492 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4493 "Host: www.google.com\r\n"
4494 "Proxy-Connection: keep-alive\r\n\r\n"};
4495 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4496 scoped_ptr<SpdyFrame> req(
4497 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4498 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4499 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4501 MockWrite writes_SPDYNPN[] = {
4502 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4503 CreateMockWrite(*req, 2),
4505 MockRead reads_SPDYNPN[] = {
4506 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4507 CreateMockRead(*resp, 3),
4508 CreateMockRead(*body.get(), 4),
4509 MockRead(ASYNC, 0, 0, 5),
4512 MockWrite writes_SPDYSSL[] = {
4513 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4514 CreateMockWrite(*req, 2),
4516 MockRead reads_SPDYSSL[] = {
4517 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4518 CreateMockRead(*resp, 3),
4519 CreateMockRead(*body.get(), 4),
4520 MockRead(ASYNC, 0, 0, 5),
4523 MockWrite writes_SPDYNOSSL[] = {
4524 CreateMockWrite(*req, 0),
4527 MockRead reads_SPDYNOSSL[] = {
4528 CreateMockRead(*resp, 1),
4529 CreateMockRead(*body.get(), 2),
4530 MockRead(ASYNC, 0, 0, 3),
4533 scoped_ptr<OrderedSocketData> data;
4534 switch(GetParam().ssl_type) {
4536 data.reset(new OrderedSocketData(reads_SPDYNOSSL,
4537 arraysize(reads_SPDYNOSSL),
4539 arraysize(writes_SPDYNOSSL)));
4542 data.reset(new OrderedSocketData(reads_SPDYSSL,
4543 arraysize(reads_SPDYSSL),
4545 arraysize(writes_SPDYSSL)));
4548 data.reset(new OrderedSocketData(reads_SPDYNPN,
4549 arraysize(reads_SPDYNPN),
4551 arraysize(writes_SPDYNPN)));
4557 helper.AddData(data.get());
4558 TestCompletionCallback callback;
4560 int rv = trans->Start(
4561 &CreateGetRequest(), callback.callback(), BoundNetLog());
4562 EXPECT_EQ(ERR_IO_PENDING, rv);
4564 rv = callback.WaitForResult();
4567 // Verify the SYN_REPLY.
4568 HttpResponseInfo response = *trans->GetResponseInfo();
4569 EXPECT_TRUE(response.headers.get() != NULL);
4570 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4572 std::string response_data;
4573 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4574 EXPECT_EQ("hello!", response_data);
4575 helper.VerifyDataConsumed();
4578 // Test to make sure we can correctly connect through a proxy to www.google.com,
4579 // if there already exists a direct spdy connection to www.google.com. See
4580 // http://crbug.com/49874
4581 TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
4582 // When setting up the first transaction, we store the SpdySessionPool so that
4583 // we can use the same pool in the second transaction.
4584 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4585 BoundNetLog(), GetParam(), NULL);
4587 // Use a proxy service which returns a proxy fallback list from DIRECT to
4588 // myproxy:70. For this test there will be no fallback, so it is equivalent
4589 // to simply DIRECT. The reason for appending the second proxy is to verify
4590 // that the session pool key used does is just "DIRECT".
4591 helper.session_deps().reset(CreateSpdySessionDependencies(
4593 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4594 helper.SetSession(make_scoped_refptr(
4595 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4597 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4598 helper.RunPreTestSetup();
4600 // Construct and send a simple GET request.
4601 scoped_ptr<SpdyFrame> req(
4602 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4603 MockWrite writes[] = {
4604 CreateMockWrite(*req, 1),
4607 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4608 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4609 MockRead reads[] = {
4610 CreateMockRead(*resp, 2),
4611 CreateMockRead(*body, 3),
4612 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
4613 MockRead(ASYNC, 0, 5) // EOF
4615 OrderedSocketData data(reads, arraysize(reads),
4616 writes, arraysize(writes));
4617 helper.AddData(&data);
4618 HttpNetworkTransaction* trans = helper.trans();
4620 TestCompletionCallback callback;
4621 TransactionHelperResult out;
4622 out.rv = trans->Start(
4623 &CreateGetRequest(), callback.callback(), BoundNetLog());
4625 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4626 out.rv = callback.WaitForResult();
4627 EXPECT_EQ(out.rv, OK);
4629 const HttpResponseInfo* response = trans->GetResponseInfo();
4630 EXPECT_TRUE(response->headers.get() != NULL);
4631 EXPECT_TRUE(response->was_fetched_via_spdy);
4632 out.rv = ReadTransaction(trans, &out.response_data);
4633 EXPECT_EQ(OK, out.rv);
4634 out.status_line = response->headers->GetStatusLine();
4635 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4636 EXPECT_EQ("hello!", out.response_data);
4638 // Check that the SpdySession is still in the SpdySessionPool.
4639 HostPortPair host_port_pair("www.google.com", helper.port());
4640 SpdySessionKey session_pool_key_direct(
4641 host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled);
4642 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
4643 SpdySessionKey session_pool_key_proxy(
4645 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
4646 kPrivacyModeDisabled);
4647 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
4649 // Set up data for the proxy connection.
4650 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4651 "Host: www.google.com\r\n"
4652 "Proxy-Connection: keep-alive\r\n\r\n"};
4653 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4654 "Host: www.google.com\r\n"
4655 "Proxy-Connection: keep-alive\r\n\r\n"};
4656 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4657 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
4658 "http://www.google.com/foo.dat", false, 1, LOWEST));
4659 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4660 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
4662 MockWrite writes_SPDYNPN[] = {
4663 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4664 CreateMockWrite(*req2, 2),
4666 MockRead reads_SPDYNPN[] = {
4667 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4668 CreateMockRead(*resp2, 3),
4669 CreateMockRead(*body2, 4),
4670 MockRead(ASYNC, 0, 5) // EOF
4673 MockWrite writes_SPDYNOSSL[] = {
4674 CreateMockWrite(*req2, 0),
4676 MockRead reads_SPDYNOSSL[] = {
4677 CreateMockRead(*resp2, 1),
4678 CreateMockRead(*body2, 2),
4679 MockRead(ASYNC, 0, 3) // EOF
4682 MockWrite writes_SPDYSSL[] = {
4683 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4684 CreateMockWrite(*req2, 2),
4686 MockRead reads_SPDYSSL[] = {
4687 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4688 CreateMockRead(*resp2, 3),
4689 CreateMockRead(*body2, 4),
4690 MockRead(ASYNC, 0, 0, 5),
4693 scoped_ptr<OrderedSocketData> data_proxy;
4694 switch(GetParam().ssl_type) {
4696 data_proxy.reset(new OrderedSocketData(reads_SPDYNPN,
4697 arraysize(reads_SPDYNPN),
4699 arraysize(writes_SPDYNPN)));
4702 data_proxy.reset(new OrderedSocketData(reads_SPDYNOSSL,
4703 arraysize(reads_SPDYNOSSL),
4705 arraysize(writes_SPDYNOSSL)));
4708 data_proxy.reset(new OrderedSocketData(reads_SPDYSSL,
4709 arraysize(reads_SPDYSSL),
4711 arraysize(writes_SPDYSSL)));
4717 // Create another request to www.google.com, but this time through a proxy.
4718 HttpRequestInfo request_proxy;
4719 request_proxy.method = "GET";
4720 request_proxy.url = GURL("http://www.google.com/foo.dat");
4721 request_proxy.load_flags = 0;
4722 scoped_ptr<SpdySessionDependencies> ssd_proxy(
4723 CreateSpdySessionDependencies(GetParam()));
4724 // Ensure that this transaction uses the same SpdySessionPool.
4725 scoped_refptr<HttpNetworkSession> session_proxy(
4726 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
4727 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
4728 BoundNetLog(), GetParam(), NULL);
4729 HttpNetworkSessionPeer session_peer(session_proxy);
4730 scoped_ptr<net::ProxyService> proxy_service(
4731 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
4732 session_peer.SetProxyService(proxy_service.get());
4733 helper_proxy.session_deps().swap(ssd_proxy);
4734 helper_proxy.SetSession(session_proxy);
4735 helper_proxy.RunPreTestSetup();
4736 helper_proxy.AddData(data_proxy.get());
4738 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
4739 TestCompletionCallback callback_proxy;
4740 int rv = trans_proxy->Start(
4741 &request_proxy, callback_proxy.callback(), BoundNetLog());
4742 EXPECT_EQ(ERR_IO_PENDING, rv);
4743 rv = callback_proxy.WaitForResult();
4746 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
4747 EXPECT_TRUE(response_proxy.headers.get() != NULL);
4748 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
4750 std::string response_data;
4751 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
4752 EXPECT_EQ("hello!", response_data);
4754 data.CompleteRead();
4755 helper_proxy.VerifyDataConsumed();
4758 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4759 // on a new connection, if the connection was previously known to be good.
4760 // This can happen when a server reboots without saying goodbye, or when
4761 // we're behind a NAT that masked the RST.
4762 TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
4763 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4764 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4765 MockRead reads[] = {
4766 CreateMockRead(*resp),
4767 CreateMockRead(*body),
4768 MockRead(ASYNC, ERR_IO_PENDING),
4769 MockRead(ASYNC, ERR_CONNECTION_RESET),
4772 MockRead reads2[] = {
4773 CreateMockRead(*resp),
4774 CreateMockRead(*body),
4775 MockRead(ASYNC, 0, 0) // EOF
4778 // This test has a couple of variants.
4780 // Induce the RST while waiting for our transaction to send.
4781 VARIANT_RST_DURING_SEND_COMPLETION,
4782 // Induce the RST while waiting for our transaction to read.
4783 // In this case, the send completed - everything copied into the SNDBUF.
4784 VARIANT_RST_DURING_READ_COMPLETION
4787 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4788 variant <= VARIANT_RST_DURING_READ_COMPLETION;
4790 DelayedSocketData data1(1, reads, arraysize(reads), NULL, 0);
4792 DelayedSocketData data2(1, reads2, arraysize(reads2), NULL, 0);
4794 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4795 BoundNetLog(), GetParam(), NULL);
4796 helper.AddData(&data1);
4797 helper.AddData(&data2);
4798 helper.RunPreTestSetup();
4800 for (int i = 0; i < 2; ++i) {
4801 scoped_ptr<HttpNetworkTransaction> trans(
4802 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
4804 TestCompletionCallback callback;
4805 int rv = trans->Start(
4806 &helper.request(), callback.callback(), BoundNetLog());
4807 EXPECT_EQ(ERR_IO_PENDING, rv);
4808 // On the second transaction, we trigger the RST.
4810 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4811 // Writes to the socket complete asynchronously on SPDY by running
4812 // through the message loop. Complete the write here.
4813 base::RunLoop().RunUntilIdle();
4816 // Now schedule the ERR_CONNECTION_RESET.
4817 EXPECT_EQ(3u, data1.read_index());
4818 data1.CompleteRead();
4819 EXPECT_EQ(4u, data1.read_index());
4821 rv = callback.WaitForResult();
4824 const HttpResponseInfo* response = trans->GetResponseInfo();
4825 ASSERT_TRUE(response != NULL);
4826 EXPECT_TRUE(response->headers.get() != NULL);
4827 EXPECT_TRUE(response->was_fetched_via_spdy);
4828 std::string response_data;
4829 rv = ReadTransaction(trans.get(), &response_data);
4831 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4832 EXPECT_EQ("hello!", response_data);
4835 helper.VerifyDataConsumed();
4839 // Test that turning SPDY on and off works properly.
4840 TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
4841 net::HttpStreamFactory::set_spdy_enabled(true);
4842 scoped_ptr<SpdyFrame> req(
4843 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4844 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
4846 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4847 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4848 MockRead spdy_reads[] = {
4849 CreateMockRead(*resp),
4850 CreateMockRead(*body),
4851 MockRead(ASYNC, 0, 0) // EOF
4854 DelayedSocketData data(1, spdy_reads, arraysize(spdy_reads),
4855 spdy_writes, arraysize(spdy_writes));
4856 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4857 BoundNetLog(), GetParam(), NULL);
4858 helper.RunToCompletion(&data);
4859 TransactionHelperResult out = helper.output();
4860 EXPECT_EQ(OK, out.rv);
4861 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4862 EXPECT_EQ("hello!", out.response_data);
4864 net::HttpStreamFactory::set_spdy_enabled(false);
4865 MockRead http_reads[] = {
4866 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4867 MockRead("hello from http"),
4868 MockRead(SYNCHRONOUS, OK),
4870 DelayedSocketData data2(1, http_reads, arraysize(http_reads), NULL, 0);
4871 NormalSpdyTransactionHelper helper2(CreateGetRequest(), DEFAULT_PRIORITY,
4872 BoundNetLog(), GetParam(), NULL);
4873 helper2.SetSpdyDisabled();
4874 helper2.RunToCompletion(&data2);
4875 TransactionHelperResult out2 = helper2.output();
4876 EXPECT_EQ(OK, out2.rv);
4877 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
4878 EXPECT_EQ("hello from http", out2.response_data);
4880 net::HttpStreamFactory::set_spdy_enabled(true);
4883 // Tests that Basic authentication works over SPDY
4884 TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
4885 net::HttpStreamFactory::set_spdy_enabled(true);
4887 // The first request will be a bare GET, the second request will be a
4888 // GET with an Authorization header.
4889 scoped_ptr<SpdyFrame> req_get(
4890 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4891 const char* const kExtraAuthorizationHeaders[] = {
4892 "authorization", "Basic Zm9vOmJhcg=="
4894 scoped_ptr<SpdyFrame> req_get_authorization(
4895 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4896 arraysize(kExtraAuthorizationHeaders) / 2,
4897 false, 3, LOWEST, true));
4898 MockWrite spdy_writes[] = {
4899 CreateMockWrite(*req_get, 1),
4900 CreateMockWrite(*req_get_authorization, 4),
4903 // The first response is a 401 authentication challenge, and the second
4904 // response will be a 200 response since the second request includes a valid
4905 // Authorization header.
4906 const char* const kExtraAuthenticationHeaders[] = {
4908 "Basic realm=\"MyRealm\""
4910 scoped_ptr<SpdyFrame> resp_authentication(
4911 spdy_util_.ConstructSpdySynReplyError(
4912 "401 Authentication Required",
4913 kExtraAuthenticationHeaders,
4914 arraysize(kExtraAuthenticationHeaders) / 2,
4916 scoped_ptr<SpdyFrame> body_authentication(
4917 spdy_util_.ConstructSpdyBodyFrame(1, true));
4918 scoped_ptr<SpdyFrame> resp_data(
4919 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4920 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
4921 MockRead spdy_reads[] = {
4922 CreateMockRead(*resp_authentication, 2),
4923 CreateMockRead(*body_authentication, 3),
4924 CreateMockRead(*resp_data, 5),
4925 CreateMockRead(*body_data, 6),
4926 MockRead(ASYNC, 0, 7),
4929 OrderedSocketData data(spdy_reads, arraysize(spdy_reads),
4930 spdy_writes, arraysize(spdy_writes));
4931 HttpRequestInfo request(CreateGetRequest());
4932 BoundNetLog net_log;
4933 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
4934 net_log, GetParam(), NULL);
4936 helper.RunPreTestSetup();
4937 helper.AddData(&data);
4938 HttpNetworkTransaction* trans = helper.trans();
4939 TestCompletionCallback callback;
4940 const int rv_start = trans->Start(&request, callback.callback(), net_log);
4941 EXPECT_EQ(ERR_IO_PENDING, rv_start);
4942 const int rv_start_complete = callback.WaitForResult();
4943 EXPECT_EQ(OK, rv_start_complete);
4945 // Make sure the response has an auth challenge.
4946 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
4947 ASSERT_TRUE(response_start != NULL);
4948 ASSERT_TRUE(response_start->headers.get() != NULL);
4949 EXPECT_EQ(401, response_start->headers->response_code());
4950 EXPECT_TRUE(response_start->was_fetched_via_spdy);
4951 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
4952 ASSERT_TRUE(auth_challenge != NULL);
4953 EXPECT_FALSE(auth_challenge->is_proxy);
4954 EXPECT_EQ("basic", auth_challenge->scheme);
4955 EXPECT_EQ("MyRealm", auth_challenge->realm);
4957 // Restart with a username/password.
4958 AuthCredentials credentials(ASCIIToUTF16("foo"), ASCIIToUTF16("bar"));
4959 TestCompletionCallback callback_restart;
4960 const int rv_restart = trans->RestartWithAuth(
4961 credentials, callback_restart.callback());
4962 EXPECT_EQ(ERR_IO_PENDING, rv_restart);
4963 const int rv_restart_complete = callback_restart.WaitForResult();
4964 EXPECT_EQ(OK, rv_restart_complete);
4965 // TODO(cbentzel): This is actually the same response object as before, but
4966 // data has changed.
4967 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
4968 ASSERT_TRUE(response_restart != NULL);
4969 ASSERT_TRUE(response_restart->headers.get() != NULL);
4970 EXPECT_EQ(200, response_restart->headers->response_code());
4971 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
4974 TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
4975 scoped_ptr<SpdyFrame> stream1_syn(
4976 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4977 scoped_ptr<SpdyFrame> stream1_body(
4978 spdy_util_.ConstructSpdyBodyFrame(1, true));
4979 MockWrite writes[] = {
4980 CreateMockWrite(*stream1_syn, 1),
4983 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
4984 spdy_util_.AddUrlToHeaderBlock(
4985 "http://www.google.com/foo.dat", initial_headers.get());
4986 scoped_ptr<SpdyFrame> stream2_syn(
4987 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
4995 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
4996 (*late_headers)["hello"] = "bye";
4997 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
4998 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4999 scoped_ptr<SpdyFrame> stream2_headers(
5000 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5008 scoped_ptr<SpdyFrame>
5009 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5010 const char kPushedData[] = "pushed";
5011 scoped_ptr<SpdyFrame> stream2_body(
5012 spdy_util_.ConstructSpdyBodyFrame(
5013 2, kPushedData, strlen(kPushedData), true));
5014 MockRead reads[] = {
5015 CreateMockRead(*stream1_reply, 2),
5016 CreateMockRead(*stream2_syn, 3),
5017 CreateMockRead(*stream2_headers, 4),
5018 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5019 CreateMockRead(*stream2_body, 5),
5020 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5023 HttpResponseInfo response;
5024 HttpResponseInfo response2;
5025 std::string expected_push_result("pushed");
5026 OrderedSocketData data(reads, arraysize(reads),
5027 writes, arraysize(writes));
5028 RunServerPushTest(&data,
5031 expected_push_result);
5033 // Verify the SYN_REPLY.
5034 EXPECT_TRUE(response.headers.get() != NULL);
5035 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5037 // Verify the pushed stream.
5038 EXPECT_TRUE(response2.headers.get() != NULL);
5039 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5042 TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
5043 // We push a stream and attempt to claim it before the headers come down.
5044 scoped_ptr<SpdyFrame> stream1_syn(
5045 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5046 scoped_ptr<SpdyFrame> stream1_body(
5047 spdy_util_.ConstructSpdyBodyFrame(1, true));
5048 MockWrite writes[] = {
5049 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5052 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5053 spdy_util_.AddUrlToHeaderBlock(
5054 "http://www.google.com/foo.dat", initial_headers.get());
5055 scoped_ptr<SpdyFrame> stream2_syn(
5056 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
5064 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5065 (*late_headers)["hello"] = "bye";
5066 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5067 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5068 scoped_ptr<SpdyFrame> stream2_headers(
5069 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5077 scoped_ptr<SpdyFrame>
5078 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5079 const char kPushedData[] = "pushed";
5080 scoped_ptr<SpdyFrame> stream2_body(
5081 spdy_util_.ConstructSpdyBodyFrame(
5082 2, kPushedData, strlen(kPushedData), true));
5083 MockRead reads[] = {
5084 CreateMockRead(*stream1_reply, 1),
5085 CreateMockRead(*stream2_syn, 2),
5086 CreateMockRead(*stream1_body, 3),
5087 CreateMockRead(*stream2_headers, 4),
5088 CreateMockRead(*stream2_body, 5),
5089 MockRead(ASYNC, 0, 6), // EOF
5092 HttpResponseInfo response;
5093 HttpResponseInfo response2;
5094 std::string expected_push_result("pushed");
5095 DeterministicSocketData data(reads, arraysize(reads),
5096 writes, arraysize(writes));
5098 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5099 BoundNetLog(), GetParam(), NULL);
5100 helper.SetDeterministic();
5101 helper.AddDeterministicData(&data);
5102 helper.RunPreTestSetup();
5104 HttpNetworkTransaction* trans = helper.trans();
5106 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5107 // and the body of the primary stream, but before we've received the HEADERS
5108 // for the pushed stream.
5111 // Start the transaction.
5112 TestCompletionCallback callback;
5113 int rv = trans->Start(
5114 &CreateGetRequest(), callback.callback(), BoundNetLog());
5115 EXPECT_EQ(ERR_IO_PENDING, rv);
5117 rv = callback.WaitForResult();
5120 // Request the pushed path. At this point, we've received the push, but the
5121 // headers are not yet complete.
5122 scoped_ptr<HttpNetworkTransaction> trans2(
5123 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5125 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5126 EXPECT_EQ(ERR_IO_PENDING, rv);
5128 base::RunLoop().RunUntilIdle();
5130 // Read the server push body.
5131 std::string result2;
5132 ReadResult(trans2.get(), &data, &result2);
5133 // Read the response body.
5135 ReadResult(trans, &data, &result);
5137 // Verify that the received push data is same as the expected push data.
5138 EXPECT_EQ(result2.compare(expected_push_result), 0)
5139 << "Received data: "
5141 << "||||| Expected data: "
5142 << expected_push_result;
5144 // Verify the SYN_REPLY.
5145 // Copy the response info, because trans goes away.
5146 response = *trans->GetResponseInfo();
5147 response2 = *trans2->GetResponseInfo();
5149 VerifyStreamsClosed(helper);
5151 // Verify the SYN_REPLY.
5152 EXPECT_TRUE(response.headers.get() != NULL);
5153 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5155 // Verify the pushed stream.
5156 EXPECT_TRUE(response2.headers.get() != NULL);
5157 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5159 // Read the final EOF (which will close the session)
5162 // Verify that we consumed all test data.
5163 EXPECT_TRUE(data.at_read_eof());
5164 EXPECT_TRUE(data.at_write_eof());
5167 TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
5168 // We push a stream and attempt to claim it before the headers come down.
5169 scoped_ptr<SpdyFrame> stream1_syn(
5170 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5171 scoped_ptr<SpdyFrame> stream1_body(
5172 spdy_util_.ConstructSpdyBodyFrame(1, true));
5173 MockWrite writes[] = {
5174 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5177 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5178 spdy_util_.AddUrlToHeaderBlock(
5179 "http://www.google.com/foo.dat", initial_headers.get());
5180 scoped_ptr<SpdyFrame> stream2_syn(
5181 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
5189 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5190 (*middle_headers)["hello"] = "bye";
5191 scoped_ptr<SpdyFrame> stream2_headers1(
5192 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5200 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5201 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5202 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5203 scoped_ptr<SpdyFrame> stream2_headers2(
5204 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5212 scoped_ptr<SpdyFrame>
5213 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5214 const char kPushedData[] = "pushed";
5215 scoped_ptr<SpdyFrame> stream2_body(
5216 spdy_util_.ConstructSpdyBodyFrame(
5217 2, kPushedData, strlen(kPushedData), true));
5218 MockRead reads[] = {
5219 CreateMockRead(*stream1_reply, 1),
5220 CreateMockRead(*stream2_syn, 2),
5221 CreateMockRead(*stream1_body, 3),
5222 CreateMockRead(*stream2_headers1, 4),
5223 CreateMockRead(*stream2_headers2, 5),
5224 CreateMockRead(*stream2_body, 6),
5225 MockRead(ASYNC, 0, 7), // EOF
5228 HttpResponseInfo response;
5229 HttpResponseInfo response2;
5230 std::string expected_push_result("pushed");
5231 DeterministicSocketData data(reads, arraysize(reads),
5232 writes, arraysize(writes));
5234 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5235 BoundNetLog(), GetParam(), NULL);
5236 helper.SetDeterministic();
5237 helper.AddDeterministicData(&data);
5238 helper.RunPreTestSetup();
5240 HttpNetworkTransaction* trans = helper.trans();
5242 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5243 // the first HEADERS frame, and the body of the primary stream, but before
5244 // we've received the final HEADERS for the pushed stream.
5247 // Start the transaction.
5248 TestCompletionCallback callback;
5249 int rv = trans->Start(
5250 &CreateGetRequest(), callback.callback(), BoundNetLog());
5251 EXPECT_EQ(ERR_IO_PENDING, rv);
5253 rv = callback.WaitForResult();
5256 // Request the pushed path. At this point, we've received the push, but the
5257 // headers are not yet complete.
5258 scoped_ptr<HttpNetworkTransaction> trans2(
5259 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5261 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5262 EXPECT_EQ(ERR_IO_PENDING, rv);
5264 base::RunLoop().RunUntilIdle();
5266 // Read the server push body.
5267 std::string result2;
5268 ReadResult(trans2.get(), &data, &result2);
5269 // Read the response body.
5271 ReadResult(trans, &data, &result);
5273 // Verify that the received push data is same as the expected push data.
5274 EXPECT_EQ(expected_push_result, result2);
5276 // Verify the SYN_REPLY.
5277 // Copy the response info, because trans goes away.
5278 response = *trans->GetResponseInfo();
5279 response2 = *trans2->GetResponseInfo();
5281 VerifyStreamsClosed(helper);
5283 // Verify the SYN_REPLY.
5284 EXPECT_TRUE(response.headers.get() != NULL);
5285 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5287 // Verify the pushed stream.
5288 EXPECT_TRUE(response2.headers.get() != NULL);
5289 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5291 // Verify we got all the headers
5292 if (spdy_util_.spdy_version() < SPDY3) {
5293 EXPECT_TRUE(response2.headers->HasHeaderValue(
5295 "http://www.google.com/foo.dat"));
5297 EXPECT_TRUE(response2.headers->HasHeaderValue(
5299 EXPECT_TRUE(response2.headers->HasHeaderValue(
5300 "host", "www.google.com"));
5301 EXPECT_TRUE(response2.headers->HasHeaderValue(
5302 "path", "/foo.dat"));
5304 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5305 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
5306 EXPECT_TRUE(response2.headers->HasHeaderValue("version", "HTTP/1.1"));
5308 // Read the final EOF (which will close the session)
5311 // Verify that we consumed all test data.
5312 EXPECT_TRUE(data.at_read_eof());
5313 EXPECT_TRUE(data.at_write_eof());
5316 TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
5317 // We push a stream and attempt to claim it before the headers come down.
5318 scoped_ptr<SpdyFrame> stream1_syn(
5319 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5320 scoped_ptr<SpdyFrame> stream1_body(
5321 spdy_util_.ConstructSpdyBodyFrame(1, true));
5322 MockWrite writes[] = {
5323 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5326 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5327 spdy_util_.AddUrlToHeaderBlock(
5328 "http://www.google.com/foo.dat", initial_headers.get());
5329 scoped_ptr<SpdyFrame> stream2_syn(
5330 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
5338 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5339 (*middle_headers)["hello"] = "bye";
5340 scoped_ptr<SpdyFrame> stream2_headers1(
5341 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5349 scoped_ptr<SpdyFrame>
5350 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5351 const char kPushedData[] = "pushed";
5352 scoped_ptr<SpdyFrame> stream2_body(
5353 spdy_util_.ConstructSpdyBodyFrame(
5354 2, kPushedData, strlen(kPushedData), true));
5355 MockRead reads[] = {
5356 CreateMockRead(*stream1_reply, 1),
5357 CreateMockRead(*stream2_syn, 2),
5358 CreateMockRead(*stream1_body, 3),
5359 CreateMockRead(*stream2_headers1, 4),
5360 CreateMockRead(*stream2_body, 5),
5361 MockRead(ASYNC, 0, 6), // EOF
5364 DeterministicSocketData data(reads, arraysize(reads),
5365 writes, arraysize(writes));
5367 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5368 BoundNetLog(), GetParam(), NULL);
5369 helper.SetDeterministic();
5370 helper.AddDeterministicData(&data);
5371 helper.RunPreTestSetup();
5373 HttpNetworkTransaction* trans = helper.trans();
5375 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5376 // the first HEADERS frame, and the body of the primary stream, but before
5377 // we've received the final HEADERS for the pushed stream.
5380 // Start the transaction.
5381 TestCompletionCallback callback;
5382 int rv = trans->Start(
5383 &CreateGetRequest(), callback.callback(), BoundNetLog());
5384 EXPECT_EQ(ERR_IO_PENDING, rv);
5386 rv = callback.WaitForResult();
5389 // Request the pushed path. At this point, we've received the push, but the
5390 // headers are not yet complete.
5391 scoped_ptr<HttpNetworkTransaction> trans2(
5392 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5394 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5395 EXPECT_EQ(ERR_IO_PENDING, rv);
5397 base::RunLoop().RunUntilIdle();
5399 // Read the server push body.
5400 std::string result2;
5401 ReadResult(trans2.get(), &data, &result2);
5402 // Read the response body.
5404 ReadResult(trans, &data, &result);
5405 EXPECT_EQ("hello!", result);
5407 // Verify that we haven't received any push data.
5408 EXPECT_EQ("", result2);
5410 // Verify the SYN_REPLY.
5411 // Copy the response info, because trans goes away.
5412 HttpResponseInfo response = *trans->GetResponseInfo();
5413 ASSERT_TRUE(trans2->GetResponseInfo() == NULL);
5415 VerifyStreamsClosed(helper);
5417 // Verify the SYN_REPLY.
5418 EXPECT_TRUE(response.headers.get() != NULL);
5419 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5421 // Read the final EOF (which will close the session).
5424 // Verify that we consumed all test data.
5425 EXPECT_TRUE(data.at_read_eof());
5426 EXPECT_TRUE(data.at_write_eof());
5429 TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
5430 scoped_ptr<SpdyFrame> req(
5431 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5432 scoped_ptr<SpdyFrame> rst(
5433 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5434 MockWrite writes[] = {
5435 CreateMockWrite(*req),
5436 CreateMockWrite(*rst),
5439 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5440 (*initial_headers)[spdy_util_.GetStatusKey()] = "200 OK";
5441 (*initial_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5442 scoped_ptr<SpdyFrame> stream1_reply(
5443 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
5451 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5452 (*late_headers)["hello"] = "bye";
5453 scoped_ptr<SpdyFrame> stream1_headers(
5454 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5461 scoped_ptr<SpdyFrame> stream1_body(
5462 spdy_util_.ConstructSpdyBodyFrame(1, true));
5463 MockRead reads[] = {
5464 CreateMockRead(*stream1_reply),
5465 CreateMockRead(*stream1_headers),
5466 CreateMockRead(*stream1_body),
5467 MockRead(ASYNC, 0, 0) // EOF
5470 DelayedSocketData data(1, reads, arraysize(reads),
5471 writes, arraysize(writes));
5472 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5473 BoundNetLog(), GetParam(), NULL);
5474 helper.RunToCompletion(&data);
5475 TransactionHelperResult out = helper.output();
5476 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5479 TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
5480 scoped_ptr<SpdyFrame> req(
5481 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5482 scoped_ptr<SpdyFrame> rst(
5483 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5484 MockWrite writes[] = {
5485 CreateMockWrite(*req),
5486 CreateMockWrite(*rst),
5489 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5490 (*initial_headers)[spdy_util_.GetStatusKey()] = "200 OK";
5491 (*initial_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5492 scoped_ptr<SpdyFrame> stream1_reply(
5493 spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
5501 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5502 (*late_headers)["hello"] = "bye";
5503 scoped_ptr<SpdyFrame> stream1_headers(
5504 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5511 scoped_ptr<SpdyFrame> stream1_body(
5512 spdy_util_.ConstructSpdyBodyFrame(1, false));
5513 scoped_ptr<SpdyFrame> stream1_body2(
5514 spdy_util_.ConstructSpdyBodyFrame(1, true));
5515 MockRead reads[] = {
5516 CreateMockRead(*stream1_reply),
5517 CreateMockRead(*stream1_body),
5518 CreateMockRead(*stream1_headers),
5519 CreateMockRead(*stream1_body2),
5520 MockRead(ASYNC, 0, 0) // EOF
5523 DelayedSocketData data(1, reads, arraysize(reads),
5524 writes, arraysize(writes));
5525 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5526 BoundNetLog(), GetParam(), NULL);
5527 helper.RunToCompletion(&data);
5528 TransactionHelperResult out = helper.output();
5529 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5532 TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
5533 // In this test we want to verify that we can't accidentally push content
5534 // which can't be pushed by this content server.
5535 // This test assumes that:
5536 // - if we're requesting http://www.foo.com/barbaz
5537 // - the browser has made a connection to "www.foo.com".
5539 // A list of the URL to fetch, followed by the URL being pushed.
5540 static const char* const kTestCases[] = {
5541 "http://www.google.com/foo.html",
5542 "http://www.google.com:81/foo.js", // Bad port
5544 "http://www.google.com/foo.html",
5545 "https://www.google.com/foo.js", // Bad protocol
5547 "http://www.google.com/foo.html",
5548 "ftp://www.google.com/foo.js", // Invalid Protocol
5550 "http://www.google.com/foo.html",
5551 "http://blat.www.google.com/foo.js", // Cross subdomain
5553 "http://www.google.com/foo.html",
5554 "http://www.foo.com/foo.js", // Cross domain
5557 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
5558 const char* url_to_fetch = kTestCases[index];
5559 const char* url_to_push = kTestCases[index + 1];
5561 scoped_ptr<SpdyFrame> stream1_syn(
5562 spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
5563 scoped_ptr<SpdyFrame> stream1_body(
5564 spdy_util_.ConstructSpdyBodyFrame(1, true));
5565 scoped_ptr<SpdyFrame> push_rst(
5566 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
5567 MockWrite writes[] = {
5568 CreateMockWrite(*stream1_syn, 1),
5569 CreateMockWrite(*push_rst, 4),
5572 scoped_ptr<SpdyFrame>
5573 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5574 scoped_ptr<SpdyFrame>
5575 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
5580 const char kPushedData[] = "pushed";
5581 scoped_ptr<SpdyFrame> stream2_body(
5582 spdy_util_.ConstructSpdyBodyFrame(
5583 2, kPushedData, strlen(kPushedData), true));
5584 scoped_ptr<SpdyFrame> rst(
5585 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
5587 MockRead reads[] = {
5588 CreateMockRead(*stream1_reply, 2),
5589 CreateMockRead(*stream2_syn, 3),
5590 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5591 CreateMockRead(*stream2_body, 6),
5592 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5595 HttpResponseInfo response;
5596 OrderedSocketData data(reads, arraysize(reads),
5597 writes, arraysize(writes));
5599 HttpRequestInfo request;
5600 request.method = "GET";
5601 request.url = GURL(url_to_fetch);
5602 request.load_flags = 0;
5604 // Enable cross-origin push. Since we are not using a proxy, this should
5605 // not actually enable cross-origin SPDY push.
5606 scoped_ptr<SpdySessionDependencies> session_deps(
5607 CreateSpdySessionDependencies(GetParam()));
5608 session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
5609 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5610 BoundNetLog(), GetParam(),
5611 session_deps.release());
5612 helper.RunPreTestSetup();
5613 helper.AddData(&data);
5615 HttpNetworkTransaction* trans = helper.trans();
5617 // Start the transaction with basic parameters.
5618 TestCompletionCallback callback;
5620 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5621 EXPECT_EQ(ERR_IO_PENDING, rv);
5622 rv = callback.WaitForResult();
5624 // Read the response body.
5626 ReadResult(trans, &data, &result);
5628 // Verify that we consumed all test data.
5629 EXPECT_TRUE(data.at_read_eof());
5630 EXPECT_TRUE(data.at_write_eof());
5632 // Verify the SYN_REPLY.
5633 // Copy the response info, because trans goes away.
5634 response = *trans->GetResponseInfo();
5636 VerifyStreamsClosed(helper);
5638 // Verify the SYN_REPLY.
5639 EXPECT_TRUE(response.headers.get() != NULL);
5640 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5644 TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
5645 // Construct the request.
5646 scoped_ptr<SpdyFrame> req(
5647 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5648 scoped_ptr<SpdyFrame> req2(
5649 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
5650 MockWrite writes[] = {
5651 CreateMockWrite(*req, 1),
5652 CreateMockWrite(*req2, 3),
5655 scoped_ptr<SpdyFrame> refused(
5656 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
5657 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5658 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true));
5659 MockRead reads[] = {
5660 CreateMockRead(*refused, 2),
5661 CreateMockRead(*resp, 4),
5662 CreateMockRead(*body, 5),
5663 MockRead(ASYNC, 0, 6) // EOF
5666 OrderedSocketData data(reads, arraysize(reads),
5667 writes, arraysize(writes));
5668 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5669 BoundNetLog(), GetParam(), NULL);
5671 helper.RunPreTestSetup();
5672 helper.AddData(&data);
5674 HttpNetworkTransaction* trans = helper.trans();
5676 // Start the transaction with basic parameters.
5677 TestCompletionCallback callback;
5678 int rv = trans->Start(
5679 &CreateGetRequest(), callback.callback(), BoundNetLog());
5680 EXPECT_EQ(ERR_IO_PENDING, rv);
5681 rv = callback.WaitForResult();
5684 // Verify that we consumed all test data.
5685 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
5686 << data.read_count()
5688 << data.read_index();
5689 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
5690 << data.write_count()
5692 << data.write_index();
5694 // Verify the SYN_REPLY.
5695 HttpResponseInfo response = *trans->GetResponseInfo();
5696 EXPECT_TRUE(response.headers.get() != NULL);
5697 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5700 TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) {
5701 // This first request will start to establish the SpdySession.
5702 // Then we will start the second (MEDIUM priority) and then third
5703 // (HIGHEST priority) request in such a way that the third will actually
5704 // start before the second, causing the second to be numbered differently
5705 // than the order they were created.
5706 scoped_ptr<SpdyFrame> req1(
5707 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5708 scoped_ptr<SpdyFrame> req2(
5709 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true));
5710 scoped_ptr<SpdyFrame> req3(
5711 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true));
5712 MockWrite writes[] = {
5713 CreateMockWrite(*req1, 0),
5714 CreateMockWrite(*req2, 3),
5715 CreateMockWrite(*req3, 4),
5718 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5719 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
5720 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5721 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
5722 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
5723 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
5724 MockRead reads[] = {
5725 CreateMockRead(*resp1, 1),
5726 CreateMockRead(*body1, 2),
5727 CreateMockRead(*resp2, 5),
5728 CreateMockRead(*body2, 6),
5729 CreateMockRead(*resp3, 7),
5730 CreateMockRead(*body3, 8),
5731 MockRead(ASYNC, 0, 9) // EOF
5734 DeterministicSocketData data(reads, arraysize(reads),
5735 writes, arraysize(writes));
5736 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
5737 BoundNetLog(), GetParam(), NULL);
5738 helper.SetDeterministic();
5739 helper.RunPreTestSetup();
5740 helper.AddDeterministicData(&data);
5742 // Start the first transaction to set up the SpdySession
5743 HttpNetworkTransaction* trans = helper.trans();
5744 TestCompletionCallback callback;
5745 HttpRequestInfo info1 = CreateGetRequest();
5746 int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
5747 EXPECT_EQ(ERR_IO_PENDING, rv);
5749 // Run the message loop, but do not allow the write to complete.
5750 // This leaves the SpdySession with a write pending, which prevents
5751 // SpdySession from attempting subsequent writes until this write completes.
5752 base::RunLoop().RunUntilIdle();
5754 // Now, start both new transactions
5755 HttpRequestInfo info2 = CreateGetRequest();
5756 TestCompletionCallback callback2;
5757 scoped_ptr<HttpNetworkTransaction> trans2(
5758 new HttpNetworkTransaction(MEDIUM, helper.session().get()));
5759 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog());
5760 EXPECT_EQ(ERR_IO_PENDING, rv);
5761 base::RunLoop().RunUntilIdle();
5763 HttpRequestInfo info3 = CreateGetRequest();
5764 TestCompletionCallback callback3;
5765 scoped_ptr<HttpNetworkTransaction> trans3(
5766 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
5767 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog());
5768 EXPECT_EQ(ERR_IO_PENDING, rv);
5769 base::RunLoop().RunUntilIdle();
5771 // We now have two SYN_STREAM frames queued up which will be
5772 // dequeued only once the first write completes, which we
5773 // now allow to happen.
5775 EXPECT_EQ(OK, callback.WaitForResult());
5777 // And now we can allow everything else to run to completion.
5780 EXPECT_EQ(OK, callback2.WaitForResult());
5781 EXPECT_EQ(OK, callback3.WaitForResult());
5783 helper.VerifyDataConsumed();
5786 // The tests below are only for SPDY/3 and above.
5788 // Test that sent data frames and received WINDOW_UPDATE frames change
5789 // the send_window_size_ correctly.
5791 // WINDOW_UPDATE is different than most other frames in that it can arrive
5792 // while the client is still sending the request body. In order to enforce
5793 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
5794 // socket data provider, so that initial read that is done as soon as the
5795 // stream is created, succeeds and schedules another read. This way reads
5796 // and writes are interleaved; after doing a full frame write, SpdyStream
5797 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
5798 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5799 // since request has not been completely written, therefore we feed
5800 // enough number of WINDOW_UPDATEs to finish the first read and cause a
5801 // write, leading to a complete write of request body; after that we send
5802 // a reply with a body, to cause a graceful shutdown.
5804 // TODO(agayev): develop a socket data provider where both, reads and
5805 // writes are ordered so that writing tests like these are easy and rewrite
5806 // all these tests using it. Right now we are working around the
5807 // limitations as described above and it's not deterministic, tests may
5808 // fail under specific circumstances.
5809 TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
5810 if (GetParam().protocol < kProtoSPDY3)
5813 static int kFrameCount = 2;
5814 scoped_ptr<std::string> content(
5815 new std::string(kMaxSpdyFrameChunkSize, 'a'));
5816 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
5817 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
5818 scoped_ptr<SpdyFrame> body(
5819 spdy_util_.ConstructSpdyBodyFrame(
5820 1, content->c_str(), content->size(), false));
5821 scoped_ptr<SpdyFrame> body_end(
5822 spdy_util_.ConstructSpdyBodyFrame(
5823 1, content->c_str(), content->size(), true));
5825 MockWrite writes[] = {
5826 CreateMockWrite(*req, 0),
5827 CreateMockWrite(*body, 1),
5828 CreateMockWrite(*body_end, 2),
5831 static const int32 kDeltaWindowSize = 0xff;
5832 static const int kDeltaCount = 4;
5833 scoped_ptr<SpdyFrame> window_update(
5834 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5835 scoped_ptr<SpdyFrame> window_update_dummy(
5836 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
5837 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
5838 MockRead reads[] = {
5839 CreateMockRead(*window_update_dummy, 3),
5840 CreateMockRead(*window_update_dummy, 4),
5841 CreateMockRead(*window_update_dummy, 5),
5842 CreateMockRead(*window_update, 6), // Four updates, therefore window
5843 CreateMockRead(*window_update, 7), // size should increase by
5844 CreateMockRead(*window_update, 8), // kDeltaWindowSize * 4
5845 CreateMockRead(*window_update, 9),
5846 CreateMockRead(*resp, 10),
5847 CreateMockRead(*body_end, 11),
5848 MockRead(ASYNC, 0, 0, 12) // EOF
5851 DeterministicSocketData data(reads, arraysize(reads),
5852 writes, arraysize(writes));
5854 ScopedVector<UploadElementReader> element_readers;
5855 for (int i = 0; i < kFrameCount; ++i) {
5856 element_readers.push_back(
5857 new UploadBytesElementReader(content->c_str(), content->size()));
5859 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
5861 // Setup the request
5862 HttpRequestInfo request;
5863 request.method = "POST";
5864 request.url = GURL(kDefaultURL);
5865 request.upload_data_stream = &upload_data_stream;
5867 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5868 BoundNetLog(), GetParam(), NULL);
5869 helper.SetDeterministic();
5870 helper.AddDeterministicData(&data);
5871 helper.RunPreTestSetup();
5873 HttpNetworkTransaction* trans = helper.trans();
5875 TestCompletionCallback callback;
5876 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5878 EXPECT_EQ(ERR_IO_PENDING, rv);
5882 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
5883 ASSERT_TRUE(stream != NULL);
5884 ASSERT_TRUE(stream->stream() != NULL);
5885 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize) +
5886 kDeltaWindowSize * kDeltaCount -
5887 kMaxSpdyFrameChunkSize * kFrameCount,
5888 stream->stream()->send_window_size());
5892 rv = callback.WaitForResult();
5895 helper.VerifyDataConsumed();
5898 // Test that received data frames and sent WINDOW_UPDATE frames change
5899 // the recv_window_size_ correctly.
5900 TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
5901 if (GetParam().protocol < kProtoSPDY3)
5904 // Set the data in the body frame large enough to trigger sending a
5905 // WINDOW_UPDATE by the stream.
5906 const std::string body_data(kSpdyStreamInitialWindowSize / 2 + 1, 'x');
5908 scoped_ptr<SpdyFrame> req(
5909 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5910 scoped_ptr<SpdyFrame> session_window_update(
5911 spdy_util_.ConstructSpdyWindowUpdate(0, body_data.size()));
5912 scoped_ptr<SpdyFrame> window_update(
5913 spdy_util_.ConstructSpdyWindowUpdate(1, body_data.size()));
5915 std::vector<MockWrite> writes;
5916 writes.push_back(CreateMockWrite(*req));
5917 if (GetParam().protocol >= kProtoSPDY31)
5918 writes.push_back(CreateMockWrite(*session_window_update));
5919 writes.push_back(CreateMockWrite(*window_update));
5921 scoped_ptr<SpdyFrame> resp(
5922 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5923 scoped_ptr<SpdyFrame> body_no_fin(
5924 spdy_util_.ConstructSpdyBodyFrame(
5925 1, body_data.data(), body_data.size(), false));
5926 scoped_ptr<SpdyFrame> body_fin(
5927 spdy_util_.ConstructSpdyBodyFrame(1, NULL, 0, true));
5928 MockRead reads[] = {
5929 CreateMockRead(*resp),
5930 CreateMockRead(*body_no_fin),
5931 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause
5932 CreateMockRead(*body_fin),
5933 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause
5934 MockRead(ASYNC, 0, 0) // EOF
5937 DelayedSocketData data(1, reads, arraysize(reads),
5938 vector_as_array(&writes), writes.size());
5940 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5941 BoundNetLog(), GetParam(), NULL);
5942 helper.AddData(&data);
5943 helper.RunPreTestSetup();
5944 HttpNetworkTransaction* trans = helper.trans();
5946 TestCompletionCallback callback;
5947 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5949 EXPECT_EQ(ERR_IO_PENDING, rv);
5950 rv = callback.WaitForResult();
5953 SpdyHttpStream* stream =
5954 static_cast<SpdyHttpStream*>(trans->stream_.get());
5955 ASSERT_TRUE(stream != NULL);
5956 ASSERT_TRUE(stream->stream() != NULL);
5959 static_cast<int>(kSpdyStreamInitialWindowSize - body_data.size()),
5960 stream->stream()->recv_window_size());
5962 const HttpResponseInfo* response = trans->GetResponseInfo();
5963 ASSERT_TRUE(response != NULL);
5964 ASSERT_TRUE(response->headers.get() != NULL);
5965 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5966 EXPECT_TRUE(response->was_fetched_via_spdy);
5968 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
5969 // size increased to default.
5970 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(body_data.size()));
5971 rv = trans->Read(buf.get(), body_data.size(), CompletionCallback());
5972 EXPECT_EQ(static_cast<int>(body_data.size()), rv);
5973 std::string content(buf->data(), buf->data() + body_data.size());
5974 EXPECT_EQ(body_data, content);
5976 // Schedule the reading of empty data frame with FIN
5977 data.CompleteRead();
5979 // Force write of WINDOW_UPDATE which was scheduled during the above
5981 base::RunLoop().RunUntilIdle();
5984 data.CompleteRead();
5986 helper.VerifyDataConsumed();
5989 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
5990 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
5991 if (GetParam().protocol < kProtoSPDY3)
5994 // Number of full frames we hope to write (but will not, used to
5995 // set content-length header correctly)
5996 static int kFrameCount = 3;
5998 scoped_ptr<std::string> content(
5999 new std::string(kMaxSpdyFrameChunkSize, 'a'));
6000 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6001 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
6002 scoped_ptr<SpdyFrame> body(
6003 spdy_util_.ConstructSpdyBodyFrame(
6004 1, content->c_str(), content->size(), false));
6005 scoped_ptr<SpdyFrame> rst(
6006 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
6008 // We're not going to write a data frame with FIN, we'll receive a bad
6009 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6010 MockWrite writes[] = {
6011 CreateMockWrite(*req, 0),
6012 CreateMockWrite(*body, 2),
6013 CreateMockWrite(*rst, 3),
6016 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow
6017 scoped_ptr<SpdyFrame> window_update(
6018 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
6019 MockRead reads[] = {
6020 CreateMockRead(*window_update, 1),
6021 MockRead(ASYNC, 0, 4) // EOF
6024 DeterministicSocketData data(reads, arraysize(reads),
6025 writes, arraysize(writes));
6027 ScopedVector<UploadElementReader> element_readers;
6028 for (int i = 0; i < kFrameCount; ++i) {
6029 element_readers.push_back(
6030 new UploadBytesElementReader(content->c_str(), content->size()));
6032 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
6034 // Setup the request
6035 HttpRequestInfo request;
6036 request.method = "POST";
6037 request.url = GURL("http://www.google.com/");
6038 request.upload_data_stream = &upload_data_stream;
6040 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6041 BoundNetLog(), GetParam(), NULL);
6042 helper.SetDeterministic();
6043 helper.RunPreTestSetup();
6044 helper.AddDeterministicData(&data);
6045 HttpNetworkTransaction* trans = helper.trans();
6047 TestCompletionCallback callback;
6048 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6049 ASSERT_EQ(ERR_IO_PENDING, rv);
6052 ASSERT_TRUE(callback.have_result());
6053 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
6054 helper.VerifyDataConsumed();
6057 // Test that after hitting a send window size of 0, the write process
6058 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
6060 // This test constructs a POST request followed by enough data frames
6061 // containing 'a' that would make the window size 0, followed by another
6062 // data frame containing default content (which is "hello!") and this frame
6063 // also contains a FIN flag. DelayedSocketData is used to enforce all
6064 // writes go through before a read could happen. However, the last frame
6065 // ("hello!") is not supposed to go through since by the time its turn
6066 // arrives, window size is 0. At this point MessageLoop::Run() called via
6067 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
6068 // which returns after performing all possible writes. We use DCHECKS to
6069 // ensure that last data frame is still there and stream has stalled.
6070 // After that, next read is artifically enforced, which causes a
6071 // WINDOW_UPDATE to be read and I/O process resumes.
6072 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
6073 if (GetParam().protocol < kProtoSPDY3)
6076 // Number of frames we need to send to zero out the window size: data
6077 // frames plus SYN_STREAM plus the last data frame; also we need another
6078 // data frame that we will send once the WINDOW_UPDATE is received,
6080 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
6082 // Calculate last frame's size; 0 size data frame is legal.
6083 size_t last_frame_size =
6084 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6086 // Construct content for a data frame of maximum size.
6087 std::string content(kMaxSpdyFrameChunkSize, 'a');
6089 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6090 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6094 scoped_ptr<SpdyFrame> body1(
6095 spdy_util_.ConstructSpdyBodyFrame(
6096 1, content.c_str(), content.size(), false));
6098 // Last frame to zero out the window size.
6099 scoped_ptr<SpdyFrame> body2(
6100 spdy_util_.ConstructSpdyBodyFrame(
6101 1, content.c_str(), last_frame_size, false));
6103 // Data frame to be sent once WINDOW_UPDATE frame is received.
6104 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6106 // Fill in mock writes.
6107 scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
6109 writes[i] = CreateMockWrite(*req);
6110 for (i = 1; i < num_writes - 2; i++)
6111 writes[i] = CreateMockWrite(*body1);
6112 writes[i++] = CreateMockWrite(*body2);
6113 writes[i] = CreateMockWrite(*body3);
6115 // Construct read frame, give enough space to upload the rest of the
6117 scoped_ptr<SpdyFrame> session_window_update(
6118 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6119 scoped_ptr<SpdyFrame> window_update(
6120 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
6121 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6122 MockRead reads[] = {
6123 CreateMockRead(*session_window_update),
6124 CreateMockRead(*session_window_update),
6125 CreateMockRead(*window_update),
6126 CreateMockRead(*window_update),
6127 CreateMockRead(*reply),
6128 CreateMockRead(*body2),
6129 CreateMockRead(*body3),
6130 MockRead(ASYNC, 0, 0) // EOF
6133 // Skip the session window updates unless we're using SPDY/3.1 and
6135 size_t read_offset = (GetParam().protocol >= kProtoSPDY31) ? 0 : 2;
6136 size_t num_reads = arraysize(reads) - read_offset;
6138 // Force all writes to happen before any read, last write will not
6139 // actually queue a frame, due to window size being 0.
6140 DelayedSocketData data(num_writes, reads + read_offset, num_reads,
6141 writes.get(), num_writes);
6143 ScopedVector<UploadElementReader> element_readers;
6144 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6145 upload_data_string.append(kUploadData, kUploadDataSize);
6146 element_readers.push_back(new UploadBytesElementReader(
6147 upload_data_string.c_str(), upload_data_string.size()));
6148 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
6150 HttpRequestInfo request;
6151 request.method = "POST";
6152 request.url = GURL("http://www.google.com/");
6153 request.upload_data_stream = &upload_data_stream;
6154 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6155 BoundNetLog(), GetParam(), NULL);
6156 helper.AddData(&data);
6157 helper.RunPreTestSetup();
6159 HttpNetworkTransaction* trans = helper.trans();
6161 TestCompletionCallback callback;
6162 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6163 EXPECT_EQ(ERR_IO_PENDING, rv);
6165 base::RunLoop().RunUntilIdle(); // Write as much as we can.
6167 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6168 ASSERT_TRUE(stream != NULL);
6169 ASSERT_TRUE(stream->stream() != NULL);
6170 EXPECT_EQ(0, stream->stream()->send_window_size());
6171 // All the body data should have been read.
6172 // TODO(satorux): This is because of the weirdness in reading the request
6173 // body in OnSendBodyComplete(). See crbug.com/113107.
6174 EXPECT_TRUE(upload_data_stream.IsEOF());
6175 // But the body is not yet fully sent (kUploadData is not yet sent)
6176 // since we're send-stalled.
6177 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6179 data.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6180 rv = callback.WaitForResult();
6181 helper.VerifyDataConsumed();
6184 // Test we correctly handle the case where the SETTINGS frame results in
6185 // unstalling the send window.
6186 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
6187 if (GetParam().protocol < kProtoSPDY3)
6190 // Number of frames we need to send to zero out the window size: data
6191 // frames plus SYN_STREAM plus the last data frame; also we need another
6192 // data frame that we will send once the SETTING is received, therefore +3.
6193 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
6195 // Calculate last frame's size; 0 size data frame is legal.
6196 size_t last_frame_size =
6197 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6199 // Construct content for a data frame of maximum size.
6200 std::string content(kMaxSpdyFrameChunkSize, 'a');
6202 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6203 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6207 scoped_ptr<SpdyFrame> body1(
6208 spdy_util_.ConstructSpdyBodyFrame(
6209 1, content.c_str(), content.size(), false));
6211 // Last frame to zero out the window size.
6212 scoped_ptr<SpdyFrame> body2(
6213 spdy_util_.ConstructSpdyBodyFrame(
6214 1, content.c_str(), last_frame_size, false));
6216 // Data frame to be sent once SETTINGS frame is received.
6217 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6219 // Fill in mock reads/writes.
6220 std::vector<MockRead> reads;
6221 std::vector<MockWrite> writes;
6223 writes.push_back(CreateMockWrite(*req, i++));
6224 while (i < num_writes - 2)
6225 writes.push_back(CreateMockWrite(*body1, i++));
6226 writes.push_back(CreateMockWrite(*body2, i++));
6228 // Construct read frame for SETTINGS that gives enough space to upload the
6229 // rest of the data.
6230 SettingsMap settings;
6231 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6232 SettingsFlagsAndValue(
6233 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize * 2);
6234 scoped_ptr<SpdyFrame> settings_frame_large(
6235 spdy_util_.ConstructSpdySettings(settings));
6237 reads.push_back(CreateMockRead(*settings_frame_large, i++));
6239 scoped_ptr<SpdyFrame> session_window_update(
6240 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6241 if (GetParam().protocol >= kProtoSPDY31)
6242 reads.push_back(CreateMockRead(*session_window_update, i++));
6244 writes.push_back(CreateMockWrite(*body3, i++));
6246 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6247 reads.push_back(CreateMockRead(*reply, i++));
6248 reads.push_back(CreateMockRead(*body2, i++));
6249 reads.push_back(CreateMockRead(*body3, i++));
6250 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6252 // Force all writes to happen before any read, last write will not
6253 // actually queue a frame, due to window size being 0.
6254 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6255 vector_as_array(&writes), writes.size());
6257 ScopedVector<UploadElementReader> element_readers;
6258 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6259 upload_data_string.append(kUploadData, kUploadDataSize);
6260 element_readers.push_back(new UploadBytesElementReader(
6261 upload_data_string.c_str(), upload_data_string.size()));
6262 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
6264 HttpRequestInfo request;
6265 request.method = "POST";
6266 request.url = GURL("http://www.google.com/");
6267 request.upload_data_stream = &upload_data_stream;
6268 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6269 BoundNetLog(), GetParam(), NULL);
6270 helper.SetDeterministic();
6271 helper.RunPreTestSetup();
6272 helper.AddDeterministicData(&data);
6274 HttpNetworkTransaction* trans = helper.trans();
6276 TestCompletionCallback callback;
6277 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6278 EXPECT_EQ(ERR_IO_PENDING, rv);
6280 data.RunFor(num_writes - 1); // Write as much as we can.
6282 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6283 ASSERT_TRUE(stream != NULL);
6284 ASSERT_TRUE(stream->stream() != NULL);
6285 EXPECT_EQ(0, stream->stream()->send_window_size());
6287 // All the body data should have been read.
6288 // TODO(satorux): This is because of the weirdness in reading the request
6289 // body in OnSendBodyComplete(). See crbug.com/113107.
6290 EXPECT_TRUE(upload_data_stream.IsEOF());
6291 // But the body is not yet fully sent (kUploadData is not yet sent)
6292 // since we're send-stalled.
6293 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6295 data.RunFor(6); // Read in SETTINGS frame to unstall.
6296 rv = callback.WaitForResult();
6297 helper.VerifyDataConsumed();
6298 // If stream is NULL, that means it was unstalled and closed.
6299 EXPECT_TRUE(stream->stream() == NULL);
6302 // Test we correctly handle the case where the SETTINGS frame results in a
6303 // negative send window size.
6304 TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
6305 if (GetParam().protocol < kProtoSPDY3)
6308 // Number of frames we need to send to zero out the window size: data
6309 // frames plus SYN_STREAM plus the last data frame; also we need another
6310 // data frame that we will send once the SETTING is received, therefore +3.
6311 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
6313 // Calculate last frame's size; 0 size data frame is legal.
6314 size_t last_frame_size =
6315 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6317 // Construct content for a data frame of maximum size.
6318 std::string content(kMaxSpdyFrameChunkSize, 'a');
6320 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6321 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6325 scoped_ptr<SpdyFrame> body1(
6326 spdy_util_.ConstructSpdyBodyFrame(
6327 1, content.c_str(), content.size(), false));
6329 // Last frame to zero out the window size.
6330 scoped_ptr<SpdyFrame> body2(
6331 spdy_util_.ConstructSpdyBodyFrame(
6332 1, content.c_str(), last_frame_size, false));
6334 // Data frame to be sent once SETTINGS frame is received.
6335 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6337 // Fill in mock reads/writes.
6338 std::vector<MockRead> reads;
6339 std::vector<MockWrite> writes;
6341 writes.push_back(CreateMockWrite(*req, i++));
6342 while (i < num_writes - 2)
6343 writes.push_back(CreateMockWrite(*body1, i++));
6344 writes.push_back(CreateMockWrite(*body2, i++));
6346 // Construct read frame for SETTINGS that makes the send_window_size
6348 SettingsMap new_settings;
6349 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6350 SettingsFlagsAndValue(
6351 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize / 2);
6352 scoped_ptr<SpdyFrame> settings_frame_small(
6353 spdy_util_.ConstructSpdySettings(new_settings));
6354 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6356 scoped_ptr<SpdyFrame> session_window_update_init_size(
6357 spdy_util_.ConstructSpdyWindowUpdate(0, kSpdyStreamInitialWindowSize));
6358 scoped_ptr<SpdyFrame> window_update_init_size(
6359 spdy_util_.ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize));
6361 reads.push_back(CreateMockRead(*settings_frame_small, i++));
6363 if (GetParam().protocol >= kProtoSPDY3)
6364 reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
6366 reads.push_back(CreateMockRead(*window_update_init_size, i++));
6368 writes.push_back(CreateMockWrite(*body3, i++));
6370 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6371 reads.push_back(CreateMockRead(*reply, i++));
6372 reads.push_back(CreateMockRead(*body2, i++));
6373 reads.push_back(CreateMockRead(*body3, i++));
6374 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6376 // Force all writes to happen before any read, last write will not
6377 // actually queue a frame, due to window size being 0.
6378 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6379 vector_as_array(&writes), writes.size());
6381 ScopedVector<UploadElementReader> element_readers;
6382 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6383 upload_data_string.append(kUploadData, kUploadDataSize);
6384 element_readers.push_back(new UploadBytesElementReader(
6385 upload_data_string.c_str(), upload_data_string.size()));
6386 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
6388 HttpRequestInfo request;
6389 request.method = "POST";
6390 request.url = GURL("http://www.google.com/");
6391 request.upload_data_stream = &upload_data_stream;
6392 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6393 BoundNetLog(), GetParam(), NULL);
6394 helper.SetDeterministic();
6395 helper.RunPreTestSetup();
6396 helper.AddDeterministicData(&data);
6398 HttpNetworkTransaction* trans = helper.trans();
6400 TestCompletionCallback callback;
6401 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6402 EXPECT_EQ(ERR_IO_PENDING, rv);
6404 data.RunFor(num_writes - 1); // Write as much as we can.
6406 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6407 ASSERT_TRUE(stream != NULL);
6408 ASSERT_TRUE(stream->stream() != NULL);
6409 EXPECT_EQ(0, stream->stream()->send_window_size());
6411 // All the body data should have been read.
6412 // TODO(satorux): This is because of the weirdness in reading the request
6413 // body in OnSendBodyComplete(). See crbug.com/113107.
6414 EXPECT_TRUE(upload_data_stream.IsEOF());
6415 // But the body is not yet fully sent (kUploadData is not yet sent)
6416 // since we're send-stalled.
6417 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6419 // Read in WINDOW_UPDATE or SETTINGS frame.
6420 data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 8 : 7);
6421 rv = callback.WaitForResult();
6422 helper.VerifyDataConsumed();