Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / net / spdy / spdy_network_transaction_unittest.cc
blob3836fd31849e7454fa85e4260c3aa04d23b054aa
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <string>
6 #include <vector>
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
10 #include "base/files/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 "base/strings/string_piece.h"
16 #include "base/test/test_file_util.h"
17 #include "net/base/auth.h"
18 #include "net/base/chunked_upload_data_stream.h"
19 #include "net/base/elements_upload_data_stream.h"
20 #include "net/base/net_log_unittest.h"
21 #include "net/base/request_priority.h"
22 #include "net/base/upload_bytes_element_reader.h"
23 #include "net/base/upload_file_element_reader.h"
24 #include "net/http/http_network_session_peer.h"
25 #include "net/http/http_network_transaction.h"
26 #include "net/http/http_server_properties.h"
27 #include "net/http/http_transaction_test_util.h"
28 #include "net/socket/client_socket_pool_base.h"
29 #include "net/socket/next_proto.h"
30 #include "net/spdy/buffered_spdy_framer.h"
31 #include "net/spdy/spdy_http_stream.h"
32 #include "net/spdy/spdy_http_utils.h"
33 #include "net/spdy/spdy_session.h"
34 #include "net/spdy/spdy_session_pool.h"
35 #include "net/spdy/spdy_test_util_common.h"
36 #include "net/spdy/spdy_test_utils.h"
37 #include "net/ssl/ssl_connection_status_flags.h"
38 #include "net/url_request/url_request_test_util.h"
39 #include "testing/gmock/include/gmock/gmock.h"
40 #include "testing/platform_test.h"
42 //-----------------------------------------------------------------------------
44 namespace net {
46 namespace {
48 using testing::Each;
49 using testing::Eq;
51 const char kRequestUrl[] = "http://www.google.com/";
53 enum SpdyNetworkTransactionTestSSLType {
54 SPDYNPN,
55 SPDYNOSSL,
56 SPDYSSL,
59 struct SpdyNetworkTransactionTestParams {
60 SpdyNetworkTransactionTestParams()
61 : protocol(kProtoSPDY31),
62 ssl_type(SPDYNPN) {}
64 SpdyNetworkTransactionTestParams(
65 NextProto protocol,
66 SpdyNetworkTransactionTestSSLType ssl_type)
67 : protocol(protocol),
68 ssl_type(ssl_type) {}
70 NextProto protocol;
71 SpdyNetworkTransactionTestSSLType ssl_type;
74 void UpdateSpdySessionDependencies(
75 SpdyNetworkTransactionTestParams test_params,
76 SpdySessionDependencies* session_deps) {
77 switch (test_params.ssl_type) {
78 case SPDYNPN:
79 session_deps->http_server_properties.SetAlternateProtocol(
80 HostPortPair("www.google.com", 80), 443,
81 AlternateProtocolFromNextProto(test_params.protocol), 1);
82 session_deps->use_alternate_protocols = true;
83 session_deps->next_protos = SpdyNextProtos();
84 break;
85 case SPDYNOSSL:
86 session_deps->force_spdy_over_ssl = false;
87 session_deps->force_spdy_always = true;
88 break;
89 case SPDYSSL:
90 session_deps->force_spdy_over_ssl = true;
91 session_deps->force_spdy_always = true;
92 break;
93 default:
94 NOTREACHED();
98 SpdySessionDependencies* CreateSpdySessionDependencies(
99 SpdyNetworkTransactionTestParams test_params) {
100 SpdySessionDependencies* session_deps =
101 new SpdySessionDependencies(test_params.protocol);
102 UpdateSpdySessionDependencies(test_params, session_deps);
103 return session_deps;
106 SpdySessionDependencies* CreateSpdySessionDependencies(
107 SpdyNetworkTransactionTestParams test_params,
108 ProxyService* proxy_service) {
109 SpdySessionDependencies* session_deps =
110 new SpdySessionDependencies(test_params.protocol, proxy_service);
111 UpdateSpdySessionDependencies(test_params, session_deps);
112 return session_deps;
115 } // namespace
117 class SpdyNetworkTransactionTest
118 : public ::testing::TestWithParam<SpdyNetworkTransactionTestParams> {
119 protected:
120 SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol) {
123 virtual ~SpdyNetworkTransactionTest() {
124 // UploadDataStream may post a deletion tasks back to the message loop on
125 // destruction.
126 upload_data_stream_.reset();
127 base::RunLoop().RunUntilIdle();
130 void SetUp() override {
131 google_get_request_initialized_ = false;
132 google_post_request_initialized_ = false;
133 google_chunked_post_request_initialized_ = false;
134 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
137 struct TransactionHelperResult {
138 int rv;
139 std::string status_line;
140 std::string response_data;
141 HttpResponseInfo response_info;
144 // A helper class that handles all the initial npn/ssl setup.
145 class NormalSpdyTransactionHelper {
146 public:
147 NormalSpdyTransactionHelper(const HttpRequestInfo& request,
148 RequestPriority priority,
149 const BoundNetLog& log,
150 SpdyNetworkTransactionTestParams test_params,
151 SpdySessionDependencies* session_deps)
152 : request_(request),
153 priority_(priority),
154 session_deps_(session_deps == NULL ?
155 CreateSpdySessionDependencies(test_params) :
156 session_deps),
157 session_(SpdySessionDependencies::SpdyCreateSession(
158 session_deps_.get())),
159 log_(log),
160 test_params_(test_params),
161 deterministic_(false),
162 spdy_enabled_(true) {
163 switch (test_params_.ssl_type) {
164 case SPDYNOSSL:
165 case SPDYSSL:
166 port_ = 80;
167 break;
168 case SPDYNPN:
169 port_ = 443;
170 break;
171 default:
172 NOTREACHED();
176 ~NormalSpdyTransactionHelper() {
177 // Any test which doesn't close the socket by sending it an EOF will
178 // have a valid session left open, which leaks the entire session pool.
179 // This is just fine - in fact, some of our tests intentionally do this
180 // so that we can check consistency of the SpdySessionPool as the test
181 // finishes. If we had put an EOF on the socket, the SpdySession would
182 // have closed and we wouldn't be able to check the consistency.
184 // Forcefully close existing sessions here.
185 session()->spdy_session_pool()->CloseAllSessions();
188 void SetDeterministic() {
189 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
190 session_deps_.get());
191 deterministic_ = true;
194 void SetSpdyDisabled() {
195 spdy_enabled_ = false;
196 port_ = 80;
199 void RunPreTestSetup() {
200 if (!session_deps_.get())
201 session_deps_.reset(CreateSpdySessionDependencies(test_params_));
202 if (!session_.get()) {
203 session_ = SpdySessionDependencies::SpdyCreateSession(
204 session_deps_.get());
207 // We're now ready to use SSL-npn SPDY.
208 trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
211 // Start the transaction, read some data, finish.
212 void RunDefaultTest() {
213 if (!StartDefaultTest())
214 return;
215 FinishDefaultTest();
218 bool StartDefaultTest() {
219 output_.rv = trans_->Start(&request_, callback_.callback(), log_);
221 // We expect an IO Pending or some sort of error.
222 EXPECT_LT(output_.rv, 0);
223 return output_.rv == ERR_IO_PENDING;
226 void FinishDefaultTest() {
227 output_.rv = callback_.WaitForResult();
228 if (output_.rv != OK) {
229 session_->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED);
230 return;
233 // Verify responses.
234 const HttpResponseInfo* response = trans_->GetResponseInfo();
235 ASSERT_TRUE(response != NULL);
236 ASSERT_TRUE(response->headers.get() != NULL);
237 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
238 EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
239 if (HttpStreamFactory::spdy_enabled()) {
240 EXPECT_EQ(
241 HttpResponseInfo::ConnectionInfoFromNextProto(
242 test_params_.protocol),
243 response->connection_info);
244 } else {
245 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
246 response->connection_info);
248 if (test_params_.ssl_type == SPDYNPN && spdy_enabled_) {
249 EXPECT_TRUE(response->was_npn_negotiated);
250 } else {
251 EXPECT_TRUE(!response->was_npn_negotiated);
253 // If SPDY is not enabled, a HTTP request should not be diverted
254 // over a SSL session.
255 if (!spdy_enabled_) {
256 EXPECT_EQ(request_.url.SchemeIs("https"),
257 response->was_npn_negotiated);
259 EXPECT_EQ("127.0.0.1", response->socket_address.host());
260 EXPECT_EQ(port_, response->socket_address.port());
261 output_.status_line = response->headers->GetStatusLine();
262 output_.response_info = *response; // Make a copy so we can verify.
263 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
266 // Most tests will want to call this function. In particular, the MockReads
267 // should end with an empty read, and that read needs to be processed to
268 // ensure proper deletion of the spdy_session_pool.
269 void VerifyDataConsumed() {
270 for (DataVector::iterator it = data_vector_.begin();
271 it != data_vector_.end(); ++it) {
272 EXPECT_TRUE((*it)->at_read_eof()) << "Read count: "
273 << (*it)->read_count()
274 << " Read index: "
275 << (*it)->read_index();
276 EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
277 << (*it)->write_count()
278 << " Write index: "
279 << (*it)->write_index();
283 // Occasionally a test will expect to error out before certain reads are
284 // processed. In that case we want to explicitly ensure that the reads were
285 // not processed.
286 void VerifyDataNotConsumed() {
287 for (DataVector::iterator it = data_vector_.begin();
288 it != data_vector_.end(); ++it) {
289 EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: "
290 << (*it)->read_count()
291 << " Read index: "
292 << (*it)->read_index();
293 EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
294 << (*it)->write_count()
295 << " Write index: "
296 << (*it)->write_index();
300 void RunToCompletion(StaticSocketDataProvider* data) {
301 RunPreTestSetup();
302 AddData(data);
303 RunDefaultTest();
304 VerifyDataConsumed();
307 void RunToCompletionWithSSLData(
308 StaticSocketDataProvider* data,
309 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
310 RunPreTestSetup();
311 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
312 RunDefaultTest();
313 VerifyDataConsumed();
316 void AddData(StaticSocketDataProvider* data) {
317 scoped_ptr<SSLSocketDataProvider> ssl_provider(
318 new SSLSocketDataProvider(ASYNC, OK));
319 AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
322 void AddDataWithSSLSocketDataProvider(
323 StaticSocketDataProvider* data,
324 scoped_ptr<SSLSocketDataProvider> ssl_provider) {
325 DCHECK(!deterministic_);
326 data_vector_.push_back(data);
327 if (test_params_.ssl_type == SPDYNPN)
328 ssl_provider->SetNextProto(test_params_.protocol);
330 if (test_params_.ssl_type == SPDYNPN ||
331 test_params_.ssl_type == SPDYSSL) {
332 session_deps_->socket_factory->AddSSLSocketDataProvider(
333 ssl_provider.get());
335 ssl_vector_.push_back(ssl_provider.release());
337 session_deps_->socket_factory->AddSocketDataProvider(data);
338 if (test_params_.ssl_type == SPDYNPN) {
339 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
340 StaticSocketDataProvider* hanging_non_alternate_protocol_socket =
341 new StaticSocketDataProvider(NULL, 0, NULL, 0);
342 hanging_non_alternate_protocol_socket->set_connect_data(
343 never_finishing_connect);
344 session_deps_->socket_factory->AddSocketDataProvider(
345 hanging_non_alternate_protocol_socket);
346 alternate_vector_.push_back(hanging_non_alternate_protocol_socket);
350 void AddDeterministicData(DeterministicSocketData* data) {
351 DCHECK(deterministic_);
352 data_vector_.push_back(data);
353 SSLSocketDataProvider* ssl_provider =
354 new SSLSocketDataProvider(ASYNC, OK);
355 if (test_params_.ssl_type == SPDYNPN)
356 ssl_provider->SetNextProto(test_params_.protocol);
358 ssl_vector_.push_back(ssl_provider);
359 if (test_params_.ssl_type == SPDYNPN ||
360 test_params_.ssl_type == SPDYSSL) {
361 session_deps_->deterministic_socket_factory->
362 AddSSLSocketDataProvider(ssl_provider);
364 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
365 if (test_params_.ssl_type == SPDYNPN) {
366 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
367 DeterministicSocketData* hanging_non_alternate_protocol_socket =
368 new DeterministicSocketData(NULL, 0, NULL, 0);
369 hanging_non_alternate_protocol_socket->set_connect_data(
370 never_finishing_connect);
371 session_deps_->deterministic_socket_factory->AddSocketDataProvider(
372 hanging_non_alternate_protocol_socket);
373 alternate_deterministic_vector_.push_back(
374 hanging_non_alternate_protocol_socket);
378 void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
379 session_ = session;
381 HttpNetworkTransaction* trans() { return trans_.get(); }
382 void ResetTrans() { trans_.reset(); }
383 TransactionHelperResult& output() { return output_; }
384 const HttpRequestInfo& request() const { return request_; }
385 const scoped_refptr<HttpNetworkSession>& session() const {
386 return session_;
388 scoped_ptr<SpdySessionDependencies>& session_deps() {
389 return session_deps_;
391 int port() const { return port_; }
392 SpdyNetworkTransactionTestParams test_params() const {
393 return test_params_;
396 private:
397 typedef std::vector<StaticSocketDataProvider*> DataVector;
398 typedef ScopedVector<SSLSocketDataProvider> SSLVector;
399 typedef ScopedVector<StaticSocketDataProvider> AlternateVector;
400 typedef ScopedVector<DeterministicSocketData> AlternateDeterministicVector;
401 HttpRequestInfo request_;
402 RequestPriority priority_;
403 scoped_ptr<SpdySessionDependencies> session_deps_;
404 scoped_refptr<HttpNetworkSession> session_;
405 TransactionHelperResult output_;
406 scoped_ptr<StaticSocketDataProvider> first_transaction_;
407 SSLVector ssl_vector_;
408 TestCompletionCallback callback_;
409 scoped_ptr<HttpNetworkTransaction> trans_;
410 scoped_ptr<HttpNetworkTransaction> trans_http_;
411 DataVector data_vector_;
412 AlternateVector alternate_vector_;
413 AlternateDeterministicVector alternate_deterministic_vector_;
414 const BoundNetLog& log_;
415 SpdyNetworkTransactionTestParams test_params_;
416 int port_;
417 bool deterministic_;
418 bool spdy_enabled_;
421 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
422 int expected_status);
424 void ConnectStatusHelper(const MockRead& status);
426 const HttpRequestInfo& CreateGetPushRequest() {
427 google_get_push_request_.method = "GET";
428 google_get_push_request_.url = GURL("http://www.google.com/foo.dat");
429 google_get_push_request_.load_flags = 0;
430 return google_get_push_request_;
433 const HttpRequestInfo& CreateGetRequest() {
434 if (!google_get_request_initialized_) {
435 google_get_request_.method = "GET";
436 google_get_request_.url = GURL(kDefaultURL);
437 google_get_request_.load_flags = 0;
438 google_get_request_initialized_ = true;
440 return google_get_request_;
443 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
444 if (!google_get_request_initialized_) {
445 google_get_request_.method = "GET";
446 google_get_request_.url = GURL(kDefaultURL);
447 google_get_request_.load_flags = 0;
448 google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
449 google_get_request_initialized_ = true;
451 return google_get_request_;
454 const HttpRequestInfo& CreatePostRequest() {
455 if (!google_post_request_initialized_) {
456 ScopedVector<UploadElementReader> element_readers;
457 element_readers.push_back(
458 new UploadBytesElementReader(kUploadData, kUploadDataSize));
459 upload_data_stream_.reset(
460 new ElementsUploadDataStream(element_readers.Pass(), 0));
462 google_post_request_.method = "POST";
463 google_post_request_.url = GURL(kDefaultURL);
464 google_post_request_.upload_data_stream = upload_data_stream_.get();
465 google_post_request_initialized_ = true;
467 return google_post_request_;
470 const HttpRequestInfo& CreateFilePostRequest() {
471 if (!google_post_request_initialized_) {
472 base::FilePath file_path;
473 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
474 CHECK_EQ(static_cast<int>(kUploadDataSize),
475 base::WriteFile(file_path, kUploadData, kUploadDataSize));
477 ScopedVector<UploadElementReader> element_readers;
478 element_readers.push_back(
479 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
480 file_path,
482 kUploadDataSize,
483 base::Time()));
484 upload_data_stream_.reset(
485 new ElementsUploadDataStream(element_readers.Pass(), 0));
487 google_post_request_.method = "POST";
488 google_post_request_.url = GURL(kDefaultURL);
489 google_post_request_.upload_data_stream = upload_data_stream_.get();
490 google_post_request_initialized_ = true;
492 return google_post_request_;
495 const HttpRequestInfo& CreateUnreadableFilePostRequest() {
496 if (google_post_request_initialized_)
497 return google_post_request_;
499 base::FilePath file_path;
500 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
501 CHECK_EQ(static_cast<int>(kUploadDataSize),
502 base::WriteFile(file_path, kUploadData, kUploadDataSize));
503 CHECK(base::MakeFileUnreadable(file_path));
505 ScopedVector<UploadElementReader> element_readers;
506 element_readers.push_back(
507 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
508 file_path,
510 kUploadDataSize,
511 base::Time()));
512 upload_data_stream_.reset(
513 new ElementsUploadDataStream(element_readers.Pass(), 0));
515 google_post_request_.method = "POST";
516 google_post_request_.url = GURL(kDefaultURL);
517 google_post_request_.upload_data_stream = upload_data_stream_.get();
518 google_post_request_initialized_ = true;
519 return google_post_request_;
522 const HttpRequestInfo& CreateComplexPostRequest() {
523 if (!google_post_request_initialized_) {
524 const int kFileRangeOffset = 1;
525 const int kFileRangeLength = 3;
526 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
528 base::FilePath file_path;
529 CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
530 CHECK_EQ(static_cast<int>(kUploadDataSize),
531 base::WriteFile(file_path, kUploadData, kUploadDataSize));
533 ScopedVector<UploadElementReader> element_readers;
534 element_readers.push_back(
535 new UploadBytesElementReader(kUploadData, kFileRangeOffset));
536 element_readers.push_back(
537 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
538 file_path,
539 kFileRangeOffset,
540 kFileRangeLength,
541 base::Time()));
542 element_readers.push_back(new UploadBytesElementReader(
543 kUploadData + kFileRangeOffset + kFileRangeLength,
544 kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
545 upload_data_stream_.reset(
546 new ElementsUploadDataStream(element_readers.Pass(), 0));
548 google_post_request_.method = "POST";
549 google_post_request_.url = GURL(kDefaultURL);
550 google_post_request_.upload_data_stream = upload_data_stream_.get();
551 google_post_request_initialized_ = true;
553 return google_post_request_;
556 const HttpRequestInfo& CreateChunkedPostRequest() {
557 if (!google_chunked_post_request_initialized_) {
558 upload_chunked_data_stream_.reset(new ChunkedUploadDataStream(0));
559 google_chunked_post_request_.method = "POST";
560 google_chunked_post_request_.url = GURL(kDefaultURL);
561 google_chunked_post_request_.upload_data_stream =
562 upload_chunked_data_stream_.get();
563 google_chunked_post_request_initialized_ = true;
565 return google_chunked_post_request_;
568 // Read the result of a particular transaction, knowing that we've got
569 // multiple transactions in the read pipeline; so as we read, we may have
570 // to skip over data destined for other transactions while we consume
571 // the data for |trans|.
572 int ReadResult(HttpNetworkTransaction* trans,
573 StaticSocketDataProvider* data,
574 std::string* result) {
575 const int kSize = 3000;
577 int bytes_read = 0;
578 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
579 TestCompletionCallback callback;
580 while (true) {
581 int rv = trans->Read(buf.get(), kSize, callback.callback());
582 if (rv == ERR_IO_PENDING) {
583 // Multiple transactions may be in the data set. Keep pulling off
584 // reads until we complete our callback.
585 while (!callback.have_result()) {
586 data->CompleteRead();
587 base::RunLoop().RunUntilIdle();
589 rv = callback.WaitForResult();
590 } else if (rv <= 0) {
591 break;
593 result->append(buf->data(), rv);
594 bytes_read += rv;
596 return bytes_read;
599 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
600 // This lengthy block is reaching into the pool to dig out the active
601 // session. Once we have the session, we verify that the streams are
602 // all closed and not leaked at this point.
603 const GURL& url = helper.request().url;
604 int port = helper.test_params().ssl_type == SPDYNPN ? 443 : 80;
605 HostPortPair host_port_pair(url.host(), port);
606 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
607 PRIVACY_MODE_DISABLED);
608 BoundNetLog log;
609 const scoped_refptr<HttpNetworkSession>& session = helper.session();
610 base::WeakPtr<SpdySession> spdy_session =
611 session->spdy_session_pool()->FindAvailableSession(key, log);
612 ASSERT_TRUE(spdy_session != NULL);
613 EXPECT_EQ(0u, spdy_session->num_active_streams());
614 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
617 void RunServerPushTest(OrderedSocketData* data,
618 HttpResponseInfo* response,
619 HttpResponseInfo* push_response,
620 const std::string& expected) {
621 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
622 BoundNetLog(), GetParam(), NULL);
623 helper.RunPreTestSetup();
624 helper.AddData(data);
626 HttpNetworkTransaction* trans = helper.trans();
628 // Start the transaction with basic parameters.
629 TestCompletionCallback callback;
630 int rv = trans->Start(
631 &CreateGetRequest(), callback.callback(), BoundNetLog());
632 EXPECT_EQ(ERR_IO_PENDING, rv);
633 rv = callback.WaitForResult();
635 // Request the pushed path.
636 scoped_ptr<HttpNetworkTransaction> trans2(
637 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
638 rv = trans2->Start(
639 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
640 EXPECT_EQ(ERR_IO_PENDING, rv);
641 base::RunLoop().RunUntilIdle();
643 // The data for the pushed path may be coming in more than 1 frame. Compile
644 // the results into a single string.
646 // Read the server push body.
647 std::string result2;
648 ReadResult(trans2.get(), data, &result2);
649 // Read the response body.
650 std::string result;
651 ReadResult(trans, data, &result);
653 // Verify that we consumed all test data.
654 EXPECT_TRUE(data->at_read_eof());
655 EXPECT_TRUE(data->at_write_eof());
657 // Verify that the received push data is same as the expected push data.
658 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
659 << result2
660 << "||||| Expected data: "
661 << expected;
663 // Verify the SYN_REPLY.
664 // Copy the response info, because trans goes away.
665 *response = *trans->GetResponseInfo();
666 *push_response = *trans2->GetResponseInfo();
668 VerifyStreamsClosed(helper);
671 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
672 int result) {
673 helper->ResetTrans();
676 static void StartTransactionCallback(
677 const scoped_refptr<HttpNetworkSession>& session,
678 int result) {
679 scoped_ptr<HttpNetworkTransaction> trans(
680 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
681 TestCompletionCallback callback;
682 HttpRequestInfo request;
683 request.method = "GET";
684 request.url = GURL("http://www.google.com/");
685 request.load_flags = 0;
686 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
687 EXPECT_EQ(ERR_IO_PENDING, rv);
688 callback.WaitForResult();
691 ChunkedUploadDataStream* upload_chunked_data_stream() const {
692 return upload_chunked_data_stream_.get();
695 SpdyTestUtil spdy_util_;
697 private:
698 scoped_ptr<ChunkedUploadDataStream> upload_chunked_data_stream_;
699 scoped_ptr<UploadDataStream> upload_data_stream_;
700 bool google_get_request_initialized_;
701 bool google_post_request_initialized_;
702 bool google_chunked_post_request_initialized_;
703 HttpRequestInfo google_get_request_;
704 HttpRequestInfo google_post_request_;
705 HttpRequestInfo google_chunked_post_request_;
706 HttpRequestInfo google_get_push_request_;
707 base::ScopedTempDir temp_dir_;
710 //-----------------------------------------------------------------------------
711 // All tests are run with three different connection types: SPDY after NPN
712 // negotiation, SPDY without SSL, and SPDY with SSL.
714 // TODO(akalin): Use ::testing::Combine() when we are able to use
715 // <tr1/tuple>.
716 INSTANTIATE_TEST_CASE_P(
717 Spdy,
718 SpdyNetworkTransactionTest,
719 ::testing::Values(
720 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNOSSL),
721 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYSSL),
722 SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN),
723 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, SPDYNOSSL),
724 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, SPDYSSL),
725 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, SPDYNPN),
726 SpdyNetworkTransactionTestParams(kProtoSPDY4_15, SPDYNOSSL),
727 SpdyNetworkTransactionTestParams(kProtoSPDY4_15, SPDYSSL),
728 SpdyNetworkTransactionTestParams(kProtoSPDY4_15, SPDYNPN)));
730 // Verify HttpNetworkTransaction constructor.
731 TEST_P(SpdyNetworkTransactionTest, Constructor) {
732 scoped_ptr<SpdySessionDependencies> session_deps(
733 CreateSpdySessionDependencies(GetParam()));
734 scoped_refptr<HttpNetworkSession> session(
735 SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
736 scoped_ptr<HttpTransaction> trans(
737 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
740 TEST_P(SpdyNetworkTransactionTest, Get) {
741 // Construct the request.
742 scoped_ptr<SpdyFrame> req(
743 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
744 MockWrite writes[] = { CreateMockWrite(*req) };
746 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
747 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
748 MockRead reads[] = {
749 CreateMockRead(*resp),
750 CreateMockRead(*body),
751 MockRead(ASYNC, 0, 0) // EOF
754 DelayedSocketData data(1, reads, arraysize(reads),
755 writes, arraysize(writes));
756 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
757 BoundNetLog(), GetParam(), NULL);
758 helper.RunToCompletion(&data);
759 TransactionHelperResult out = helper.output();
760 EXPECT_EQ(OK, out.rv);
761 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
762 EXPECT_EQ("hello!", out.response_data);
765 TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
766 for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
767 p = RequestPriority(p + 1)) {
768 // Construct the request.
769 scoped_ptr<SpdyFrame> req(
770 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true));
771 MockWrite writes[] = { CreateMockWrite(*req) };
773 SpdyPriority spdy_prio = 0;
774 EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio));
775 // this repeats the RequestPriority-->SpdyPriority mapping from
776 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
777 // sure it's being done right.
778 if (spdy_util_.spdy_version() < SPDY3) {
779 switch (p) {
780 case HIGHEST:
781 EXPECT_EQ(0, spdy_prio);
782 break;
783 case MEDIUM:
784 EXPECT_EQ(1, spdy_prio);
785 break;
786 case LOW:
787 case LOWEST:
788 EXPECT_EQ(2, spdy_prio);
789 break;
790 case IDLE:
791 EXPECT_EQ(3, spdy_prio);
792 break;
793 default:
794 FAIL();
796 } else {
797 switch(p) {
798 case HIGHEST:
799 EXPECT_EQ(0, spdy_prio);
800 break;
801 case MEDIUM:
802 EXPECT_EQ(1, spdy_prio);
803 break;
804 case LOW:
805 EXPECT_EQ(2, spdy_prio);
806 break;
807 case LOWEST:
808 EXPECT_EQ(3, spdy_prio);
809 break;
810 case IDLE:
811 EXPECT_EQ(4, spdy_prio);
812 break;
813 default:
814 FAIL();
818 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
819 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
820 MockRead reads[] = {
821 CreateMockRead(*resp),
822 CreateMockRead(*body),
823 MockRead(ASYNC, 0, 0) // EOF
826 DelayedSocketData data(1, reads, arraysize(reads),
827 writes, arraysize(writes));
828 HttpRequestInfo http_req = CreateGetRequest();
830 NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(),
831 GetParam(), NULL);
832 helper.RunToCompletion(&data);
833 TransactionHelperResult out = helper.output();
834 EXPECT_EQ(OK, out.rv);
835 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
836 EXPECT_EQ("hello!", out.response_data);
840 // Start three gets simultaniously; making sure that multiplexed
841 // streams work properly.
843 // This can't use the TransactionHelper method, since it only
844 // handles a single transaction, and finishes them as soon
845 // as it launches them.
847 // TODO(gavinp): create a working generalized TransactionHelper that
848 // can allow multiple streams in flight.
850 TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
851 scoped_ptr<SpdyFrame> req(
852 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
853 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
854 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
855 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
857 scoped_ptr<SpdyFrame> req2(
858 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
859 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
860 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
861 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
863 scoped_ptr<SpdyFrame> req3(
864 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
865 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
866 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
867 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
869 MockWrite writes[] = {
870 CreateMockWrite(*req),
871 CreateMockWrite(*req2),
872 CreateMockWrite(*req3),
874 MockRead reads[] = {
875 CreateMockRead(*resp, 1),
876 CreateMockRead(*body),
877 CreateMockRead(*resp2, 4),
878 CreateMockRead(*body2),
879 CreateMockRead(*resp3, 7),
880 CreateMockRead(*body3),
882 CreateMockRead(*fbody),
883 CreateMockRead(*fbody2),
884 CreateMockRead(*fbody3),
886 MockRead(ASYNC, 0, 0), // EOF
888 OrderedSocketData data(reads, arraysize(reads),
889 writes, arraysize(writes));
890 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
892 BoundNetLog log;
893 TransactionHelperResult out;
894 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
895 BoundNetLog(), GetParam(), NULL);
896 helper.RunPreTestSetup();
897 helper.AddData(&data);
898 // We require placeholder data because three get requests are sent out, so
899 // there needs to be three sets of SSL connection data.
900 helper.AddData(&data_placeholder);
901 helper.AddData(&data_placeholder);
902 scoped_ptr<HttpNetworkTransaction> trans1(
903 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
904 scoped_ptr<HttpNetworkTransaction> trans2(
905 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
906 scoped_ptr<HttpNetworkTransaction> trans3(
907 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
909 TestCompletionCallback callback1;
910 TestCompletionCallback callback2;
911 TestCompletionCallback callback3;
913 HttpRequestInfo httpreq1 = CreateGetRequest();
914 HttpRequestInfo httpreq2 = CreateGetRequest();
915 HttpRequestInfo httpreq3 = CreateGetRequest();
917 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
918 ASSERT_EQ(ERR_IO_PENDING, out.rv);
919 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
920 ASSERT_EQ(ERR_IO_PENDING, out.rv);
921 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
922 ASSERT_EQ(ERR_IO_PENDING, out.rv);
924 out.rv = callback1.WaitForResult();
925 ASSERT_EQ(OK, out.rv);
926 out.rv = callback3.WaitForResult();
927 ASSERT_EQ(OK, out.rv);
929 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
930 EXPECT_TRUE(response1->headers.get() != NULL);
931 EXPECT_TRUE(response1->was_fetched_via_spdy);
932 out.status_line = response1->headers->GetStatusLine();
933 out.response_info = *response1;
935 trans2->GetResponseInfo();
937 out.rv = ReadTransaction(trans1.get(), &out.response_data);
938 helper.VerifyDataConsumed();
939 EXPECT_EQ(OK, out.rv);
941 EXPECT_EQ(OK, out.rv);
942 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
943 EXPECT_EQ("hello!hello!", out.response_data);
946 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
947 scoped_ptr<SpdyFrame> req(
948 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
949 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
950 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
951 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
953 scoped_ptr<SpdyFrame> req2(
954 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
955 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
956 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
957 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
959 MockWrite writes[] = {
960 CreateMockWrite(*req),
961 CreateMockWrite(*req2),
963 MockRead reads[] = {
964 CreateMockRead(*resp, 1),
965 CreateMockRead(*body),
966 CreateMockRead(*resp2, 4),
967 CreateMockRead(*body2),
968 CreateMockRead(*fbody),
969 CreateMockRead(*fbody2),
970 MockRead(ASYNC, 0, 0), // EOF
972 OrderedSocketData data(reads, arraysize(reads),
973 writes, arraysize(writes));
975 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
977 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
978 data_placeholder.set_connect_data(never_finishing_connect);
980 BoundNetLog log;
981 TransactionHelperResult out;
982 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
983 BoundNetLog(), GetParam(), NULL);
984 helper.RunPreTestSetup();
985 helper.AddData(&data);
986 // We require placeholder data because two get requests are sent out, so
987 // there needs to be two sets of SSL connection data.
988 helper.AddData(&data_placeholder);
989 scoped_ptr<HttpNetworkTransaction> trans1(
990 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
991 scoped_ptr<HttpNetworkTransaction> trans2(
992 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
994 TestCompletionCallback callback1;
995 TestCompletionCallback callback2;
997 HttpRequestInfo httpreq1 = CreateGetRequest();
998 HttpRequestInfo httpreq2 = CreateGetRequest();
1000 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1001 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1002 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1003 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1005 out.rv = callback1.WaitForResult();
1006 ASSERT_EQ(OK, out.rv);
1007 out.rv = callback2.WaitForResult();
1008 ASSERT_EQ(OK, out.rv);
1010 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1011 EXPECT_TRUE(response1->headers.get() != NULL);
1012 EXPECT_TRUE(response1->was_fetched_via_spdy);
1013 out.status_line = response1->headers->GetStatusLine();
1014 out.response_info = *response1;
1015 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1016 EXPECT_EQ(OK, out.rv);
1017 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1018 EXPECT_EQ("hello!hello!", out.response_data);
1020 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1021 EXPECT_TRUE(response2->headers.get() != NULL);
1022 EXPECT_TRUE(response2->was_fetched_via_spdy);
1023 out.status_line = response2->headers->GetStatusLine();
1024 out.response_info = *response2;
1025 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1026 EXPECT_EQ(OK, out.rv);
1027 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1028 EXPECT_EQ("hello!hello!", out.response_data);
1030 helper.VerifyDataConsumed();
1033 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
1034 scoped_ptr<SpdyFrame> req(
1035 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1036 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1037 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1038 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1040 scoped_ptr<SpdyFrame> req2(
1041 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1042 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1043 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1044 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1046 MockWrite writes[] = {
1047 CreateMockWrite(*req),
1048 CreateMockWrite(*req2),
1050 MockRead reads[] = {
1051 CreateMockRead(*resp, 1),
1052 CreateMockRead(*body),
1053 CreateMockRead(*resp2, 4),
1054 CreateMockRead(*body2),
1055 CreateMockRead(*fbody),
1056 CreateMockRead(*fbody2),
1057 MockRead(ASYNC, 0, 0), // EOF
1059 OrderedSocketData preconnect_data(reads, arraysize(reads),
1060 writes, arraysize(writes));
1062 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
1064 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1065 data_placeholder.set_connect_data(never_finishing_connect);
1067 BoundNetLog log;
1068 TransactionHelperResult out;
1069 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1070 BoundNetLog(), GetParam(), NULL);
1071 helper.RunPreTestSetup();
1072 helper.AddData(&preconnect_data);
1073 // We require placeholder data because 3 connections are attempted (first is
1074 // the preconnect, 2nd and 3rd are the never finished connections.
1075 helper.AddData(&data_placeholder);
1076 helper.AddData(&data_placeholder);
1078 scoped_ptr<HttpNetworkTransaction> trans1(
1079 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1080 scoped_ptr<HttpNetworkTransaction> trans2(
1081 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1083 TestCompletionCallback callback1;
1084 TestCompletionCallback callback2;
1086 HttpRequestInfo httpreq = CreateGetRequest();
1088 // Preconnect the first.
1089 SSLConfig preconnect_ssl_config;
1090 helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
1091 HttpStreamFactory* http_stream_factory =
1092 helper.session()->http_stream_factory();
1093 helper.session()->GetNextProtos(&preconnect_ssl_config.next_protos);
1095 http_stream_factory->PreconnectStreams(
1096 1, httpreq, DEFAULT_PRIORITY,
1097 preconnect_ssl_config, preconnect_ssl_config);
1099 out.rv = trans1->Start(&httpreq, callback1.callback(), log);
1100 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1101 out.rv = trans2->Start(&httpreq, callback2.callback(), log);
1102 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1104 out.rv = callback1.WaitForResult();
1105 ASSERT_EQ(OK, out.rv);
1106 out.rv = callback2.WaitForResult();
1107 ASSERT_EQ(OK, out.rv);
1109 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1110 EXPECT_TRUE(response1->headers.get() != NULL);
1111 EXPECT_TRUE(response1->was_fetched_via_spdy);
1112 out.status_line = response1->headers->GetStatusLine();
1113 out.response_info = *response1;
1114 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1115 EXPECT_EQ(OK, out.rv);
1116 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1117 EXPECT_EQ("hello!hello!", out.response_data);
1119 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1120 EXPECT_TRUE(response2->headers.get() != NULL);
1121 EXPECT_TRUE(response2->was_fetched_via_spdy);
1122 out.status_line = response2->headers->GetStatusLine();
1123 out.response_info = *response2;
1124 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1125 EXPECT_EQ(OK, out.rv);
1126 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1127 EXPECT_EQ("hello!hello!", out.response_data);
1129 helper.VerifyDataConsumed();
1132 // Similar to ThreeGets above, however this test adds a SETTINGS
1133 // frame. The SETTINGS frame is read during the IO loop waiting on
1134 // the first transaction completion, and sets a maximum concurrent
1135 // stream limit of 1. This means that our IO loop exists after the
1136 // second transaction completes, so we can assert on read_index().
1137 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
1138 // Construct the request.
1139 scoped_ptr<SpdyFrame> req(
1140 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1141 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1142 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1143 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1145 scoped_ptr<SpdyFrame> req2(
1146 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1147 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1148 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1149 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1151 scoped_ptr<SpdyFrame> req3(
1152 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
1153 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1154 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
1155 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
1157 SettingsMap settings;
1158 const uint32 max_concurrent_streams = 1;
1159 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1160 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1161 scoped_ptr<SpdyFrame> settings_frame(
1162 spdy_util_.ConstructSpdySettings(settings));
1163 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1165 MockWrite writes[] = {
1166 CreateMockWrite(*req),
1167 CreateMockWrite(*settings_ack, 2),
1168 CreateMockWrite(*req2),
1169 CreateMockWrite(*req3),
1172 MockRead reads[] = {
1173 CreateMockRead(*settings_frame, 1),
1174 CreateMockRead(*resp),
1175 CreateMockRead(*body),
1176 CreateMockRead(*fbody),
1177 CreateMockRead(*resp2, 8),
1178 CreateMockRead(*body2),
1179 CreateMockRead(*fbody2),
1180 CreateMockRead(*resp3, 13),
1181 CreateMockRead(*body3),
1182 CreateMockRead(*fbody3),
1184 MockRead(ASYNC, 0, 0), // EOF
1187 OrderedSocketData data(reads, arraysize(reads),
1188 writes, arraysize(writes));
1189 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1191 BoundNetLog log;
1192 TransactionHelperResult out;
1194 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1195 BoundNetLog(), GetParam(), NULL);
1196 helper.RunPreTestSetup();
1197 helper.AddData(&data);
1198 // We require placeholder data because three get requests are sent out, so
1199 // there needs to be three sets of SSL connection data.
1200 helper.AddData(&data_placeholder);
1201 helper.AddData(&data_placeholder);
1202 scoped_ptr<HttpNetworkTransaction> trans1(
1203 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1204 scoped_ptr<HttpNetworkTransaction> trans2(
1205 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1206 scoped_ptr<HttpNetworkTransaction> trans3(
1207 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1209 TestCompletionCallback callback1;
1210 TestCompletionCallback callback2;
1211 TestCompletionCallback callback3;
1213 HttpRequestInfo httpreq1 = CreateGetRequest();
1214 HttpRequestInfo httpreq2 = CreateGetRequest();
1215 HttpRequestInfo httpreq3 = CreateGetRequest();
1217 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1218 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1219 // Run transaction 1 through quickly to force a read of our SETTINGS
1220 // frame.
1221 out.rv = callback1.WaitForResult();
1222 ASSERT_EQ(OK, out.rv);
1224 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1225 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1226 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1227 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1228 out.rv = callback2.WaitForResult();
1229 ASSERT_EQ(OK, out.rv);
1230 EXPECT_EQ(7U, data.read_index()); // i.e. the third trans was queued
1232 out.rv = callback3.WaitForResult();
1233 ASSERT_EQ(OK, out.rv);
1235 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1236 ASSERT_TRUE(response1 != NULL);
1237 EXPECT_TRUE(response1->headers.get() != NULL);
1238 EXPECT_TRUE(response1->was_fetched_via_spdy);
1239 out.status_line = response1->headers->GetStatusLine();
1240 out.response_info = *response1;
1241 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1242 EXPECT_EQ(OK, out.rv);
1243 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1244 EXPECT_EQ("hello!hello!", out.response_data);
1246 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1247 out.status_line = response2->headers->GetStatusLine();
1248 out.response_info = *response2;
1249 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1250 EXPECT_EQ(OK, out.rv);
1251 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1252 EXPECT_EQ("hello!hello!", out.response_data);
1254 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1255 out.status_line = response3->headers->GetStatusLine();
1256 out.response_info = *response3;
1257 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1258 EXPECT_EQ(OK, out.rv);
1259 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1260 EXPECT_EQ("hello!hello!", out.response_data);
1262 helper.VerifyDataConsumed();
1264 EXPECT_EQ(OK, out.rv);
1267 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1268 // a fourth transaction. The third and fourth transactions have
1269 // different data ("hello!" vs "hello!hello!") and because of the
1270 // user specified priority, we expect to see them inverted in
1271 // the response from the server.
1272 TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
1273 // Construct the request.
1274 scoped_ptr<SpdyFrame> req(
1275 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1276 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1277 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1278 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1280 scoped_ptr<SpdyFrame> req2(
1281 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1282 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1283 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1284 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1286 scoped_ptr<SpdyFrame> req4(
1287 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true));
1288 scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
1289 scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true));
1291 scoped_ptr<SpdyFrame> req3(
1292 spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true));
1293 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
1294 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false));
1295 scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true));
1297 SettingsMap settings;
1298 const uint32 max_concurrent_streams = 1;
1299 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1300 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1301 scoped_ptr<SpdyFrame> settings_frame(
1302 spdy_util_.ConstructSpdySettings(settings));
1303 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1305 MockWrite writes[] = { CreateMockWrite(*req),
1306 CreateMockWrite(*settings_ack, 2),
1307 CreateMockWrite(*req2),
1308 CreateMockWrite(*req4),
1309 CreateMockWrite(*req3),
1311 MockRead reads[] = {
1312 CreateMockRead(*settings_frame, 1),
1313 CreateMockRead(*resp),
1314 CreateMockRead(*body),
1315 CreateMockRead(*fbody),
1316 CreateMockRead(*resp2, 8),
1317 CreateMockRead(*body2),
1318 CreateMockRead(*fbody2),
1319 CreateMockRead(*resp4, 14),
1320 CreateMockRead(*fbody4),
1321 CreateMockRead(*resp3, 17),
1322 CreateMockRead(*body3),
1323 CreateMockRead(*fbody3),
1325 MockRead(ASYNC, 0, 0), // EOF
1328 OrderedSocketData data(reads, arraysize(reads),
1329 writes, arraysize(writes));
1330 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1332 BoundNetLog log;
1333 TransactionHelperResult out;
1334 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1335 BoundNetLog(), GetParam(), NULL);
1336 helper.RunPreTestSetup();
1337 helper.AddData(&data);
1338 // We require placeholder data because four get requests are sent out, so
1339 // there needs to be four sets of SSL connection data.
1340 helper.AddData(&data_placeholder);
1341 helper.AddData(&data_placeholder);
1342 helper.AddData(&data_placeholder);
1343 scoped_ptr<HttpNetworkTransaction> trans1(
1344 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1345 scoped_ptr<HttpNetworkTransaction> trans2(
1346 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1347 scoped_ptr<HttpNetworkTransaction> trans3(
1348 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1349 scoped_ptr<HttpNetworkTransaction> trans4(
1350 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
1352 TestCompletionCallback callback1;
1353 TestCompletionCallback callback2;
1354 TestCompletionCallback callback3;
1355 TestCompletionCallback callback4;
1357 HttpRequestInfo httpreq1 = CreateGetRequest();
1358 HttpRequestInfo httpreq2 = CreateGetRequest();
1359 HttpRequestInfo httpreq3 = CreateGetRequest();
1360 HttpRequestInfo httpreq4 = CreateGetRequest();
1362 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1363 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1364 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1365 out.rv = callback1.WaitForResult();
1366 ASSERT_EQ(OK, out.rv);
1368 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1369 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1370 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1371 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1372 out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
1373 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1375 out.rv = callback2.WaitForResult();
1376 ASSERT_EQ(OK, out.rv);
1377 EXPECT_EQ(data.read_index(), 7U); // i.e. the third & fourth trans queued
1379 out.rv = callback3.WaitForResult();
1380 ASSERT_EQ(OK, out.rv);
1382 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1383 EXPECT_TRUE(response1->headers.get() != NULL);
1384 EXPECT_TRUE(response1->was_fetched_via_spdy);
1385 out.status_line = response1->headers->GetStatusLine();
1386 out.response_info = *response1;
1387 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1388 EXPECT_EQ(OK, out.rv);
1389 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1390 EXPECT_EQ("hello!hello!", out.response_data);
1392 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1393 out.status_line = response2->headers->GetStatusLine();
1394 out.response_info = *response2;
1395 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1396 EXPECT_EQ(OK, out.rv);
1397 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1398 EXPECT_EQ("hello!hello!", out.response_data);
1400 // notice: response3 gets two hellos, response4 gets one
1401 // hello, so we know dequeuing priority was respected.
1402 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1403 out.status_line = response3->headers->GetStatusLine();
1404 out.response_info = *response3;
1405 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1406 EXPECT_EQ(OK, out.rv);
1407 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1408 EXPECT_EQ("hello!hello!", out.response_data);
1410 out.rv = callback4.WaitForResult();
1411 EXPECT_EQ(OK, out.rv);
1412 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
1413 out.status_line = response4->headers->GetStatusLine();
1414 out.response_info = *response4;
1415 out.rv = ReadTransaction(trans4.get(), &out.response_data);
1416 EXPECT_EQ(OK, out.rv);
1417 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1418 EXPECT_EQ("hello!", out.response_data);
1419 helper.VerifyDataConsumed();
1420 EXPECT_EQ(OK, out.rv);
1423 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1424 // deletes a session in the middle of the transaction to insure
1425 // that we properly remove pendingcreatestream objects from
1426 // the spdy_session
1427 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
1428 // Construct the request.
1429 scoped_ptr<SpdyFrame> req(
1430 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1431 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1432 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1433 scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
1435 scoped_ptr<SpdyFrame> req2(
1436 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1437 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1438 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
1439 scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
1441 SettingsMap settings;
1442 const uint32 max_concurrent_streams = 1;
1443 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1444 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1445 scoped_ptr<SpdyFrame> settings_frame(
1446 spdy_util_.ConstructSpdySettings(settings));
1447 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1449 MockWrite writes[] = {
1450 CreateMockWrite(*req),
1451 CreateMockWrite(*settings_ack, 2),
1452 CreateMockWrite(*req2),
1454 MockRead reads[] = {
1455 CreateMockRead(*settings_frame, 1),
1456 CreateMockRead(*resp),
1457 CreateMockRead(*body),
1458 CreateMockRead(*fbody),
1459 CreateMockRead(*resp2, 8),
1460 CreateMockRead(*body2),
1461 CreateMockRead(*fbody2),
1462 MockRead(ASYNC, 0, 0), // EOF
1465 OrderedSocketData data(reads, arraysize(reads),
1466 writes, arraysize(writes));
1467 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1469 BoundNetLog log;
1470 TransactionHelperResult out;
1471 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1472 BoundNetLog(), GetParam(), NULL);
1473 helper.RunPreTestSetup();
1474 helper.AddData(&data);
1475 // We require placeholder data because three get requests are sent out, so
1476 // there needs to be three sets of SSL connection data.
1477 helper.AddData(&data_placeholder);
1478 helper.AddData(&data_placeholder);
1479 scoped_ptr<HttpNetworkTransaction> trans1(
1480 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1481 scoped_ptr<HttpNetworkTransaction> trans2(
1482 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1483 scoped_ptr<HttpNetworkTransaction> trans3(
1484 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1486 TestCompletionCallback callback1;
1487 TestCompletionCallback callback2;
1488 TestCompletionCallback callback3;
1490 HttpRequestInfo httpreq1 = CreateGetRequest();
1491 HttpRequestInfo httpreq2 = CreateGetRequest();
1492 HttpRequestInfo httpreq3 = CreateGetRequest();
1494 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1495 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1496 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1497 out.rv = callback1.WaitForResult();
1498 ASSERT_EQ(OK, out.rv);
1500 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1501 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1502 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1503 delete trans3.release();
1504 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1505 out.rv = callback2.WaitForResult();
1506 ASSERT_EQ(OK, out.rv);
1508 EXPECT_EQ(8U, data.read_index());
1510 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1511 ASSERT_TRUE(response1 != NULL);
1512 EXPECT_TRUE(response1->headers.get() != NULL);
1513 EXPECT_TRUE(response1->was_fetched_via_spdy);
1514 out.status_line = response1->headers->GetStatusLine();
1515 out.response_info = *response1;
1516 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1517 EXPECT_EQ(OK, out.rv);
1518 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1519 EXPECT_EQ("hello!hello!", out.response_data);
1521 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1522 ASSERT_TRUE(response2 != NULL);
1523 out.status_line = response2->headers->GetStatusLine();
1524 out.response_info = *response2;
1525 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1526 EXPECT_EQ(OK, out.rv);
1527 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1528 EXPECT_EQ("hello!hello!", out.response_data);
1529 helper.VerifyDataConsumed();
1530 EXPECT_EQ(OK, out.rv);
1533 namespace {
1535 // The KillerCallback will delete the transaction on error as part of the
1536 // callback.
1537 class KillerCallback : public TestCompletionCallbackBase {
1538 public:
1539 explicit KillerCallback(HttpNetworkTransaction* transaction)
1540 : transaction_(transaction),
1541 callback_(base::Bind(&KillerCallback::OnComplete,
1542 base::Unretained(this))) {
1545 ~KillerCallback() override {}
1547 const CompletionCallback& callback() const { return callback_; }
1549 private:
1550 void OnComplete(int result) {
1551 if (result < 0)
1552 delete transaction_;
1554 SetResult(result);
1557 HttpNetworkTransaction* transaction_;
1558 CompletionCallback callback_;
1561 } // namespace
1563 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1564 // closes the socket while we have a pending transaction waiting for
1565 // a pending stream creation. http://crbug.com/52901
1566 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
1567 // Construct the request.
1568 scoped_ptr<SpdyFrame> req(
1569 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
1570 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1571 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
1572 scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1574 scoped_ptr<SpdyFrame> req2(
1575 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
1576 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
1578 SettingsMap settings;
1579 const uint32 max_concurrent_streams = 1;
1580 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1581 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1582 scoped_ptr<SpdyFrame> settings_frame(
1583 spdy_util_.ConstructSpdySettings(settings));
1584 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
1586 MockWrite writes[] = {
1587 CreateMockWrite(*req),
1588 CreateMockWrite(*settings_ack, 2),
1589 CreateMockWrite(*req2),
1591 MockRead reads[] = {
1592 CreateMockRead(*settings_frame, 1),
1593 CreateMockRead(*resp),
1594 CreateMockRead(*body),
1595 CreateMockRead(*fin_body),
1596 CreateMockRead(*resp2, 8),
1597 MockRead(ASYNC, ERR_CONNECTION_RESET, 0), // Abort!
1600 OrderedSocketData data(reads, arraysize(reads),
1601 writes, arraysize(writes));
1602 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1604 BoundNetLog log;
1605 TransactionHelperResult out;
1606 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
1607 BoundNetLog(), GetParam(), NULL);
1608 helper.RunPreTestSetup();
1609 helper.AddData(&data);
1610 // We require placeholder data because three get requests are sent out, so
1611 // there needs to be three sets of SSL connection data.
1612 helper.AddData(&data_placeholder);
1613 helper.AddData(&data_placeholder);
1614 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session().get());
1615 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session().get());
1616 HttpNetworkTransaction* trans3(
1617 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
1619 TestCompletionCallback callback1;
1620 TestCompletionCallback callback2;
1621 KillerCallback callback3(trans3);
1623 HttpRequestInfo httpreq1 = CreateGetRequest();
1624 HttpRequestInfo httpreq2 = CreateGetRequest();
1625 HttpRequestInfo httpreq3 = CreateGetRequest();
1627 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
1628 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1629 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1630 out.rv = callback1.WaitForResult();
1631 ASSERT_EQ(OK, out.rv);
1633 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
1634 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1635 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1636 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1637 out.rv = callback3.WaitForResult();
1638 ASSERT_EQ(ERR_ABORTED, out.rv);
1640 EXPECT_EQ(6U, data.read_index());
1642 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1643 ASSERT_TRUE(response1 != NULL);
1644 EXPECT_TRUE(response1->headers.get() != NULL);
1645 EXPECT_TRUE(response1->was_fetched_via_spdy);
1646 out.status_line = response1->headers->GetStatusLine();
1647 out.response_info = *response1;
1648 out.rv = ReadTransaction(&trans1, &out.response_data);
1649 EXPECT_EQ(OK, out.rv);
1651 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1652 ASSERT_TRUE(response2 != NULL);
1653 out.status_line = response2->headers->GetStatusLine();
1654 out.response_info = *response2;
1655 out.rv = ReadTransaction(&trans2, &out.response_data);
1656 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1658 helper.VerifyDataConsumed();
1661 // Test that a simple PUT request works.
1662 TEST_P(SpdyNetworkTransactionTest, Put) {
1663 // Setup the request
1664 HttpRequestInfo request;
1665 request.method = "PUT";
1666 request.url = GURL("http://www.google.com/");
1668 scoped_ptr<SpdyHeaderBlock> put_headers(
1669 spdy_util_.ConstructPutHeaderBlock("http://www.google.com", 0));
1670 scoped_ptr<SpdyFrame> req(
1671 spdy_util_.ConstructSpdySyn(1, *put_headers, LOWEST, false, true));
1672 MockWrite writes[] = {
1673 CreateMockWrite(*req),
1676 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1677 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1678 MockRead reads[] = {
1679 CreateMockRead(*resp),
1680 CreateMockRead(*body),
1681 MockRead(ASYNC, 0, 0) // EOF
1684 DelayedSocketData data(1, reads, arraysize(reads),
1685 writes, arraysize(writes));
1686 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1687 BoundNetLog(), GetParam(), NULL);
1688 helper.RunToCompletion(&data);
1689 TransactionHelperResult out = helper.output();
1691 EXPECT_EQ(OK, out.rv);
1692 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1695 // Test that a simple HEAD request works.
1696 TEST_P(SpdyNetworkTransactionTest, Head) {
1697 // Setup the request
1698 HttpRequestInfo request;
1699 request.method = "HEAD";
1700 request.url = GURL("http://www.google.com/");
1702 scoped_ptr<SpdyHeaderBlock> head_headers(
1703 spdy_util_.ConstructHeadHeaderBlock("http://www.google.com", 0));
1704 scoped_ptr<SpdyFrame> req(
1705 spdy_util_.ConstructSpdySyn(1, *head_headers, LOWEST, false, true));
1706 MockWrite writes[] = {
1707 CreateMockWrite(*req),
1710 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
1711 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1712 MockRead reads[] = {
1713 CreateMockRead(*resp),
1714 CreateMockRead(*body),
1715 MockRead(ASYNC, 0, 0) // EOF
1718 DelayedSocketData data(1, reads, arraysize(reads),
1719 writes, arraysize(writes));
1720 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1721 BoundNetLog(), GetParam(), NULL);
1722 helper.RunToCompletion(&data);
1723 TransactionHelperResult out = helper.output();
1725 EXPECT_EQ(OK, out.rv);
1726 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1729 // Test that a simple POST works.
1730 TEST_P(SpdyNetworkTransactionTest, Post) {
1731 scoped_ptr<SpdyFrame> req(
1732 spdy_util_.ConstructSpdyPost(
1733 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1734 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1735 MockWrite writes[] = {
1736 CreateMockWrite(*req),
1737 CreateMockWrite(*body), // POST upload frame
1740 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1741 MockRead reads[] = {
1742 CreateMockRead(*resp),
1743 CreateMockRead(*body),
1744 MockRead(ASYNC, 0, 0) // EOF
1747 DelayedSocketData data(2, reads, arraysize(reads),
1748 writes, arraysize(writes));
1749 NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
1750 BoundNetLog(), GetParam(), NULL);
1751 helper.RunToCompletion(&data);
1752 TransactionHelperResult out = helper.output();
1753 EXPECT_EQ(OK, out.rv);
1754 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1755 EXPECT_EQ("hello!", out.response_data);
1758 // Test that a POST with a file works.
1759 TEST_P(SpdyNetworkTransactionTest, FilePost) {
1760 scoped_ptr<SpdyFrame> req(
1761 spdy_util_.ConstructSpdyPost(
1762 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1763 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1764 MockWrite writes[] = {
1765 CreateMockWrite(*req),
1766 CreateMockWrite(*body), // POST upload frame
1769 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1770 MockRead reads[] = {
1771 CreateMockRead(*resp),
1772 CreateMockRead(*body),
1773 MockRead(ASYNC, 0, 0) // EOF
1776 DelayedSocketData data(2, reads, arraysize(reads),
1777 writes, arraysize(writes));
1778 NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
1779 BoundNetLog(), GetParam(), NULL);
1780 helper.RunToCompletion(&data);
1781 TransactionHelperResult out = helper.output();
1782 EXPECT_EQ(OK, out.rv);
1783 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1784 EXPECT_EQ("hello!", out.response_data);
1787 // Test that a POST with a unreadable file fails.
1788 TEST_P(SpdyNetworkTransactionTest, UnreadableFilePost) {
1789 MockWrite writes[] = {
1790 MockWrite(ASYNC, 0, 0) // EOF
1792 MockRead reads[] = {
1793 MockRead(ASYNC, 0, 0) // EOF
1796 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
1797 NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
1798 DEFAULT_PRIORITY,
1799 BoundNetLog(), GetParam(), NULL);
1800 helper.RunPreTestSetup();
1801 helper.AddData(&data);
1802 helper.RunDefaultTest();
1804 base::RunLoop().RunUntilIdle();
1805 helper.VerifyDataNotConsumed();
1806 EXPECT_EQ(ERR_ACCESS_DENIED, helper.output().rv);
1809 // Test that a complex POST works.
1810 TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
1811 scoped_ptr<SpdyFrame> req(
1812 spdy_util_.ConstructSpdyPost(
1813 kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
1814 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1815 MockWrite writes[] = {
1816 CreateMockWrite(*req),
1817 CreateMockWrite(*body), // POST upload frame
1820 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1821 MockRead reads[] = {
1822 CreateMockRead(*resp),
1823 CreateMockRead(*body),
1824 MockRead(ASYNC, 0, 0) // EOF
1827 DelayedSocketData data(2, reads, arraysize(reads),
1828 writes, arraysize(writes));
1829 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
1830 DEFAULT_PRIORITY,
1831 BoundNetLog(), GetParam(), NULL);
1832 helper.RunToCompletion(&data);
1833 TransactionHelperResult out = helper.output();
1834 EXPECT_EQ(OK, out.rv);
1835 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1836 EXPECT_EQ("hello!", out.response_data);
1839 // Test that a chunked POST works.
1840 TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
1841 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1842 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1843 MockWrite writes[] = {
1844 CreateMockWrite(*req),
1845 CreateMockWrite(*body),
1848 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1849 MockRead reads[] = {
1850 CreateMockRead(*resp),
1851 CreateMockRead(*body),
1852 MockRead(ASYNC, 0, 0) // EOF
1855 DelayedSocketData data(2, reads, arraysize(reads),
1856 writes, arraysize(writes));
1857 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1858 DEFAULT_PRIORITY,
1859 BoundNetLog(), GetParam(), NULL);
1861 // These chunks get merged into a single frame when being sent.
1862 const int kFirstChunkSize = kUploadDataSize/2;
1863 upload_chunked_data_stream()->AppendData(kUploadData, kFirstChunkSize, false);
1864 upload_chunked_data_stream()->AppendData(
1865 kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
1867 helper.RunToCompletion(&data);
1868 TransactionHelperResult out = helper.output();
1869 EXPECT_EQ(OK, out.rv);
1870 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1871 EXPECT_EQ(kUploadData, out.response_data);
1874 // Test that a chunked POST works with chunks appended after transaction starts.
1875 TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
1876 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
1877 scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
1878 scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false));
1879 scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
1880 MockWrite writes[] = {
1881 CreateMockWrite(*req),
1882 CreateMockWrite(*chunk1),
1883 CreateMockWrite(*chunk2),
1884 CreateMockWrite(*chunk3),
1887 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1888 MockRead reads[] = {
1889 CreateMockRead(*resp),
1890 CreateMockRead(*chunk1),
1891 CreateMockRead(*chunk2),
1892 CreateMockRead(*chunk3),
1893 MockRead(ASYNC, 0, 0) // EOF
1896 DelayedSocketData data(4, reads, arraysize(reads),
1897 writes, arraysize(writes));
1898 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1899 DEFAULT_PRIORITY,
1900 BoundNetLog(), GetParam(), NULL);
1902 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
1904 helper.RunPreTestSetup();
1905 helper.AddData(&data);
1906 ASSERT_TRUE(helper.StartDefaultTest());
1908 base::RunLoop().RunUntilIdle();
1909 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, false);
1910 base::RunLoop().RunUntilIdle();
1911 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
1913 helper.FinishDefaultTest();
1914 helper.VerifyDataConsumed();
1916 std::string expected_response;
1917 expected_response += kUploadData;
1918 expected_response += kUploadData;
1919 expected_response += kUploadData;
1921 TransactionHelperResult out = helper.output();
1922 EXPECT_EQ(OK, out.rv);
1923 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1924 EXPECT_EQ(expected_response, out.response_data);
1927 // Test that a POST without any post data works.
1928 TEST_P(SpdyNetworkTransactionTest, NullPost) {
1929 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
1930 // Setup the request
1931 HttpRequestInfo request;
1932 request.method = "POST";
1933 request.url = GURL(kRequestUrl);
1934 // Create an empty UploadData.
1935 request.upload_data_stream = NULL;
1937 // When request.upload_data_stream is NULL for post, content-length is
1938 // expected to be 0.
1939 scoped_ptr<SpdyHeaderBlock> req_block(
1940 spdy_util_.ConstructPostHeaderBlock(kRequestUrl, 0));
1941 scoped_ptr<SpdyFrame> req(
1942 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
1944 MockWrite writes[] = {
1945 CreateMockWrite(*req),
1948 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1949 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1950 MockRead reads[] = {
1951 CreateMockRead(*resp),
1952 CreateMockRead(*body),
1953 MockRead(ASYNC, 0, 0) // EOF
1956 DelayedSocketData data(1, reads, arraysize(reads),
1957 writes, arraysize(writes));
1959 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
1960 BoundNetLog(), GetParam(), NULL);
1961 helper.RunToCompletion(&data);
1962 TransactionHelperResult out = helper.output();
1963 EXPECT_EQ(OK, out.rv);
1964 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1965 EXPECT_EQ("hello!", out.response_data);
1968 // Test that a simple POST works.
1969 TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
1970 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
1971 // Create an empty UploadDataStream.
1972 ScopedVector<UploadElementReader> element_readers;
1973 ElementsUploadDataStream stream(element_readers.Pass(), 0);
1975 // Setup the request
1976 HttpRequestInfo request;
1977 request.method = "POST";
1978 request.url = GURL(kRequestUrl);
1979 request.upload_data_stream = &stream;
1981 const uint64 kContentLength = 0;
1983 scoped_ptr<SpdyHeaderBlock> req_block(
1984 spdy_util_.ConstructPostHeaderBlock(kRequestUrl, kContentLength));
1985 scoped_ptr<SpdyFrame> req(
1986 spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
1988 MockWrite writes[] = {
1989 CreateMockWrite(*req),
1992 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
1993 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
1994 MockRead reads[] = {
1995 CreateMockRead(*resp),
1996 CreateMockRead(*body),
1997 MockRead(ASYNC, 0, 0) // EOF
2000 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
2002 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
2003 BoundNetLog(), GetParam(), NULL);
2004 helper.RunToCompletion(&data);
2005 TransactionHelperResult out = helper.output();
2006 EXPECT_EQ(OK, out.rv);
2007 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2008 EXPECT_EQ("hello!", out.response_data);
2011 // While we're doing a post, the server sends the reply before upload completes.
2012 TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
2013 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
2014 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2015 MockWrite writes[] = {
2016 CreateMockWrite(*req, 0),
2017 CreateMockWrite(*body, 3),
2019 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
2020 MockRead reads[] = {
2021 CreateMockRead(*resp, 1),
2022 CreateMockRead(*body, 2),
2023 MockRead(ASYNC, 0, 4) // EOF
2026 // Write the request headers, and read the complete response
2027 // while still waiting for chunked request data.
2028 DeterministicSocketData data(reads, arraysize(reads),
2029 writes, arraysize(writes));
2030 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
2031 DEFAULT_PRIORITY,
2032 BoundNetLog(), GetParam(), NULL);
2033 helper.SetDeterministic();
2034 helper.RunPreTestSetup();
2035 helper.AddDeterministicData(&data);
2037 ASSERT_TRUE(helper.StartDefaultTest());
2039 // Process the request headers, SYN_REPLY, and response body.
2040 // The request body is still in flight.
2041 data.RunFor(3);
2043 const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
2044 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2046 // Finish sending the request body.
2047 upload_chunked_data_stream()->AppendData(kUploadData, kUploadDataSize, true);
2048 data.RunFor(2);
2050 std::string response_body;
2051 EXPECT_EQ(OK, ReadTransaction(helper.trans(), &response_body));
2052 EXPECT_EQ(kUploadData, response_body);
2053 helper.VerifyDataConsumed();
2056 // The client upon cancellation tries to send a RST_STREAM frame. The mock
2057 // socket causes the TCP write to return zero. This test checks that the client
2058 // tries to queue up the RST_STREAM frame again.
2059 TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
2060 scoped_ptr<SpdyFrame> req(
2061 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2062 scoped_ptr<SpdyFrame> rst(
2063 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2064 MockWrite writes[] = {
2065 CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
2066 MockWrite(SYNCHRONOUS, 0, 0, 2),
2067 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
2070 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2071 MockRead reads[] = {
2072 CreateMockRead(*resp.get(), 1, ASYNC),
2073 MockRead(ASYNC, 0, 0, 4) // EOF
2076 DeterministicSocketData data(reads, arraysize(reads),
2077 writes, arraysize(writes));
2078 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2079 BoundNetLog(), GetParam(), NULL);
2080 helper.SetDeterministic();
2081 helper.RunPreTestSetup();
2082 helper.AddDeterministicData(&data);
2083 HttpNetworkTransaction* trans = helper.trans();
2085 TestCompletionCallback callback;
2086 int rv = trans->Start(
2087 &CreateGetRequest(), callback.callback(), BoundNetLog());
2088 EXPECT_EQ(ERR_IO_PENDING, rv);
2090 data.SetStop(2);
2091 data.Run();
2092 helper.ResetTrans();
2093 data.SetStop(20);
2094 data.Run();
2096 helper.VerifyDataConsumed();
2099 // Test that the transaction doesn't crash when we don't have a reply.
2100 TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
2101 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2102 MockRead reads[] = {
2103 CreateMockRead(*body),
2104 MockRead(ASYNC, 0, 0) // EOF
2107 DelayedSocketData data(1, reads, arraysize(reads), NULL, 0);
2108 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2109 BoundNetLog(), GetParam(), NULL);
2110 helper.RunToCompletion(&data);
2111 TransactionHelperResult out = helper.output();
2112 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2115 // Test that the transaction doesn't crash when we get two replies on the same
2116 // stream ID. See http://crbug.com/45639.
2117 TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
2118 scoped_ptr<SpdyFrame> req(
2119 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2120 scoped_ptr<SpdyFrame> rst(
2121 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2122 MockWrite writes[] = {
2123 CreateMockWrite(*req),
2124 CreateMockWrite(*rst),
2127 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2128 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2129 MockRead reads[] = {
2130 CreateMockRead(*resp),
2131 CreateMockRead(*resp),
2132 CreateMockRead(*body),
2133 MockRead(ASYNC, 0, 0) // EOF
2136 DelayedSocketData data(1, reads, arraysize(reads),
2137 writes, arraysize(writes));
2139 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2140 BoundNetLog(), GetParam(), NULL);
2141 helper.RunPreTestSetup();
2142 helper.AddData(&data);
2144 HttpNetworkTransaction* trans = helper.trans();
2146 TestCompletionCallback callback;
2147 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2148 EXPECT_EQ(ERR_IO_PENDING, rv);
2149 rv = callback.WaitForResult();
2150 EXPECT_EQ(OK, rv);
2152 const HttpResponseInfo* response = trans->GetResponseInfo();
2153 ASSERT_TRUE(response != NULL);
2154 EXPECT_TRUE(response->headers.get() != NULL);
2155 EXPECT_TRUE(response->was_fetched_via_spdy);
2156 std::string response_data;
2157 rv = ReadTransaction(trans, &response_data);
2158 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
2160 helper.VerifyDataConsumed();
2163 TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
2164 // Construct the request.
2165 scoped_ptr<SpdyFrame> req(
2166 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2167 scoped_ptr<SpdyFrame> rst(
2168 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2169 MockWrite writes[] = {
2170 CreateMockWrite(*req),
2171 CreateMockWrite(*rst),
2174 const char* const headers[] = {
2175 "transfer-encoding", "chunked"
2177 scoped_ptr<SpdyFrame> resp(
2178 spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1));
2179 scoped_ptr<SpdyFrame> body(
2180 spdy_util_.ConstructSpdyBodyFrame(1, true));
2181 MockRead reads[] = {
2182 CreateMockRead(*resp),
2183 CreateMockRead(*body),
2184 MockRead(ASYNC, 0, 0) // EOF
2187 DelayedSocketData data(1, reads, arraysize(reads),
2188 writes, arraysize(writes));
2189 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2190 BoundNetLog(), GetParam(), NULL);
2191 helper.RunToCompletion(&data);
2192 TransactionHelperResult out = helper.output();
2193 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2195 helper.session()->spdy_session_pool()->CloseAllSessions();
2196 helper.VerifyDataConsumed();
2199 TEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
2200 // Construct the request.
2201 scoped_ptr<SpdyFrame> req(
2202 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2203 scoped_ptr<SpdyFrame> rst(
2204 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
2205 MockWrite writes[] = {
2206 CreateMockWrite(*req),
2207 CreateMockWrite(*rst),
2210 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2211 const char* const headers[] = {
2212 "transfer-encoding", "chunked"
2214 scoped_ptr<SpdyFrame> push(
2215 spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2,
2216 2, 1, "http://www.google.com/1"));
2217 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2218 MockRead reads[] = {
2219 CreateMockRead(*resp),
2220 CreateMockRead(*push),
2221 CreateMockRead(*body),
2222 MockRead(ASYNC, 0, 0) // EOF
2225 DelayedSocketData data(1, reads, arraysize(reads),
2226 writes, arraysize(writes));
2227 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2228 BoundNetLog(), GetParam(), NULL);
2229 helper.RunToCompletion(&data);
2230 TransactionHelperResult out = helper.output();
2231 EXPECT_EQ(OK, out.rv);
2232 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2233 EXPECT_EQ("hello!", out.response_data);
2235 helper.session()->spdy_session_pool()->CloseAllSessions();
2236 helper.VerifyDataConsumed();
2239 TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
2240 // Construct the request.
2241 scoped_ptr<SpdyFrame> req(
2242 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2243 MockWrite writes[] = {
2244 CreateMockWrite(*req),
2247 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2248 MockRead reads[] = {
2249 CreateMockRead(*resp),
2250 // This following read isn't used by the test, except during the
2251 // RunUntilIdle() call at the end since the SpdySession survives the
2252 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2253 // MockRead will do here.
2254 MockRead(ASYNC, 0, 0) // EOF
2257 StaticSocketDataProvider data(reads, arraysize(reads),
2258 writes, arraysize(writes));
2260 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2261 BoundNetLog(), GetParam(), NULL);
2262 helper.RunPreTestSetup();
2263 helper.AddData(&data);
2264 HttpNetworkTransaction* trans = helper.trans();
2266 TestCompletionCallback callback;
2267 int rv = trans->Start(
2268 &CreateGetRequest(), callback.callback(), BoundNetLog());
2269 EXPECT_EQ(ERR_IO_PENDING, rv);
2270 helper.ResetTrans(); // Cancel the transaction.
2272 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2273 // MockClientSocketFactory) are still alive.
2274 base::RunLoop().RunUntilIdle();
2275 helper.VerifyDataNotConsumed();
2278 // Verify that the client sends a Rst Frame upon cancelling the stream.
2279 TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
2280 scoped_ptr<SpdyFrame> req(
2281 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2282 scoped_ptr<SpdyFrame> rst(
2283 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2284 MockWrite writes[] = {
2285 CreateMockWrite(*req, 0, SYNCHRONOUS),
2286 CreateMockWrite(*rst, 2, SYNCHRONOUS),
2289 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2290 MockRead reads[] = {
2291 CreateMockRead(*resp, 1, ASYNC),
2292 MockRead(ASYNC, 0, 0, 3) // EOF
2295 DeterministicSocketData data(reads, arraysize(reads),
2296 writes, arraysize(writes));
2298 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2299 BoundNetLog(),
2300 GetParam(), NULL);
2301 helper.SetDeterministic();
2302 helper.RunPreTestSetup();
2303 helper.AddDeterministicData(&data);
2304 HttpNetworkTransaction* trans = helper.trans();
2306 TestCompletionCallback callback;
2308 int rv = trans->Start(
2309 &CreateGetRequest(), callback.callback(), BoundNetLog());
2310 EXPECT_EQ(ERR_IO_PENDING, rv);
2312 data.SetStop(2);
2313 data.Run();
2314 helper.ResetTrans();
2315 data.SetStop(20);
2316 data.Run();
2318 helper.VerifyDataConsumed();
2321 // Verify that the client can correctly deal with the user callback attempting
2322 // to start another transaction on a session that is closing down. See
2323 // http://crbug.com/47455
2324 TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
2325 scoped_ptr<SpdyFrame> req(
2326 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2327 MockWrite writes[] = { CreateMockWrite(*req) };
2328 MockWrite writes2[] = { CreateMockWrite(*req) };
2330 // The indicated length of this frame is longer than its actual length. When
2331 // the session receives an empty frame after this one, it shuts down the
2332 // session, and calls the read callback with the incomplete data.
2333 const uint8 kGetBodyFrame2[] = {
2334 0x00, 0x00, 0x00, 0x01,
2335 0x01, 0x00, 0x00, 0x07,
2336 'h', 'e', 'l', 'l', 'o', '!',
2339 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2340 MockRead reads[] = {
2341 CreateMockRead(*resp, 2),
2342 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2343 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2344 arraysize(kGetBodyFrame2), 4),
2345 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2346 MockRead(ASYNC, 0, 0, 6), // EOF
2348 MockRead reads2[] = {
2349 CreateMockRead(*resp, 2),
2350 MockRead(ASYNC, 0, 0, 3), // EOF
2353 OrderedSocketData data(reads, arraysize(reads),
2354 writes, arraysize(writes));
2355 DelayedSocketData data2(1, reads2, arraysize(reads2),
2356 writes2, arraysize(writes2));
2358 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2359 BoundNetLog(), GetParam(), NULL);
2360 helper.RunPreTestSetup();
2361 helper.AddData(&data);
2362 helper.AddData(&data2);
2363 HttpNetworkTransaction* trans = helper.trans();
2365 // Start the transaction with basic parameters.
2366 TestCompletionCallback callback;
2367 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2368 EXPECT_EQ(ERR_IO_PENDING, rv);
2369 rv = callback.WaitForResult();
2371 const int kSize = 3000;
2372 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2373 rv = trans->Read(
2374 buf.get(),
2375 kSize,
2376 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
2377 helper.session()));
2378 // This forces an err_IO_pending, which sets the callback.
2379 data.CompleteRead();
2380 // This finishes the read.
2381 data.CompleteRead();
2382 helper.VerifyDataConsumed();
2385 // Verify that the client can correctly deal with the user callback deleting the
2386 // transaction. Failures will usually be valgrind errors. See
2387 // http://crbug.com/46925
2388 TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
2389 scoped_ptr<SpdyFrame> req(
2390 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2391 MockWrite writes[] = { CreateMockWrite(*req) };
2393 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2394 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2395 MockRead reads[] = {
2396 CreateMockRead(*resp.get(), 2),
2397 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2398 CreateMockRead(*body.get(), 4),
2399 MockRead(ASYNC, 0, 0, 5), // EOF
2402 OrderedSocketData data(reads, arraysize(reads),
2403 writes, arraysize(writes));
2405 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2406 BoundNetLog(), GetParam(), NULL);
2407 helper.RunPreTestSetup();
2408 helper.AddData(&data);
2409 HttpNetworkTransaction* trans = helper.trans();
2411 // Start the transaction with basic parameters.
2412 TestCompletionCallback callback;
2413 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2414 EXPECT_EQ(ERR_IO_PENDING, rv);
2415 rv = callback.WaitForResult();
2417 // Setup a user callback which will delete the session, and clear out the
2418 // memory holding the stream object. Note that the callback deletes trans.
2419 const int kSize = 3000;
2420 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2421 rv = trans->Read(
2422 buf.get(),
2423 kSize,
2424 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
2425 base::Unretained(&helper)));
2426 ASSERT_EQ(ERR_IO_PENDING, rv);
2427 data.CompleteRead();
2429 // Finish running rest of tasks.
2430 base::RunLoop().RunUntilIdle();
2431 helper.VerifyDataConsumed();
2434 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2435 TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
2436 scoped_ptr<SpdyHeaderBlock> headers(
2437 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2438 (*headers)["user-agent"] = "";
2439 (*headers)["accept-encoding"] = "gzip, deflate";
2440 scoped_ptr<SpdyHeaderBlock> headers2(
2441 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2442 (*headers2)["user-agent"] = "";
2443 (*headers2)["accept-encoding"] = "gzip, deflate";
2445 // Setup writes/reads to www.google.com
2446 scoped_ptr<SpdyFrame> req(
2447 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
2448 scoped_ptr<SpdyFrame> req2(
2449 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
2450 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
2451 MockWrite writes[] = {
2452 CreateMockWrite(*req, 1),
2454 MockRead reads[] = {
2455 CreateMockRead(*resp, 2),
2456 MockRead(ASYNC, 0, 0, 3) // EOF
2459 // Setup writes/reads to www.foo.com
2460 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2461 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2462 MockWrite writes2[] = {
2463 CreateMockWrite(*req2, 1),
2465 MockRead reads2[] = {
2466 CreateMockRead(*resp2, 2),
2467 CreateMockRead(*body2, 3),
2468 MockRead(ASYNC, 0, 0, 4) // EOF
2470 OrderedSocketData data(reads, arraysize(reads),
2471 writes, arraysize(writes));
2472 OrderedSocketData data2(reads2, arraysize(reads2),
2473 writes2, arraysize(writes2));
2475 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2476 TestDelegate d;
2478 SpdyURLRequestContext spdy_url_request_context(
2479 GetParam().protocol,
2480 false /* force_spdy_over_ssl*/,
2481 true /* force_spdy_always */);
2482 scoped_ptr<URLRequest> r(
2483 spdy_url_request_context.CreateRequest(GURL("http://www.google.com/"),
2484 DEFAULT_PRIORITY,
2486 NULL));
2487 spdy_url_request_context.socket_factory().
2488 AddSocketDataProvider(&data);
2489 spdy_url_request_context.socket_factory().
2490 AddSocketDataProvider(&data2);
2492 d.set_quit_on_redirect(true);
2493 r->Start();
2494 base::RunLoop().Run();
2496 EXPECT_EQ(1, d.received_redirect_count());
2498 r->FollowDeferredRedirect();
2499 base::RunLoop().Run();
2500 EXPECT_EQ(1, d.response_started_count());
2501 EXPECT_FALSE(d.received_data_before_response());
2502 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r->status().status());
2503 std::string contents("hello!");
2504 EXPECT_EQ(contents, d.data_received());
2506 EXPECT_TRUE(data.at_read_eof());
2507 EXPECT_TRUE(data.at_write_eof());
2508 EXPECT_TRUE(data2.at_read_eof());
2509 EXPECT_TRUE(data2.at_write_eof());
2512 // Send a spdy request to www.google.com. Get a pushed stream that redirects to
2513 // www.foo.com.
2514 TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
2515 scoped_ptr<SpdyHeaderBlock> headers(
2516 spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2517 (*headers)["user-agent"] = "";
2518 (*headers)["accept-encoding"] = "gzip, deflate";
2520 // Setup writes/reads to www.google.com
2521 scoped_ptr<SpdyFrame> req(
2522 spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
2523 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2524 scoped_ptr<SpdyFrame> rep(
2525 spdy_util_.ConstructSpdyPush(NULL,
2529 "http://www.google.com/foo.dat",
2530 "301 Moved Permanently",
2531 "http://www.foo.com/index.php"));
2532 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2533 scoped_ptr<SpdyFrame> rst(
2534 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
2535 MockWrite writes[] = {
2536 CreateMockWrite(*req, 1),
2537 CreateMockWrite(*rst, 6),
2539 MockRead reads[] = {
2540 CreateMockRead(*resp, 2),
2541 CreateMockRead(*rep, 3),
2542 CreateMockRead(*body, 4),
2543 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2544 MockRead(ASYNC, 0, 0, 7) // EOF
2547 // Setup writes/reads to www.foo.com
2548 scoped_ptr<SpdyHeaderBlock> headers2(
2549 spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2550 (*headers2)["user-agent"] = "";
2551 (*headers2)["accept-encoding"] = "gzip, deflate";
2552 scoped_ptr<SpdyFrame> req2(
2553 spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
2554 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2555 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2556 MockWrite writes2[] = {
2557 CreateMockWrite(*req2, 1),
2559 MockRead reads2[] = {
2560 CreateMockRead(*resp2, 2),
2561 CreateMockRead(*body2, 3),
2562 MockRead(ASYNC, 0, 0, 5) // EOF
2564 OrderedSocketData data(reads, arraysize(reads),
2565 writes, arraysize(writes));
2566 OrderedSocketData data2(reads2, arraysize(reads2),
2567 writes2, arraysize(writes2));
2569 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2570 TestDelegate d;
2571 TestDelegate d2;
2572 SpdyURLRequestContext spdy_url_request_context(
2573 GetParam().protocol,
2574 false /* force_spdy_over_ssl*/,
2575 true /* force_spdy_always */);
2577 scoped_ptr<URLRequest> r(
2578 spdy_url_request_context.CreateRequest(GURL("http://www.google.com/"),
2579 DEFAULT_PRIORITY,
2581 NULL));
2582 spdy_url_request_context.socket_factory().
2583 AddSocketDataProvider(&data);
2585 r->Start();
2586 base::RunLoop().Run();
2588 EXPECT_EQ(0, d.received_redirect_count());
2589 std::string contents("hello!");
2590 EXPECT_EQ(contents, d.data_received());
2592 scoped_ptr<URLRequest> r2(
2593 spdy_url_request_context.CreateRequest(
2594 GURL("http://www.google.com/foo.dat"),
2595 DEFAULT_PRIORITY,
2596 &d2,
2597 NULL));
2598 spdy_url_request_context.socket_factory().
2599 AddSocketDataProvider(&data2);
2601 d2.set_quit_on_redirect(true);
2602 r2->Start();
2603 base::RunLoop().Run();
2604 EXPECT_EQ(1, d2.received_redirect_count());
2606 r2->FollowDeferredRedirect();
2607 base::RunLoop().Run();
2608 EXPECT_EQ(1, d2.response_started_count());
2609 EXPECT_FALSE(d2.received_data_before_response());
2610 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2->status().status());
2611 std::string contents2("hello!");
2612 EXPECT_EQ(contents2, d2.data_received());
2614 data.CompleteRead();
2615 data2.CompleteRead();
2616 EXPECT_TRUE(data.at_read_eof());
2617 EXPECT_TRUE(data.at_write_eof());
2618 EXPECT_TRUE(data2.at_read_eof());
2619 EXPECT_TRUE(data2.at_write_eof());
2622 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
2623 scoped_ptr<SpdyFrame> stream1_syn(
2624 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2625 scoped_ptr<SpdyFrame> stream1_body(
2626 spdy_util_.ConstructSpdyBodyFrame(1, true));
2627 MockWrite writes[] = {
2628 CreateMockWrite(*stream1_syn, 1),
2631 scoped_ptr<SpdyFrame>
2632 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2633 scoped_ptr<SpdyFrame>
2634 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2638 "http://www.google.com/foo.dat"));
2639 const char kPushedData[] = "pushed";
2640 scoped_ptr<SpdyFrame> stream2_body(
2641 spdy_util_.ConstructSpdyBodyFrame(
2642 2, kPushedData, strlen(kPushedData), true));
2643 MockRead reads[] = {
2644 CreateMockRead(*stream1_reply, 2),
2645 CreateMockRead(*stream2_syn, 3),
2646 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2647 CreateMockRead(*stream2_body, 5),
2648 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2651 HttpResponseInfo response;
2652 HttpResponseInfo response2;
2653 std::string expected_push_result("pushed");
2654 OrderedSocketData data(reads, arraysize(reads),
2655 writes, arraysize(writes));
2656 RunServerPushTest(&data,
2657 &response,
2658 &response2,
2659 expected_push_result);
2661 // Verify the SYN_REPLY.
2662 EXPECT_TRUE(response.headers.get() != NULL);
2663 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2665 // Verify the pushed stream.
2666 EXPECT_TRUE(response2.headers.get() != NULL);
2667 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2670 TEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
2671 scoped_ptr<SpdyFrame> stream1_syn(
2672 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2673 scoped_ptr<SpdyFrame> stream1_body(
2674 spdy_util_.ConstructSpdyBodyFrame(1, true));
2675 MockWrite writes[] = {
2676 CreateMockWrite(*stream1_syn, 1),
2679 scoped_ptr<SpdyFrame>
2680 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2681 scoped_ptr<SpdyFrame>
2682 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2686 "http://www.google.com/foo.dat"));
2687 const char kPushedData[] = "pushed";
2688 scoped_ptr<SpdyFrame> stream2_body(
2689 spdy_util_.ConstructSpdyBodyFrame(
2690 2, kPushedData, strlen(kPushedData), true));
2691 MockRead reads[] = {
2692 CreateMockRead(*stream2_syn, 2),
2693 CreateMockRead(*stream1_reply, 3),
2694 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2695 CreateMockRead(*stream2_body, 5),
2696 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2699 HttpResponseInfo response;
2700 HttpResponseInfo response2;
2701 std::string expected_push_result("pushed");
2702 OrderedSocketData data(reads, arraysize(reads),
2703 writes, arraysize(writes));
2704 RunServerPushTest(&data,
2705 &response,
2706 &response2,
2707 expected_push_result);
2709 // Verify the SYN_REPLY.
2710 EXPECT_TRUE(response.headers.get() != NULL);
2711 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2713 // Verify the pushed stream.
2714 EXPECT_TRUE(response2.headers.get() != NULL);
2715 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2718 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
2719 scoped_ptr<SpdyFrame> stream1_syn(
2720 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2721 MockWrite writes[] = { CreateMockWrite(*stream1_syn, 1), };
2723 scoped_ptr<SpdyFrame>
2724 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2725 scoped_ptr<SpdyFrame>
2726 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2730 "http://www.google.com/foo.dat"));
2731 const char kPushedData[] = "pushed";
2732 scoped_ptr<SpdyFrame> stream2_body(
2733 spdy_util_.ConstructSpdyBodyFrame(
2734 2, kPushedData, strlen(kPushedData), true));
2735 scoped_ptr<SpdyFrame>
2736 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2737 MockRead reads[] = {
2738 CreateMockRead(*stream1_reply, 2),
2739 CreateMockRead(*stream2_syn, 3),
2740 CreateMockRead(*stream2_body, 4),
2741 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2742 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2745 HttpResponseInfo response;
2746 HttpResponseInfo response2;
2747 std::string expected_push_result("pushed");
2748 OrderedSocketData data(reads, arraysize(reads),
2749 writes, arraysize(writes));
2750 RunServerPushTest(&data,
2751 &response,
2752 &response2,
2753 expected_push_result);
2755 // Verify the SYN_REPLY.
2756 EXPECT_TRUE(response.headers.get() != NULL);
2757 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2759 // Verify the pushed stream.
2760 EXPECT_TRUE(response2.headers.get() != NULL);
2761 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2764 TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
2765 scoped_ptr<SpdyFrame> stream1_syn(
2766 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2767 scoped_ptr<SpdyFrame> stream1_body(
2768 spdy_util_.ConstructSpdyBodyFrame(1, true));
2769 MockWrite writes[] = {
2770 CreateMockWrite(*stream1_syn, 1),
2773 scoped_ptr<SpdyFrame>
2774 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2775 scoped_ptr<SpdyFrame>
2776 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2780 "http://www.google.com/foo.dat"));
2781 scoped_ptr<SpdyFrame> stream2_rst(
2782 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
2783 MockRead reads[] = {
2784 CreateMockRead(*stream1_reply, 2),
2785 CreateMockRead(*stream2_syn, 3),
2786 CreateMockRead(*stream2_rst, 4),
2787 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2788 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2791 OrderedSocketData data(reads, arraysize(reads),
2792 writes, arraysize(writes));
2793 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2794 BoundNetLog(), GetParam(), NULL);
2796 helper.RunPreTestSetup();
2797 helper.AddData(&data);
2799 HttpNetworkTransaction* trans = helper.trans();
2801 // Start the transaction with basic parameters.
2802 TestCompletionCallback callback;
2803 int rv = trans->Start(
2804 &CreateGetRequest(), callback.callback(), BoundNetLog());
2805 EXPECT_EQ(ERR_IO_PENDING, rv);
2806 rv = callback.WaitForResult();
2807 EXPECT_EQ(OK, rv);
2809 // Verify that we consumed all test data.
2810 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
2811 << data.read_count()
2812 << " Read index: "
2813 << data.read_index();
2814 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
2815 << data.write_count()
2816 << " Write index: "
2817 << data.write_index();
2819 // Verify the SYN_REPLY.
2820 HttpResponseInfo response = *trans->GetResponseInfo();
2821 EXPECT_TRUE(response.headers.get() != NULL);
2822 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2825 // Verify that we don't leak streams and that we properly send a reset
2826 // if the server pushes the same stream twice.
2827 TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
2828 scoped_ptr<SpdyFrame> stream1_syn(
2829 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2830 scoped_ptr<SpdyFrame> stream1_body(
2831 spdy_util_.ConstructSpdyBodyFrame(1, true));
2832 scoped_ptr<SpdyFrame> stream3_rst(
2833 spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
2834 MockWrite writes[] = {
2835 CreateMockWrite(*stream1_syn, 1),
2836 CreateMockWrite(*stream3_rst, 5),
2839 scoped_ptr<SpdyFrame>
2840 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2841 scoped_ptr<SpdyFrame>
2842 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2846 "http://www.google.com/foo.dat"));
2847 const char kPushedData[] = "pushed";
2848 scoped_ptr<SpdyFrame> stream2_body(
2849 spdy_util_.ConstructSpdyBodyFrame(
2850 2, kPushedData, strlen(kPushedData), true));
2851 scoped_ptr<SpdyFrame>
2852 stream3_syn(spdy_util_.ConstructSpdyPush(NULL,
2856 "http://www.google.com/foo.dat"));
2857 MockRead reads[] = {
2858 CreateMockRead(*stream1_reply, 2),
2859 CreateMockRead(*stream2_syn, 3),
2860 CreateMockRead(*stream3_syn, 4),
2861 CreateMockRead(*stream1_body, 6, SYNCHRONOUS),
2862 CreateMockRead(*stream2_body, 7),
2863 MockRead(ASYNC, ERR_IO_PENDING, 8), // Force a pause
2866 HttpResponseInfo response;
2867 HttpResponseInfo response2;
2868 std::string expected_push_result("pushed");
2869 OrderedSocketData data(reads, arraysize(reads),
2870 writes, arraysize(writes));
2871 RunServerPushTest(&data,
2872 &response,
2873 &response2,
2874 expected_push_result);
2876 // Verify the SYN_REPLY.
2877 EXPECT_TRUE(response.headers.get() != NULL);
2878 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2880 // Verify the pushed stream.
2881 EXPECT_TRUE(response2.headers.get() != NULL);
2882 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2885 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
2886 scoped_ptr<SpdyFrame> stream1_syn(
2887 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2888 scoped_ptr<SpdyFrame> stream1_body(
2889 spdy_util_.ConstructSpdyBodyFrame(1, true));
2890 MockWrite writes[] = {
2891 CreateMockWrite(*stream1_syn, 1),
2894 scoped_ptr<SpdyFrame>
2895 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2896 scoped_ptr<SpdyFrame>
2897 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2901 "http://www.google.com/foo.dat"));
2902 static const char kPushedData[] = "pushed my darling hello my baby";
2903 scoped_ptr<SpdyFrame> stream2_body_base(
2904 spdy_util_.ConstructSpdyBodyFrame(
2905 2, kPushedData, strlen(kPushedData), true));
2906 const size_t kChunkSize = strlen(kPushedData) / 4;
2907 scoped_ptr<SpdyFrame> stream2_body1(
2908 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2909 scoped_ptr<SpdyFrame> stream2_body2(
2910 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2911 scoped_ptr<SpdyFrame> stream2_body3(
2912 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2913 kChunkSize, false));
2914 scoped_ptr<SpdyFrame> stream2_body4(
2915 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2916 stream2_body_base->size() - 3 * kChunkSize, false));
2917 MockRead reads[] = {
2918 CreateMockRead(*stream1_reply, 2),
2919 CreateMockRead(*stream2_syn, 3),
2920 CreateMockRead(*stream2_body1, 4),
2921 CreateMockRead(*stream2_body2, 5),
2922 CreateMockRead(*stream2_body3, 6),
2923 CreateMockRead(*stream2_body4, 7),
2924 CreateMockRead(*stream1_body, 8, SYNCHRONOUS),
2925 MockRead(ASYNC, ERR_IO_PENDING, 9), // Force a pause
2928 HttpResponseInfo response;
2929 HttpResponseInfo response2;
2930 std::string expected_push_result("pushed my darling hello my baby");
2931 OrderedSocketData data(reads, arraysize(reads),
2932 writes, arraysize(writes));
2933 RunServerPushTest(&data, &response, &response2, kPushedData);
2935 // Verify the SYN_REPLY.
2936 EXPECT_TRUE(response.headers.get() != NULL);
2937 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2939 // Verify the pushed stream.
2940 EXPECT_TRUE(response2.headers.get() != NULL);
2941 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2944 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
2945 scoped_ptr<SpdyFrame> stream1_syn(
2946 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2947 scoped_ptr<SpdyFrame> stream1_body(
2948 spdy_util_.ConstructSpdyBodyFrame(1, true));
2949 MockWrite writes[] = {
2950 CreateMockWrite(*stream1_syn, 1),
2953 scoped_ptr<SpdyFrame>
2954 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2955 scoped_ptr<SpdyFrame>
2956 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2960 "http://www.google.com/foo.dat"));
2961 static const char kPushedData[] = "pushed my darling hello my baby";
2962 scoped_ptr<SpdyFrame> stream2_body_base(
2963 spdy_util_.ConstructSpdyBodyFrame(
2964 2, kPushedData, strlen(kPushedData), true));
2965 const size_t kChunkSize = strlen(kPushedData) / 4;
2966 scoped_ptr<SpdyFrame> stream2_body1(
2967 new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2968 scoped_ptr<SpdyFrame> stream2_body2(
2969 new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2970 scoped_ptr<SpdyFrame> stream2_body3(
2971 new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2972 kChunkSize, false));
2973 scoped_ptr<SpdyFrame> stream2_body4(
2974 new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2975 stream2_body_base->size() - 3 * kChunkSize, false));
2976 MockRead reads[] = {
2977 CreateMockRead(*stream1_reply, 2),
2978 CreateMockRead(*stream2_syn, 3),
2979 CreateMockRead(*stream2_body1, 4),
2980 CreateMockRead(*stream2_body2, 5),
2981 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2982 CreateMockRead(*stream2_body3, 7),
2983 CreateMockRead(*stream2_body4, 8),
2984 CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS),
2985 MockRead(ASYNC, ERR_IO_PENDING, 10) // Force a pause.
2988 HttpResponseInfo response;
2989 HttpResponseInfo response2;
2990 OrderedSocketData data(reads, arraysize(reads),
2991 writes, arraysize(writes));
2992 RunServerPushTest(&data, &response, &response2, kPushedData);
2994 // Verify the SYN_REPLY.
2995 EXPECT_TRUE(response.headers.get() != NULL);
2996 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2998 // Verify the pushed stream.
2999 EXPECT_TRUE(response2.headers.get() != NULL);
3000 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3003 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
3004 if (spdy_util_.spdy_version() == SPDY4) {
3005 // PUSH_PROMISE with stream id 0 is connection-level error.
3006 // TODO(baranovich): Test session going away.
3007 return;
3010 scoped_ptr<SpdyFrame> stream1_syn(
3011 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3012 scoped_ptr<SpdyFrame> stream1_body(
3013 spdy_util_.ConstructSpdyBodyFrame(1, true));
3014 scoped_ptr<SpdyFrame> stream2_rst(
3015 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
3016 MockWrite writes[] = {
3017 CreateMockWrite(*stream1_syn, 1),
3018 CreateMockWrite(*stream2_rst, 4),
3021 scoped_ptr<SpdyFrame>
3022 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3023 scoped_ptr<SpdyFrame>
3024 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3028 "http://www.google.com/foo.dat"));
3029 MockRead reads[] = {
3030 CreateMockRead(*stream1_reply, 2),
3031 CreateMockRead(*stream2_syn, 3),
3032 CreateMockRead(*stream1_body, 4),
3033 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3036 OrderedSocketData data(reads, arraysize(reads),
3037 writes, arraysize(writes));
3038 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3039 BoundNetLog(), GetParam(), NULL);
3041 helper.RunPreTestSetup();
3042 helper.AddData(&data);
3044 HttpNetworkTransaction* trans = helper.trans();
3046 // Start the transaction with basic parameters.
3047 TestCompletionCallback callback;
3048 int rv = trans->Start(
3049 &CreateGetRequest(), callback.callback(), BoundNetLog());
3050 EXPECT_EQ(ERR_IO_PENDING, rv);
3051 rv = callback.WaitForResult();
3052 EXPECT_EQ(OK, rv);
3054 // Verify that we consumed all test data.
3055 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3056 << data.read_count()
3057 << " Read index: "
3058 << data.read_index();
3059 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3060 << data.write_count()
3061 << " Write index: "
3062 << data.write_index();
3064 // Verify the SYN_REPLY.
3065 HttpResponseInfo response = *trans->GetResponseInfo();
3066 EXPECT_TRUE(response.headers.get() != NULL);
3067 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3070 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
3071 scoped_ptr<SpdyFrame> stream1_syn(
3072 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3073 scoped_ptr<SpdyFrame> stream1_body(
3074 spdy_util_.ConstructSpdyBodyFrame(1, true));
3075 scoped_ptr<SpdyFrame> stream2_rst(
3076 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
3077 MockWrite writes[] = {
3078 CreateMockWrite(*stream1_syn, 1),
3079 CreateMockWrite(*stream2_rst, 4),
3082 scoped_ptr<SpdyFrame>
3083 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3084 scoped_ptr<SpdyFrame>
3085 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3089 "http://www.google.com/foo.dat"));
3090 MockRead reads[] = {
3091 CreateMockRead(*stream1_reply, 2),
3092 CreateMockRead(*stream2_syn, 3),
3093 CreateMockRead(*stream1_body, 4),
3094 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
3097 OrderedSocketData data(reads, arraysize(reads),
3098 writes, arraysize(writes));
3099 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3100 BoundNetLog(), GetParam(), NULL);
3102 helper.RunPreTestSetup();
3103 helper.AddData(&data);
3105 HttpNetworkTransaction* trans = helper.trans();
3107 // Start the transaction with basic parameters.
3108 TestCompletionCallback callback;
3109 int rv = trans->Start(
3110 &CreateGetRequest(), callback.callback(), BoundNetLog());
3111 EXPECT_EQ(ERR_IO_PENDING, rv);
3112 rv = callback.WaitForResult();
3113 EXPECT_EQ(OK, rv);
3115 // Verify that we consumed all test data.
3116 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3117 << data.read_count()
3118 << " Read index: "
3119 << data.read_index();
3120 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3121 << data.write_count()
3122 << " Write index: "
3123 << data.write_index();
3125 // Verify the SYN_REPLY.
3126 HttpResponseInfo response = *trans->GetResponseInfo();
3127 EXPECT_TRUE(response.headers.get() != NULL);
3128 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3131 TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
3132 scoped_ptr<SpdyFrame> stream1_syn(
3133 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3134 scoped_ptr<SpdyFrame> stream1_body(
3135 spdy_util_.ConstructSpdyBodyFrame(1, true));
3136 scoped_ptr<SpdyFrame> stream2_rst(
3137 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
3138 MockWrite writes[] = {
3139 CreateMockWrite(*stream1_syn, 1),
3140 CreateMockWrite(*stream2_rst, 4),
3143 scoped_ptr<SpdyFrame>
3144 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3145 scoped_ptr<SpdyHeaderBlock> incomplete_headers(new SpdyHeaderBlock());
3146 (*incomplete_headers)["hello"] = "bye";
3147 (*incomplete_headers)[spdy_util_.GetStatusKey()] = "200 OK";
3148 (*incomplete_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
3149 scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
3150 incomplete_headers.Pass(), 2, 1));
3151 MockRead reads[] = {
3152 CreateMockRead(*stream1_reply, 2),
3153 CreateMockRead(*stream2_syn, 3),
3154 CreateMockRead(*stream1_body, 4),
3155 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3158 OrderedSocketData data(reads, arraysize(reads),
3159 writes, arraysize(writes));
3160 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3161 BoundNetLog(), GetParam(), NULL);
3163 helper.RunPreTestSetup();
3164 helper.AddData(&data);
3166 HttpNetworkTransaction* trans = helper.trans();
3168 // Start the transaction with basic parameters.
3169 TestCompletionCallback callback;
3170 int rv = trans->Start(
3171 &CreateGetRequest(), callback.callback(), BoundNetLog());
3172 EXPECT_EQ(ERR_IO_PENDING, rv);
3173 rv = callback.WaitForResult();
3174 EXPECT_EQ(OK, rv);
3175 // Verify that we consumed all test data.
3176 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3177 << data.read_count()
3178 << " Read index: "
3179 << data.read_index();
3180 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3181 << data.write_count()
3182 << " Write index: "
3183 << data.write_index();
3185 // Verify the SYN_REPLY.
3186 HttpResponseInfo response = *trans->GetResponseInfo();
3187 EXPECT_TRUE(response.headers.get() != NULL);
3188 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3191 // Verify that various SynReply headers parse correctly through the
3192 // HTTP layer.
3193 TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
3194 struct SynReplyHeadersTests {
3195 int num_headers;
3196 const char* extra_headers[5];
3197 SpdyHeaderBlock expected_headers;
3198 } test_cases[] = {
3199 // This uses a multi-valued cookie header.
3200 { 2,
3201 { "cookie", "val1",
3202 "cookie", "val2", // will get appended separated by NULL
3203 NULL
3206 // This is the minimalist set of headers.
3207 { 0,
3208 { NULL },
3210 // Headers with a comma separated list.
3211 { 1,
3212 { "cookie", "val1,val2",
3213 NULL
3218 test_cases[0].expected_headers["cookie"] = "val1";
3219 test_cases[0].expected_headers["cookie"] += '\0';
3220 test_cases[0].expected_headers["cookie"] += "val2";
3221 test_cases[0].expected_headers["hello"] = "bye";
3222 test_cases[0].expected_headers["status"] = "200";
3224 test_cases[1].expected_headers["hello"] = "bye";
3225 test_cases[1].expected_headers["status"] = "200";
3227 test_cases[2].expected_headers["cookie"] = "val1,val2";
3228 test_cases[2].expected_headers["hello"] = "bye";
3229 test_cases[2].expected_headers["status"] = "200";
3231 if (spdy_util_.spdy_version() < SPDY4) {
3232 // SPDY4/HTTP2 eliminates use of the :version header.
3233 test_cases[0].expected_headers["version"] = "HTTP/1.1";
3234 test_cases[1].expected_headers["version"] = "HTTP/1.1";
3235 test_cases[2].expected_headers["version"] = "HTTP/1.1";
3238 for (size_t i = 0; i < arraysize(test_cases); ++i) {
3239 scoped_ptr<SpdyFrame> req(
3240 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3241 MockWrite writes[] = { CreateMockWrite(*req) };
3243 scoped_ptr<SpdyFrame> resp(
3244 spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
3245 test_cases[i].num_headers,
3246 1));
3247 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3248 MockRead reads[] = {
3249 CreateMockRead(*resp),
3250 CreateMockRead(*body),
3251 MockRead(ASYNC, 0, 0) // EOF
3254 DelayedSocketData data(1, reads, arraysize(reads),
3255 writes, arraysize(writes));
3256 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3257 BoundNetLog(), GetParam(), NULL);
3258 helper.RunToCompletion(&data);
3259 TransactionHelperResult out = helper.output();
3261 EXPECT_EQ(OK, out.rv);
3262 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3263 EXPECT_EQ("hello!", out.response_data);
3265 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3266 EXPECT_TRUE(headers.get() != NULL);
3267 void* iter = NULL;
3268 std::string name, value;
3269 SpdyHeaderBlock header_block;
3270 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3271 if (header_block[name].empty()) {
3272 header_block[name] = value;
3273 } else {
3274 header_block[name] += '\0';
3275 header_block[name] += value;
3278 EXPECT_EQ(test_cases[i].expected_headers, header_block);
3282 // Verify that various SynReply headers parse vary fields correctly
3283 // through the HTTP layer, and the response matches the request.
3284 TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
3285 // Modify the following data to change/add test cases:
3286 struct SynReplyTests {
3287 bool vary_matches;
3288 int num_headers[2];
3289 const char* extra_headers[2][16];
3290 } test_cases[] = {
3291 // Test the case of a multi-valued cookie. When the value is delimited
3292 // with NUL characters, it needs to be unfolded into multiple headers.
3294 true,
3295 { 1, 4 },
3296 { { "cookie", "val1,val2",
3297 NULL
3299 { "vary", "cookie",
3300 spdy_util_.GetStatusKey(), "200",
3301 spdy_util_.GetPathKey(), "/index.php",
3302 spdy_util_.GetVersionKey(), "HTTP/1.1",
3303 NULL
3306 }, { // Multiple vary fields.
3307 true,
3308 { 2, 5 },
3309 { { "friend", "barney",
3310 "enemy", "snaggletooth",
3311 NULL
3313 { "vary", "friend",
3314 "vary", "enemy",
3315 spdy_util_.GetStatusKey(), "200",
3316 spdy_util_.GetPathKey(), "/index.php",
3317 spdy_util_.GetVersionKey(), "HTTP/1.1",
3318 NULL
3321 }, { // Test a '*' vary field.
3322 false,
3323 { 1, 4 },
3324 { { "cookie", "val1,val2",
3325 NULL
3327 { "vary", "*",
3328 spdy_util_.GetStatusKey(), "200",
3329 spdy_util_.GetPathKey(), "/index.php",
3330 spdy_util_.GetVersionKey(), "HTTP/1.1",
3331 NULL
3334 }, { // Multiple comma-separated vary fields.
3335 true,
3336 { 2, 4 },
3337 { { "friend", "barney",
3338 "enemy", "snaggletooth",
3339 NULL
3341 { "vary", "friend,enemy",
3342 spdy_util_.GetStatusKey(), "200",
3343 spdy_util_.GetPathKey(), "/index.php",
3344 spdy_util_.GetVersionKey(), "HTTP/1.1",
3345 NULL
3351 for (size_t i = 0; i < arraysize(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 SpdyHeaderBlock reply_headers;
3364 AppendToHeaderBlock(test_cases[i].extra_headers[1],
3365 test_cases[i].num_headers[1],
3366 &reply_headers);
3367 scoped_ptr<SpdyFrame> frame_reply(
3368 spdy_util_.ConstructSpdyReply(1, reply_headers));
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;
3413 void* iter = NULL;
3414 std::string name, value, lines;
3415 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3416 lines.append(name);
3417 lines.append(": ");
3418 lines.append(value);
3419 lines.append("\n");
3422 // Construct the expected header reply string.
3423 std::string expected_reply =
3424 spdy_util_.ConstructSpdyReplyString(reply_headers);
3425 EXPECT_EQ(expected_reply, lines) << i;
3429 // Verify that we don't crash on invalid SynReply responses.
3430 TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
3431 struct InvalidSynReplyTests {
3432 int num_headers;
3433 const char* headers[10];
3434 } test_cases[] = {
3435 // SYN_REPLY missing status header
3436 { 4,
3437 { "cookie", "val1",
3438 "cookie", "val2",
3439 spdy_util_.GetPathKey(), "/index.php",
3440 spdy_util_.GetVersionKey(), "HTTP/1.1",
3441 NULL
3444 // SYN_REPLY missing version header
3445 { 2,
3446 { "status", "200",
3447 spdy_util_.GetPathKey(), "/index.php",
3448 NULL
3451 // SYN_REPLY with no headers
3452 { 0, { NULL }, },
3455 for (size_t i = 0; i < arraysize(test_cases); ++i) {
3456 scoped_ptr<SpdyFrame> req(
3457 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3458 scoped_ptr<SpdyFrame> rst(
3459 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3460 MockWrite writes[] = {
3461 CreateMockWrite(*req),
3462 CreateMockWrite(*rst),
3465 // Construct the reply.
3466 SpdyHeaderBlock reply_headers;
3467 AppendToHeaderBlock(
3468 test_cases[i].headers, test_cases[i].num_headers, &reply_headers);
3469 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, reply_headers));
3470 MockRead reads[] = {
3471 CreateMockRead(*resp),
3472 MockRead(ASYNC, 0, 0) // EOF
3475 DelayedSocketData data(1, reads, arraysize(reads),
3476 writes, arraysize(writes));
3477 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3478 BoundNetLog(), GetParam(), NULL);
3479 helper.RunToCompletion(&data);
3480 TransactionHelperResult out = helper.output();
3481 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3485 // Verify that we don't crash on some corrupt frames.
3486 // TODO(jgraettinger): SPDY4 and up treats a header decompression failure as a
3487 // connection error. I'd like to backport this behavior to SPDY3 as well.
3488 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
3489 if (spdy_util_.spdy_version() >= SPDY4) {
3490 return;
3492 // This is the length field that's too short.
3493 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3494 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3495 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3496 size_t right_size =
3497 (spdy_util_.spdy_version() < SPDY4) ?
3498 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize() :
3499 syn_reply_wrong_length->size();
3500 size_t wrong_size = right_size - 4;
3501 test::SetFrameLength(syn_reply_wrong_length.get(),
3502 wrong_size,
3503 spdy_util_.spdy_version());
3505 struct SynReplyTests {
3506 const SpdyFrame* syn_reply;
3507 } test_cases[] = {
3508 { syn_reply_wrong_length.get(), },
3511 for (size_t i = 0; i < arraysize(test_cases); ++i) {
3512 scoped_ptr<SpdyFrame> req(
3513 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3514 scoped_ptr<SpdyFrame> rst(
3515 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3516 MockWrite writes[] = {
3517 CreateMockWrite(*req),
3518 CreateMockWrite(*rst),
3521 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3522 MockRead reads[] = {
3523 MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size),
3524 CreateMockRead(*body),
3525 MockRead(ASYNC, 0, 0) // EOF
3528 DelayedSocketData data(1, reads, arraysize(reads),
3529 writes, arraysize(writes));
3530 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3531 BoundNetLog(), GetParam(), NULL);
3532 helper.RunToCompletion(&data);
3533 TransactionHelperResult out = helper.output();
3534 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3538 // SPDY4 treats a header decompression failure as a connection-level error.
3539 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionErrorSpdy4) {
3540 if (spdy_util_.spdy_version() < SPDY4) {
3541 return;
3543 // This is the length field that's too short.
3544 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
3545 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3546 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3547 size_t right_size =
3548 syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize();
3549 size_t wrong_size = right_size - 4;
3550 test::SetFrameLength(syn_reply_wrong_length.get(),
3551 wrong_size,
3552 spdy_util_.spdy_version());
3554 scoped_ptr<SpdyFrame> req(
3555 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3556 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3557 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3558 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3560 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3561 MockRead reads[] = {
3562 MockRead(ASYNC, syn_reply_wrong_length->data(),
3563 syn_reply_wrong_length->size() - 4),
3566 DelayedSocketData data(1, reads, arraysize(reads),
3567 writes, arraysize(writes));
3568 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3569 BoundNetLog(), GetParam(), NULL);
3570 helper.RunToCompletion(&data);
3571 TransactionHelperResult out = helper.output();
3572 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3575 TEST_P(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
3576 if (GetParam().protocol < kProtoSPDY4MinimumVersion) {
3577 // Decompression failures are a stream error in SPDY3 and above.
3578 return;
3580 scoped_ptr<SpdyFrame> req(
3581 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3582 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3583 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3584 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3586 // Read HEADERS with corrupted payload.
3587 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3588 memset(resp->data() + 12, 0xff, resp->size() - 12);
3589 MockRead reads[] = {CreateMockRead(*resp)};
3591 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
3592 NormalSpdyTransactionHelper helper(
3593 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3594 helper.RunToCompletion(&data);
3595 TransactionHelperResult out = helper.output();
3596 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3599 TEST_P(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
3600 scoped_ptr<SpdyFrame> req(
3601 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3602 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3603 0, GOAWAY_PROTOCOL_ERROR, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
3604 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3606 // Read WINDOW_UPDATE with incorrectly-sized payload.
3607 // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
3608 // which is mapped to a protocol error, and not a frame size error.
3609 scoped_ptr<SpdyFrame> bad_window_update(
3610 spdy_util_.ConstructSpdyWindowUpdate(1, 1));
3611 test::SetFrameLength(bad_window_update.get(),
3612 bad_window_update->size() - 1,
3613 spdy_util_.spdy_version());
3614 MockRead reads[] = {CreateMockRead(*bad_window_update)};
3616 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
3617 NormalSpdyTransactionHelper helper(
3618 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3619 helper.RunToCompletion(&data);
3620 TransactionHelperResult out = helper.output();
3621 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3624 // Test that we shutdown correctly on write errors.
3625 TEST_P(SpdyNetworkTransactionTest, WriteError) {
3626 scoped_ptr<SpdyFrame> req(
3627 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3628 MockWrite writes[] = {
3629 // We'll write 10 bytes successfully
3630 MockWrite(ASYNC, req->data(), 10, 0),
3631 // Followed by ERROR!
3632 MockWrite(ASYNC, ERR_FAILED, 1),
3633 // Session drains and attempts to write a GOAWAY: Another ERROR!
3634 MockWrite(ASYNC, ERR_FAILED, 2),
3637 MockRead reads[] = {
3638 MockRead(ASYNC, 0, 3) // EOF
3641 DeterministicSocketData data(reads, arraysize(reads),
3642 writes, arraysize(writes));
3644 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3645 BoundNetLog(), GetParam(), NULL);
3646 helper.SetDeterministic();
3647 helper.RunPreTestSetup();
3648 helper.AddDeterministicData(&data);
3649 EXPECT_TRUE(helper.StartDefaultTest());
3650 data.RunFor(2);
3651 helper.FinishDefaultTest();
3652 EXPECT_TRUE(data.at_write_eof());
3653 EXPECT_TRUE(!data.at_read_eof());
3654 TransactionHelperResult out = helper.output();
3655 EXPECT_EQ(ERR_FAILED, out.rv);
3658 // Test that partial writes work.
3659 TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
3660 // Chop the SYN_STREAM frame into 5 chunks.
3661 scoped_ptr<SpdyFrame> req(
3662 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3663 const int kChunks = 5;
3664 scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
3666 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3667 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3668 MockRead reads[] = {
3669 CreateMockRead(*resp),
3670 CreateMockRead(*body),
3671 MockRead(ASYNC, 0, 0) // EOF
3674 DelayedSocketData data(kChunks, reads, arraysize(reads),
3675 writes.get(), kChunks);
3676 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3677 BoundNetLog(), GetParam(), NULL);
3678 helper.RunToCompletion(&data);
3679 TransactionHelperResult out = helper.output();
3680 EXPECT_EQ(OK, out.rv);
3681 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3682 EXPECT_EQ("hello!", out.response_data);
3685 // In this test, we enable compression, but get a uncompressed SynReply from
3686 // the server. Verify that teardown is all clean.
3687 TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
3688 if (spdy_util_.spdy_version() >= SPDY4) {
3689 // HPACK doesn't use deflate compression.
3690 return;
3692 scoped_ptr<SpdyFrame> compressed(
3693 spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
3694 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3695 0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3696 MockWrite writes[] = {CreateMockWrite(*compressed), CreateMockWrite(*goaway)};
3698 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3699 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3700 MockRead reads[] = {
3701 CreateMockRead(*resp),
3704 DelayedSocketData data(1, reads, arraysize(reads),
3705 writes, arraysize(writes));
3706 SpdySessionDependencies* session_deps =
3707 CreateSpdySessionDependencies(GetParam());
3708 session_deps->enable_compression = true;
3709 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3710 BoundNetLog(), GetParam(), session_deps);
3711 helper.RunToCompletion(&data);
3712 TransactionHelperResult out = helper.output();
3713 EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3714 data.Reset();
3717 // Test that the NetLog contains good data for a simple GET request.
3718 TEST_P(SpdyNetworkTransactionTest, NetLog) {
3719 static const char* const kExtraHeaders[] = {
3720 "user-agent", "Chrome",
3722 scoped_ptr<SpdyFrame> req(
3723 spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
3724 MockWrite writes[] = { CreateMockWrite(*req) };
3726 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3727 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
3728 MockRead reads[] = {
3729 CreateMockRead(*resp),
3730 CreateMockRead(*body),
3731 MockRead(ASYNC, 0, 0) // EOF
3734 CapturingBoundNetLog log;
3736 DelayedSocketData data(1, reads, arraysize(reads),
3737 writes, arraysize(writes));
3738 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
3739 DEFAULT_PRIORITY,
3740 log.bound(), GetParam(), NULL);
3741 helper.RunToCompletion(&data);
3742 TransactionHelperResult out = helper.output();
3743 EXPECT_EQ(OK, out.rv);
3744 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3745 EXPECT_EQ("hello!", out.response_data);
3747 // Check that the NetLog was filled reasonably.
3748 // This test is intentionally non-specific about the exact ordering of the
3749 // log; instead we just check to make sure that certain events exist, and that
3750 // they are in the right order.
3751 net::CapturingNetLog::CapturedEntryList entries;
3752 log.GetEntries(&entries);
3754 EXPECT_LT(0u, entries.size());
3755 int pos = 0;
3756 pos = net::ExpectLogContainsSomewhere(entries, 0,
3757 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3758 net::NetLog::PHASE_BEGIN);
3759 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3760 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3761 net::NetLog::PHASE_END);
3762 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3763 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3764 net::NetLog::PHASE_BEGIN);
3765 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3766 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3767 net::NetLog::PHASE_END);
3768 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3769 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3770 net::NetLog::PHASE_BEGIN);
3771 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3772 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3773 net::NetLog::PHASE_END);
3775 // Check that we logged all the headers correctly
3776 pos = net::ExpectLogContainsSomewhere(
3777 entries, 0,
3778 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
3779 net::NetLog::PHASE_NONE);
3781 base::ListValue* header_list;
3782 ASSERT_TRUE(entries[pos].params.get());
3783 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
3785 std::vector<std::string> expected;
3786 expected.push_back(std::string(spdy_util_.GetHostKey()) + ": www.google.com");
3787 expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
3788 expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": http");
3789 expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
3790 expected.push_back("user-agent: Chrome");
3791 if (spdy_util_.spdy_version() < SPDY4) {
3792 // SPDY4/HTTP2 eliminates use of the :version header.
3793 expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
3795 EXPECT_EQ(expected.size(), header_list->GetSize());
3796 for (std::vector<std::string>::const_iterator it = expected.begin();
3797 it != expected.end();
3798 ++it) {
3799 base::StringValue header(*it);
3800 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
3801 "Header not found: " << *it;
3805 // Since we buffer the IO from the stream to the renderer, this test verifies
3806 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3807 // on the network, but issued a Read for only 5 of those bytes) that the data
3808 // flow still works correctly.
3809 TEST_P(SpdyNetworkTransactionTest, BufferFull) {
3810 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3812 scoped_ptr<SpdyFrame> req(
3813 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3814 MockWrite writes[] = { CreateMockWrite(*req) };
3816 // 2 data frames in a single read.
3817 scoped_ptr<SpdyFrame> data_frame_1(
3818 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
3819 scoped_ptr<SpdyFrame> data_frame_2(
3820 framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
3821 const SpdyFrame* data_frames[2] = {
3822 data_frame_1.get(),
3823 data_frame_2.get(),
3825 char combined_data_frames[100];
3826 int combined_data_frames_len =
3827 CombineFrames(data_frames, arraysize(data_frames),
3828 combined_data_frames, arraysize(combined_data_frames));
3829 scoped_ptr<SpdyFrame> last_frame(
3830 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
3832 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3833 MockRead reads[] = {
3834 CreateMockRead(*resp),
3835 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3836 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3837 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3838 CreateMockRead(*last_frame),
3839 MockRead(ASYNC, 0, 0) // EOF
3842 DelayedSocketData data(1, reads, arraysize(reads),
3843 writes, arraysize(writes));
3845 TestCompletionCallback callback;
3847 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3848 BoundNetLog(), GetParam(), NULL);
3849 helper.RunPreTestSetup();
3850 helper.AddData(&data);
3851 HttpNetworkTransaction* trans = helper.trans();
3852 int rv = trans->Start(
3853 &CreateGetRequest(), callback.callback(), BoundNetLog());
3854 EXPECT_EQ(ERR_IO_PENDING, rv);
3856 TransactionHelperResult out = helper.output();
3857 out.rv = callback.WaitForResult();
3858 EXPECT_EQ(out.rv, OK);
3860 const HttpResponseInfo* response = trans->GetResponseInfo();
3861 EXPECT_TRUE(response->headers.get() != NULL);
3862 EXPECT_TRUE(response->was_fetched_via_spdy);
3863 out.status_line = response->headers->GetStatusLine();
3864 out.response_info = *response; // Make a copy so we can verify.
3866 // Read Data
3867 TestCompletionCallback read_callback;
3869 std::string content;
3870 do {
3871 // Read small chunks at a time.
3872 const int kSmallReadSize = 3;
3873 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3874 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3875 if (rv == net::ERR_IO_PENDING) {
3876 data.CompleteRead();
3877 rv = read_callback.WaitForResult();
3879 if (rv > 0) {
3880 content.append(buf->data(), rv);
3881 } else if (rv < 0) {
3882 NOTREACHED();
3884 } while (rv > 0);
3886 out.response_data.swap(content);
3888 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3889 // MockClientSocketFactory) are still alive.
3890 base::RunLoop().RunUntilIdle();
3892 // Verify that we consumed all test data.
3893 helper.VerifyDataConsumed();
3895 EXPECT_EQ(OK, out.rv);
3896 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3897 EXPECT_EQ("goodbye world", out.response_data);
3900 // Verify that basic buffering works; when multiple data frames arrive
3901 // at the same time, ensure that we don't notify a read completion for
3902 // each data frame individually.
3903 TEST_P(SpdyNetworkTransactionTest, Buffering) {
3904 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3906 scoped_ptr<SpdyFrame> req(
3907 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3908 MockWrite writes[] = { CreateMockWrite(*req) };
3910 // 4 data frames in a single read.
3911 scoped_ptr<SpdyFrame> data_frame(
3912 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
3913 scoped_ptr<SpdyFrame> data_frame_fin(
3914 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
3915 const SpdyFrame* data_frames[4] = {
3916 data_frame.get(),
3917 data_frame.get(),
3918 data_frame.get(),
3919 data_frame_fin.get()
3921 char combined_data_frames[100];
3922 int combined_data_frames_len =
3923 CombineFrames(data_frames, arraysize(data_frames),
3924 combined_data_frames, arraysize(combined_data_frames));
3926 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3927 MockRead reads[] = {
3928 CreateMockRead(*resp),
3929 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3930 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3931 MockRead(ASYNC, 0, 0) // EOF
3934 DelayedSocketData data(1, reads, arraysize(reads),
3935 writes, arraysize(writes));
3937 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3938 BoundNetLog(), GetParam(), NULL);
3939 helper.RunPreTestSetup();
3940 helper.AddData(&data);
3941 HttpNetworkTransaction* trans = helper.trans();
3943 TestCompletionCallback callback;
3944 int rv = trans->Start(
3945 &CreateGetRequest(), callback.callback(), BoundNetLog());
3946 EXPECT_EQ(ERR_IO_PENDING, rv);
3948 TransactionHelperResult out = helper.output();
3949 out.rv = callback.WaitForResult();
3950 EXPECT_EQ(out.rv, OK);
3952 const HttpResponseInfo* response = trans->GetResponseInfo();
3953 EXPECT_TRUE(response->headers.get() != NULL);
3954 EXPECT_TRUE(response->was_fetched_via_spdy);
3955 out.status_line = response->headers->GetStatusLine();
3956 out.response_info = *response; // Make a copy so we can verify.
3958 // Read Data
3959 TestCompletionCallback read_callback;
3961 std::string content;
3962 int reads_completed = 0;
3963 do {
3964 // Read small chunks at a time.
3965 const int kSmallReadSize = 14;
3966 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3967 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
3968 if (rv == net::ERR_IO_PENDING) {
3969 data.CompleteRead();
3970 rv = read_callback.WaitForResult();
3972 if (rv > 0) {
3973 EXPECT_EQ(kSmallReadSize, rv);
3974 content.append(buf->data(), rv);
3975 } else if (rv < 0) {
3976 FAIL() << "Unexpected read error: " << rv;
3978 reads_completed++;
3979 } while (rv > 0);
3981 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
3983 out.response_data.swap(content);
3985 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3986 // MockClientSocketFactory) are still alive.
3987 base::RunLoop().RunUntilIdle();
3989 // Verify that we consumed all test data.
3990 helper.VerifyDataConsumed();
3992 EXPECT_EQ(OK, out.rv);
3993 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3994 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
3997 // Verify the case where we buffer data but read it after it has been buffered.
3998 TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
3999 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4001 scoped_ptr<SpdyFrame> req(
4002 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4003 MockWrite writes[] = { CreateMockWrite(*req) };
4005 // 5 data frames in a single read.
4006 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4007 scoped_ptr<SpdyFrame> data_frame(
4008 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4009 scoped_ptr<SpdyFrame> data_frame_fin(
4010 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
4011 const SpdyFrame* frames[5] = {reply.get(), data_frame.get(), data_frame.get(),
4012 data_frame.get(), data_frame_fin.get()};
4013 char combined_frames[200];
4014 int combined_frames_len =
4015 CombineFrames(frames, arraysize(frames),
4016 combined_frames, arraysize(combined_frames));
4018 MockRead reads[] = {
4019 MockRead(ASYNC, combined_frames, combined_frames_len),
4020 MockRead(ASYNC, 0, 0) // EOF
4023 DelayedSocketData data(1, reads, arraysize(reads),
4024 writes, arraysize(writes));
4026 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4027 BoundNetLog(), GetParam(), NULL);
4028 helper.RunPreTestSetup();
4029 helper.AddData(&data);
4030 HttpNetworkTransaction* trans = helper.trans();
4032 TestCompletionCallback callback;
4033 int rv = trans->Start(
4034 &CreateGetRequest(), callback.callback(), BoundNetLog());
4035 EXPECT_EQ(ERR_IO_PENDING, rv);
4037 TransactionHelperResult out = helper.output();
4038 out.rv = callback.WaitForResult();
4039 EXPECT_EQ(out.rv, OK);
4041 const HttpResponseInfo* response = trans->GetResponseInfo();
4042 EXPECT_TRUE(response->headers.get() != NULL);
4043 EXPECT_TRUE(response->was_fetched_via_spdy);
4044 out.status_line = response->headers->GetStatusLine();
4045 out.response_info = *response; // Make a copy so we can verify.
4047 // Read Data
4048 TestCompletionCallback read_callback;
4050 std::string content;
4051 int reads_completed = 0;
4052 do {
4053 // Read small chunks at a time.
4054 const int kSmallReadSize = 14;
4055 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4056 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4057 if (rv > 0) {
4058 EXPECT_EQ(kSmallReadSize, rv);
4059 content.append(buf->data(), rv);
4060 } else if (rv < 0) {
4061 FAIL() << "Unexpected read error: " << rv;
4063 reads_completed++;
4064 } while (rv > 0);
4066 EXPECT_EQ(3, reads_completed);
4068 out.response_data.swap(content);
4070 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4071 // MockClientSocketFactory) are still alive.
4072 base::RunLoop().RunUntilIdle();
4074 // Verify that we consumed all test data.
4075 helper.VerifyDataConsumed();
4077 EXPECT_EQ(OK, out.rv);
4078 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4079 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4082 // Verify the case where we buffer data and close the connection.
4083 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
4084 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4086 scoped_ptr<SpdyFrame> req(
4087 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4088 MockWrite writes[] = { CreateMockWrite(*req) };
4090 // All data frames in a single read.
4091 // NOTE: We don't FIN the stream.
4092 scoped_ptr<SpdyFrame> data_frame(
4093 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4094 const SpdyFrame* data_frames[4] = {
4095 data_frame.get(),
4096 data_frame.get(),
4097 data_frame.get(),
4098 data_frame.get()
4100 char combined_data_frames[100];
4101 int combined_data_frames_len =
4102 CombineFrames(data_frames, arraysize(data_frames),
4103 combined_data_frames, arraysize(combined_data_frames));
4104 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4105 MockRead reads[] = {
4106 CreateMockRead(*resp),
4107 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4108 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4109 MockRead(ASYNC, 0, 0) // EOF
4112 DelayedSocketData data(1, reads, arraysize(reads),
4113 writes, arraysize(writes));
4115 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4116 BoundNetLog(), GetParam(), NULL);
4117 helper.RunPreTestSetup();
4118 helper.AddData(&data);
4119 HttpNetworkTransaction* trans = helper.trans();
4121 TestCompletionCallback callback;
4123 int rv = trans->Start(
4124 &CreateGetRequest(), callback.callback(), BoundNetLog());
4125 EXPECT_EQ(ERR_IO_PENDING, rv);
4127 TransactionHelperResult out = helper.output();
4128 out.rv = callback.WaitForResult();
4129 EXPECT_EQ(out.rv, OK);
4131 const HttpResponseInfo* response = trans->GetResponseInfo();
4132 EXPECT_TRUE(response->headers.get() != NULL);
4133 EXPECT_TRUE(response->was_fetched_via_spdy);
4134 out.status_line = response->headers->GetStatusLine();
4135 out.response_info = *response; // Make a copy so we can verify.
4137 // Read Data
4138 TestCompletionCallback read_callback;
4140 std::string content;
4141 int reads_completed = 0;
4142 do {
4143 // Read small chunks at a time.
4144 const int kSmallReadSize = 14;
4145 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4146 rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
4147 if (rv == net::ERR_IO_PENDING) {
4148 data.CompleteRead();
4149 rv = read_callback.WaitForResult();
4151 if (rv > 0) {
4152 content.append(buf->data(), rv);
4153 } else if (rv < 0) {
4154 // This test intentionally closes the connection, and will get an error.
4155 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
4156 break;
4158 reads_completed++;
4159 } while (rv > 0);
4161 EXPECT_EQ(0, reads_completed);
4163 out.response_data.swap(content);
4165 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4166 // MockClientSocketFactory) are still alive.
4167 base::RunLoop().RunUntilIdle();
4169 // Verify that we consumed all test data.
4170 helper.VerifyDataConsumed();
4173 // Verify the case where we buffer data and cancel the transaction.
4174 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
4175 BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
4177 scoped_ptr<SpdyFrame> req(
4178 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4179 scoped_ptr<SpdyFrame> rst(
4180 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
4181 MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*rst)};
4183 // NOTE: We don't FIN the stream.
4184 scoped_ptr<SpdyFrame> data_frame(
4185 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4187 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4188 MockRead reads[] = {
4189 CreateMockRead(*resp),
4190 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4191 CreateMockRead(*data_frame),
4192 MockRead(ASYNC, 0, 0) // EOF
4195 DelayedSocketData data(1, reads, arraysize(reads),
4196 writes, arraysize(writes));
4198 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4199 BoundNetLog(), GetParam(), NULL);
4200 helper.RunPreTestSetup();
4201 helper.AddData(&data);
4202 HttpNetworkTransaction* trans = helper.trans();
4203 TestCompletionCallback callback;
4205 int rv = trans->Start(
4206 &CreateGetRequest(), callback.callback(), BoundNetLog());
4207 EXPECT_EQ(ERR_IO_PENDING, rv);
4209 TransactionHelperResult out = helper.output();
4210 out.rv = callback.WaitForResult();
4211 EXPECT_EQ(out.rv, OK);
4213 const HttpResponseInfo* response = trans->GetResponseInfo();
4214 EXPECT_TRUE(response->headers.get() != NULL);
4215 EXPECT_TRUE(response->was_fetched_via_spdy);
4216 out.status_line = response->headers->GetStatusLine();
4217 out.response_info = *response; // Make a copy so we can verify.
4219 // Read Data
4220 TestCompletionCallback read_callback;
4222 const int kReadSize = 256;
4223 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
4224 rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
4225 ASSERT_EQ(net::ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
4227 // Complete the read now, which causes buffering to start.
4228 data.CompleteRead();
4229 // Destroy the transaction, causing the stream to get cancelled
4230 // and orphaning the buffered IO task.
4231 helper.ResetTrans();
4233 // Flush the MessageLoop; this will cause the buffered IO task
4234 // to run for the final time.
4235 base::RunLoop().RunUntilIdle();
4237 // Verify that we consumed all test data.
4238 helper.VerifyDataConsumed();
4241 // Test that if the server requests persistence of settings, that we save
4242 // the settings in the HttpServerProperties.
4243 TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
4244 if (spdy_util_.spdy_version() >= SPDY4) {
4245 // SPDY4 doesn't support settings persistence.
4246 return;
4248 static const SpdyHeaderInfo kSynReplyInfo = {
4249 SYN_REPLY, // Syn Reply
4250 1, // Stream ID
4251 0, // Associated Stream ID
4252 ConvertRequestPriorityToSpdyPriority(
4253 LOWEST, spdy_util_.spdy_version()),
4254 kSpdyCredentialSlotUnused,
4255 CONTROL_FLAG_NONE, // Control Flags
4256 false, // Compressed
4257 RST_STREAM_INVALID, // Status
4258 NULL, // Data
4259 0, // Data Length
4260 DATA_FLAG_NONE // Data Flags
4263 BoundNetLog net_log;
4264 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4265 net_log, GetParam(), NULL);
4266 helper.RunPreTestSetup();
4268 // Verify that no settings exist initially.
4269 HostPortPair host_port_pair("www.google.com", helper.port());
4270 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4271 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4272 host_port_pair).empty());
4274 // Construct the request.
4275 scoped_ptr<SpdyFrame> req(
4276 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4277 MockWrite writes[] = { CreateMockWrite(*req) };
4279 // Construct the reply.
4280 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4281 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4282 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4283 scoped_ptr<SpdyFrame> reply(
4284 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4286 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
4287 unsigned int kSampleValue1 = 0x0a0a0a0a;
4288 const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
4289 unsigned int kSampleValue2 = 0x0b0b0b0b;
4290 const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
4291 unsigned int kSampleValue3 = 0x0c0c0c0c;
4292 scoped_ptr<SpdyFrame> settings_frame;
4294 // Construct the SETTINGS frame.
4295 SettingsMap settings;
4296 // First add a persisted setting.
4297 settings[kSampleId1] =
4298 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
4299 // Next add a non-persisted setting.
4300 settings[kSampleId2] =
4301 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
4302 // Next add another persisted setting.
4303 settings[kSampleId3] =
4304 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
4305 settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
4308 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4309 MockRead reads[] = {
4310 CreateMockRead(*reply),
4311 CreateMockRead(*body),
4312 CreateMockRead(*settings_frame),
4313 MockRead(ASYNC, 0, 0) // EOF
4316 DelayedSocketData data(1, reads, arraysize(reads),
4317 writes, arraysize(writes));
4318 helper.AddData(&data);
4319 helper.RunDefaultTest();
4320 helper.VerifyDataConsumed();
4321 TransactionHelperResult out = helper.output();
4322 EXPECT_EQ(OK, out.rv);
4323 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4324 EXPECT_EQ("hello!", out.response_data);
4327 // Verify we had two persisted settings.
4328 const SettingsMap& settings_map =
4329 spdy_session_pool->http_server_properties()->GetSpdySettings(
4330 host_port_pair);
4331 ASSERT_EQ(2u, settings_map.size());
4333 // Verify the first persisted setting.
4334 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4335 EXPECT_TRUE(it1 != settings_map.end());
4336 SettingsFlagsAndValue flags_and_value1 = it1->second;
4337 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4338 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4340 // Verify the second persisted setting.
4341 SettingsMap::const_iterator it3 = settings_map.find(kSampleId3);
4342 EXPECT_TRUE(it3 != settings_map.end());
4343 SettingsFlagsAndValue flags_and_value3 = it3->second;
4344 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first);
4345 EXPECT_EQ(kSampleValue3, flags_and_value3.second);
4349 // Test that when there are settings saved that they are sent back to the
4350 // server upon session establishment.
4351 TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
4352 if (spdy_util_.spdy_version() >= SPDY4) {
4353 // SPDY4 doesn't support settings persistence.
4354 return;
4356 static const SpdyHeaderInfo kSynReplyInfo = {
4357 SYN_REPLY, // Syn Reply
4358 1, // Stream ID
4359 0, // Associated Stream ID
4360 ConvertRequestPriorityToSpdyPriority(
4361 LOWEST, spdy_util_.spdy_version()),
4362 kSpdyCredentialSlotUnused,
4363 CONTROL_FLAG_NONE, // Control Flags
4364 false, // Compressed
4365 RST_STREAM_INVALID, // Status
4366 NULL, // Data
4367 0, // Data Length
4368 DATA_FLAG_NONE // Data Flags
4371 BoundNetLog net_log;
4372 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4373 net_log, GetParam(), NULL);
4374 helper.RunPreTestSetup();
4376 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4378 SpdySessionPoolPeer pool_peer(spdy_session_pool);
4379 pool_peer.SetEnableSendingInitialData(true);
4381 // Verify that no settings exist initially.
4382 HostPortPair host_port_pair("www.google.com", helper.port());
4383 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4384 host_port_pair).empty());
4386 const SpdySettingsIds kSampleId1 = SETTINGS_MAX_CONCURRENT_STREAMS;
4387 unsigned int kSampleValue1 = 0x0a0a0a0a;
4388 const SpdySettingsIds kSampleId2 = SETTINGS_INITIAL_WINDOW_SIZE;
4389 unsigned int kSampleValue2 = 0x0c0c0c0c;
4391 // First add a persisted setting.
4392 spdy_session_pool->http_server_properties()->SetSpdySetting(
4393 host_port_pair,
4394 kSampleId1,
4395 SETTINGS_FLAG_PLEASE_PERSIST,
4396 kSampleValue1);
4398 // Next add another persisted setting.
4399 spdy_session_pool->http_server_properties()->SetSpdySetting(
4400 host_port_pair,
4401 kSampleId2,
4402 SETTINGS_FLAG_PLEASE_PERSIST,
4403 kSampleValue2);
4405 EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4406 host_port_pair).size());
4408 // Construct the initial SETTINGS frame.
4409 SettingsMap initial_settings;
4410 initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4411 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
4412 scoped_ptr<SpdyFrame> initial_settings_frame(
4413 spdy_util_.ConstructSpdySettings(initial_settings));
4415 // Construct the initial window update.
4416 scoped_ptr<SpdyFrame> initial_window_update(
4417 spdy_util_.ConstructSpdyWindowUpdate(
4418 kSessionFlowControlStreamId,
4419 kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
4421 // Construct the persisted SETTINGS frame.
4422 const SettingsMap& settings =
4423 spdy_session_pool->http_server_properties()->GetSpdySettings(
4424 host_port_pair);
4425 scoped_ptr<SpdyFrame> settings_frame(
4426 spdy_util_.ConstructSpdySettings(settings));
4428 // Construct the request.
4429 scoped_ptr<SpdyFrame> req(
4430 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4432 std::vector<MockWrite> writes;
4433 if ((GetParam().protocol >= kProtoSPDY4MinimumVersion) &&
4434 (GetParam().protocol <= kProtoSPDY4MaximumVersion)) {
4435 writes.push_back(
4436 MockWrite(ASYNC,
4437 kHttp2ConnectionHeaderPrefix,
4438 kHttp2ConnectionHeaderPrefixSize));
4440 writes.push_back(CreateMockWrite(*initial_settings_frame));
4441 if (GetParam().protocol >= kProtoSPDY31) {
4442 writes.push_back(CreateMockWrite(*initial_window_update));
4444 writes.push_back(CreateMockWrite(*settings_frame));
4445 writes.push_back(CreateMockWrite(*req));
4447 // Construct the reply.
4448 scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4449 (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4450 (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4451 scoped_ptr<SpdyFrame> reply(
4452 spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4454 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4455 MockRead reads[] = {
4456 CreateMockRead(*reply),
4457 CreateMockRead(*body),
4458 MockRead(ASYNC, 0, 0) // EOF
4461 DelayedSocketData data(2, reads, arraysize(reads),
4462 vector_as_array(&writes), writes.size());
4463 helper.AddData(&data);
4464 helper.RunDefaultTest();
4465 helper.VerifyDataConsumed();
4466 TransactionHelperResult out = helper.output();
4467 EXPECT_EQ(OK, out.rv);
4468 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4469 EXPECT_EQ("hello!", out.response_data);
4472 // Verify we had two persisted settings.
4473 const SettingsMap& settings_map =
4474 spdy_session_pool->http_server_properties()->GetSpdySettings(
4475 host_port_pair);
4476 ASSERT_EQ(2u, settings_map.size());
4478 // Verify the first persisted setting.
4479 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4480 EXPECT_TRUE(it1 != settings_map.end());
4481 SettingsFlagsAndValue flags_and_value1 = it1->second;
4482 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4483 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4485 // Verify the second persisted setting.
4486 SettingsMap::const_iterator it2 = settings_map.find(kSampleId2);
4487 EXPECT_TRUE(it2 != settings_map.end());
4488 SettingsFlagsAndValue flags_and_value2 = it2->second;
4489 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first);
4490 EXPECT_EQ(kSampleValue2, flags_and_value2.second);
4494 TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
4495 scoped_ptr<SpdyFrame> req(
4496 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4497 MockWrite writes[] = { CreateMockWrite(*req) };
4499 scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
4500 MockRead reads[] = {
4501 CreateMockRead(*go_away),
4504 DelayedSocketData data(1, reads, arraysize(reads),
4505 writes, arraysize(writes));
4506 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4507 BoundNetLog(), GetParam(), NULL);
4508 helper.AddData(&data);
4509 helper.RunToCompletion(&data);
4510 TransactionHelperResult out = helper.output();
4511 EXPECT_EQ(ERR_ABORTED, out.rv);
4514 TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
4515 scoped_ptr<SpdyFrame> req(
4516 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4517 MockWrite writes[] = { CreateMockWrite(*req) };
4519 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4520 MockRead reads[] = {
4521 CreateMockRead(*resp),
4522 MockRead(SYNCHRONOUS, 0, 0) // EOF
4525 DelayedSocketData data(1, reads, arraysize(reads),
4526 writes, arraysize(writes));
4527 BoundNetLog log;
4528 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4529 log, GetParam(), NULL);
4530 helper.RunPreTestSetup();
4531 helper.AddData(&data);
4532 HttpNetworkTransaction* trans = helper.trans();
4534 TestCompletionCallback callback;
4535 TransactionHelperResult out;
4536 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
4538 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4539 out.rv = callback.WaitForResult();
4540 EXPECT_EQ(out.rv, OK);
4542 const HttpResponseInfo* response = trans->GetResponseInfo();
4543 EXPECT_TRUE(response->headers.get() != NULL);
4544 EXPECT_TRUE(response->was_fetched_via_spdy);
4545 out.rv = ReadTransaction(trans, &out.response_data);
4546 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4548 // Verify that we consumed all test data.
4549 helper.VerifyDataConsumed();
4552 // Test to make sure we can correctly connect through a proxy.
4553 TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
4554 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4555 BoundNetLog(), GetParam(), NULL);
4556 helper.session_deps().reset(CreateSpdySessionDependencies(
4557 GetParam(),
4558 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4559 helper.SetSession(make_scoped_refptr(
4560 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4561 helper.RunPreTestSetup();
4562 HttpNetworkTransaction* trans = helper.trans();
4564 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4565 "Host: www.google.com\r\n"
4566 "Proxy-Connection: keep-alive\r\n\r\n"};
4567 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4568 "Host: www.google.com\r\n"
4569 "Proxy-Connection: keep-alive\r\n\r\n"};
4570 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4571 scoped_ptr<SpdyFrame> req(
4572 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4573 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4574 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4576 MockWrite writes_SPDYNPN[] = {
4577 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4578 CreateMockWrite(*req, 2),
4580 MockRead reads_SPDYNPN[] = {
4581 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4582 CreateMockRead(*resp, 3),
4583 CreateMockRead(*body.get(), 4),
4584 MockRead(ASYNC, 0, 0, 5),
4587 MockWrite writes_SPDYSSL[] = {
4588 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4589 CreateMockWrite(*req, 2),
4591 MockRead reads_SPDYSSL[] = {
4592 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4593 CreateMockRead(*resp, 3),
4594 CreateMockRead(*body.get(), 4),
4595 MockRead(ASYNC, 0, 0, 5),
4598 MockWrite writes_SPDYNOSSL[] = {
4599 CreateMockWrite(*req, 0),
4602 MockRead reads_SPDYNOSSL[] = {
4603 CreateMockRead(*resp, 1),
4604 CreateMockRead(*body.get(), 2),
4605 MockRead(ASYNC, 0, 0, 3),
4608 scoped_ptr<OrderedSocketData> data;
4609 switch (GetParam().ssl_type) {
4610 case SPDYNOSSL:
4611 data.reset(new OrderedSocketData(reads_SPDYNOSSL,
4612 arraysize(reads_SPDYNOSSL),
4613 writes_SPDYNOSSL,
4614 arraysize(writes_SPDYNOSSL)));
4615 break;
4616 case SPDYSSL:
4617 data.reset(new OrderedSocketData(reads_SPDYSSL,
4618 arraysize(reads_SPDYSSL),
4619 writes_SPDYSSL,
4620 arraysize(writes_SPDYSSL)));
4621 break;
4622 case SPDYNPN:
4623 data.reset(new OrderedSocketData(reads_SPDYNPN,
4624 arraysize(reads_SPDYNPN),
4625 writes_SPDYNPN,
4626 arraysize(writes_SPDYNPN)));
4627 break;
4628 default:
4629 NOTREACHED();
4632 helper.AddData(data.get());
4633 TestCompletionCallback callback;
4635 int rv = trans->Start(
4636 &CreateGetRequest(), callback.callback(), BoundNetLog());
4637 EXPECT_EQ(ERR_IO_PENDING, rv);
4639 rv = callback.WaitForResult();
4640 EXPECT_EQ(0, rv);
4642 // Verify the SYN_REPLY.
4643 HttpResponseInfo response = *trans->GetResponseInfo();
4644 EXPECT_TRUE(response.headers.get() != NULL);
4645 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4647 std::string response_data;
4648 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4649 EXPECT_EQ("hello!", response_data);
4650 helper.VerifyDataConsumed();
4653 // Test to make sure we can correctly connect through a proxy to www.google.com,
4654 // if there already exists a direct spdy connection to www.google.com. See
4655 // http://crbug.com/49874
4656 TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
4657 // When setting up the first transaction, we store the SpdySessionPool so that
4658 // we can use the same pool in the second transaction.
4659 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4660 BoundNetLog(), GetParam(), NULL);
4662 // Use a proxy service which returns a proxy fallback list from DIRECT to
4663 // myproxy:70. For this test there will be no fallback, so it is equivalent
4664 // to simply DIRECT. The reason for appending the second proxy is to verify
4665 // that the session pool key used does is just "DIRECT".
4666 helper.session_deps().reset(CreateSpdySessionDependencies(
4667 GetParam(),
4668 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4669 helper.SetSession(make_scoped_refptr(
4670 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4672 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4673 helper.RunPreTestSetup();
4675 // Construct and send a simple GET request.
4676 scoped_ptr<SpdyFrame> req(
4677 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4678 MockWrite writes[] = {
4679 CreateMockWrite(*req, 1),
4682 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4683 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4684 MockRead reads[] = {
4685 CreateMockRead(*resp, 2),
4686 CreateMockRead(*body, 3),
4687 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
4688 MockRead(ASYNC, 0, 5) // EOF
4690 OrderedSocketData data(reads, arraysize(reads),
4691 writes, arraysize(writes));
4692 helper.AddData(&data);
4693 HttpNetworkTransaction* trans = helper.trans();
4695 TestCompletionCallback callback;
4696 TransactionHelperResult out;
4697 out.rv = trans->Start(
4698 &CreateGetRequest(), callback.callback(), BoundNetLog());
4700 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4701 out.rv = callback.WaitForResult();
4702 EXPECT_EQ(out.rv, OK);
4704 const HttpResponseInfo* response = trans->GetResponseInfo();
4705 EXPECT_TRUE(response->headers.get() != NULL);
4706 EXPECT_TRUE(response->was_fetched_via_spdy);
4707 out.rv = ReadTransaction(trans, &out.response_data);
4708 EXPECT_EQ(OK, out.rv);
4709 out.status_line = response->headers->GetStatusLine();
4710 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4711 EXPECT_EQ("hello!", out.response_data);
4713 // Check that the SpdySession is still in the SpdySessionPool.
4714 HostPortPair host_port_pair("www.google.com", helper.port());
4715 SpdySessionKey session_pool_key_direct(
4716 host_port_pair, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
4717 EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
4718 SpdySessionKey session_pool_key_proxy(
4719 host_port_pair,
4720 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
4721 PRIVACY_MODE_DISABLED);
4722 EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
4724 // Set up data for the proxy connection.
4725 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4726 "Host: www.google.com\r\n"
4727 "Proxy-Connection: keep-alive\r\n\r\n"};
4728 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4729 "Host: www.google.com\r\n"
4730 "Proxy-Connection: keep-alive\r\n\r\n"};
4731 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4732 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
4733 "http://www.google.com/foo.dat", false, 1, LOWEST));
4734 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4735 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
4737 MockWrite writes_SPDYNPN[] = {
4738 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4739 CreateMockWrite(*req2, 2),
4741 MockRead reads_SPDYNPN[] = {
4742 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4743 CreateMockRead(*resp2, 3),
4744 CreateMockRead(*body2, 4),
4745 MockRead(ASYNC, 0, 5) // EOF
4748 MockWrite writes_SPDYNOSSL[] = {
4749 CreateMockWrite(*req2, 0),
4751 MockRead reads_SPDYNOSSL[] = {
4752 CreateMockRead(*resp2, 1),
4753 CreateMockRead(*body2, 2),
4754 MockRead(ASYNC, 0, 3) // EOF
4757 MockWrite writes_SPDYSSL[] = {
4758 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4759 CreateMockWrite(*req2, 2),
4761 MockRead reads_SPDYSSL[] = {
4762 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4763 CreateMockRead(*resp2, 3),
4764 CreateMockRead(*body2, 4),
4765 MockRead(ASYNC, 0, 0, 5),
4768 scoped_ptr<OrderedSocketData> data_proxy;
4769 switch (GetParam().ssl_type) {
4770 case SPDYNPN:
4771 data_proxy.reset(new OrderedSocketData(reads_SPDYNPN,
4772 arraysize(reads_SPDYNPN),
4773 writes_SPDYNPN,
4774 arraysize(writes_SPDYNPN)));
4775 break;
4776 case SPDYNOSSL:
4777 data_proxy.reset(new OrderedSocketData(reads_SPDYNOSSL,
4778 arraysize(reads_SPDYNOSSL),
4779 writes_SPDYNOSSL,
4780 arraysize(writes_SPDYNOSSL)));
4781 break;
4782 case SPDYSSL:
4783 data_proxy.reset(new OrderedSocketData(reads_SPDYSSL,
4784 arraysize(reads_SPDYSSL),
4785 writes_SPDYSSL,
4786 arraysize(writes_SPDYSSL)));
4787 break;
4788 default:
4789 NOTREACHED();
4792 // Create another request to www.google.com, but this time through a proxy.
4793 HttpRequestInfo request_proxy;
4794 request_proxy.method = "GET";
4795 request_proxy.url = GURL("http://www.google.com/foo.dat");
4796 request_proxy.load_flags = 0;
4797 scoped_ptr<SpdySessionDependencies> ssd_proxy(
4798 CreateSpdySessionDependencies(GetParam()));
4799 // Ensure that this transaction uses the same SpdySessionPool.
4800 scoped_refptr<HttpNetworkSession> session_proxy(
4801 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
4802 NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
4803 BoundNetLog(), GetParam(), NULL);
4804 HttpNetworkSessionPeer session_peer(session_proxy);
4805 scoped_ptr<net::ProxyService> proxy_service(
4806 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
4807 session_peer.SetProxyService(proxy_service.get());
4808 helper_proxy.session_deps().swap(ssd_proxy);
4809 helper_proxy.SetSession(session_proxy);
4810 helper_proxy.RunPreTestSetup();
4811 helper_proxy.AddData(data_proxy.get());
4813 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
4814 TestCompletionCallback callback_proxy;
4815 int rv = trans_proxy->Start(
4816 &request_proxy, callback_proxy.callback(), BoundNetLog());
4817 EXPECT_EQ(ERR_IO_PENDING, rv);
4818 rv = callback_proxy.WaitForResult();
4819 EXPECT_EQ(0, rv);
4821 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
4822 EXPECT_TRUE(response_proxy.headers.get() != NULL);
4823 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
4825 std::string response_data;
4826 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
4827 EXPECT_EQ("hello!", response_data);
4829 data.CompleteRead();
4830 helper_proxy.VerifyDataConsumed();
4833 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4834 // on a new connection, if the connection was previously known to be good.
4835 // This can happen when a server reboots without saying goodbye, or when
4836 // we're behind a NAT that masked the RST.
4837 TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
4838 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4839 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4840 MockRead reads[] = {
4841 CreateMockRead(*resp),
4842 CreateMockRead(*body),
4843 MockRead(ASYNC, ERR_IO_PENDING),
4844 MockRead(ASYNC, ERR_CONNECTION_RESET),
4847 MockRead reads2[] = {
4848 CreateMockRead(*resp),
4849 CreateMockRead(*body),
4850 MockRead(ASYNC, 0, 0) // EOF
4853 // This test has a couple of variants.
4854 enum {
4855 // Induce the RST while waiting for our transaction to send.
4856 VARIANT_RST_DURING_SEND_COMPLETION,
4857 // Induce the RST while waiting for our transaction to read.
4858 // In this case, the send completed - everything copied into the SNDBUF.
4859 VARIANT_RST_DURING_READ_COMPLETION
4862 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4863 variant <= VARIANT_RST_DURING_READ_COMPLETION;
4864 ++variant) {
4865 DelayedSocketData data1(1, reads, arraysize(reads), NULL, 0);
4867 DelayedSocketData data2(1, reads2, arraysize(reads2), NULL, 0);
4869 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4870 BoundNetLog(), GetParam(), NULL);
4871 helper.AddData(&data1);
4872 helper.AddData(&data2);
4873 helper.RunPreTestSetup();
4875 for (int i = 0; i < 2; ++i) {
4876 scoped_ptr<HttpNetworkTransaction> trans(
4877 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
4879 TestCompletionCallback callback;
4880 int rv = trans->Start(
4881 &helper.request(), callback.callback(), BoundNetLog());
4882 EXPECT_EQ(ERR_IO_PENDING, rv);
4883 // On the second transaction, we trigger the RST.
4884 if (i == 1) {
4885 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4886 // Writes to the socket complete asynchronously on SPDY by running
4887 // through the message loop. Complete the write here.
4888 base::RunLoop().RunUntilIdle();
4891 // Now schedule the ERR_CONNECTION_RESET.
4892 EXPECT_EQ(3u, data1.read_index());
4893 data1.CompleteRead();
4894 EXPECT_EQ(4u, data1.read_index());
4896 rv = callback.WaitForResult();
4897 EXPECT_EQ(OK, rv);
4899 const HttpResponseInfo* response = trans->GetResponseInfo();
4900 ASSERT_TRUE(response != NULL);
4901 EXPECT_TRUE(response->headers.get() != NULL);
4902 EXPECT_TRUE(response->was_fetched_via_spdy);
4903 std::string response_data;
4904 rv = ReadTransaction(trans.get(), &response_data);
4905 EXPECT_EQ(OK, rv);
4906 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4907 EXPECT_EQ("hello!", response_data);
4910 helper.VerifyDataConsumed();
4914 // Test that turning SPDY on and off works properly.
4915 TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
4916 HttpStreamFactory::set_spdy_enabled(true);
4917 scoped_ptr<SpdyFrame> req(
4918 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4919 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
4921 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4922 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4923 MockRead spdy_reads[] = {
4924 CreateMockRead(*resp),
4925 CreateMockRead(*body),
4926 MockRead(ASYNC, 0, 0) // EOF
4929 DelayedSocketData data(1, spdy_reads, arraysize(spdy_reads),
4930 spdy_writes, arraysize(spdy_writes));
4931 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4932 BoundNetLog(), GetParam(), NULL);
4933 helper.RunToCompletion(&data);
4934 TransactionHelperResult out = helper.output();
4935 EXPECT_EQ(OK, out.rv);
4936 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4937 EXPECT_EQ("hello!", out.response_data);
4939 net::HttpStreamFactory::set_spdy_enabled(false);
4940 MockRead http_reads[] = {
4941 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4942 MockRead("hello from http"),
4943 MockRead(SYNCHRONOUS, OK),
4945 DelayedSocketData data2(1, http_reads, arraysize(http_reads), NULL, 0);
4946 NormalSpdyTransactionHelper helper2(CreateGetRequest(), DEFAULT_PRIORITY,
4947 BoundNetLog(), GetParam(), NULL);
4948 helper2.SetSpdyDisabled();
4949 helper2.RunToCompletion(&data2);
4950 TransactionHelperResult out2 = helper2.output();
4951 EXPECT_EQ(OK, out2.rv);
4952 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
4953 EXPECT_EQ("hello from http", out2.response_data);
4955 net::HttpStreamFactory::set_spdy_enabled(true);
4958 // Tests that Basic authentication works over SPDY
4959 TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
4960 net::HttpStreamFactory::set_spdy_enabled(true);
4962 // The first request will be a bare GET, the second request will be a
4963 // GET with an Authorization header.
4964 scoped_ptr<SpdyFrame> req_get(
4965 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4966 const char* const kExtraAuthorizationHeaders[] = {
4967 "authorization", "Basic Zm9vOmJhcg=="
4969 scoped_ptr<SpdyFrame> req_get_authorization(
4970 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4971 arraysize(kExtraAuthorizationHeaders) / 2,
4972 false, 3, LOWEST, true));
4973 MockWrite spdy_writes[] = {
4974 CreateMockWrite(*req_get, 1),
4975 CreateMockWrite(*req_get_authorization, 4),
4978 // The first response is a 401 authentication challenge, and the second
4979 // response will be a 200 response since the second request includes a valid
4980 // Authorization header.
4981 const char* const kExtraAuthenticationHeaders[] = {
4982 "www-authenticate",
4983 "Basic realm=\"MyRealm\""
4985 scoped_ptr<SpdyFrame> resp_authentication(
4986 spdy_util_.ConstructSpdySynReplyError(
4987 "401 Authentication Required",
4988 kExtraAuthenticationHeaders,
4989 arraysize(kExtraAuthenticationHeaders) / 2,
4990 1));
4991 scoped_ptr<SpdyFrame> body_authentication(
4992 spdy_util_.ConstructSpdyBodyFrame(1, true));
4993 scoped_ptr<SpdyFrame> resp_data(
4994 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4995 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
4996 MockRead spdy_reads[] = {
4997 CreateMockRead(*resp_authentication, 2),
4998 CreateMockRead(*body_authentication, 3),
4999 CreateMockRead(*resp_data, 5),
5000 CreateMockRead(*body_data, 6),
5001 MockRead(ASYNC, 0, 7),
5004 OrderedSocketData data(spdy_reads, arraysize(spdy_reads),
5005 spdy_writes, arraysize(spdy_writes));
5006 HttpRequestInfo request(CreateGetRequest());
5007 BoundNetLog net_log;
5008 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5009 net_log, GetParam(), NULL);
5011 helper.RunPreTestSetup();
5012 helper.AddData(&data);
5013 HttpNetworkTransaction* trans = helper.trans();
5014 TestCompletionCallback callback;
5015 const int rv_start = trans->Start(&request, callback.callback(), net_log);
5016 EXPECT_EQ(ERR_IO_PENDING, rv_start);
5017 const int rv_start_complete = callback.WaitForResult();
5018 EXPECT_EQ(OK, rv_start_complete);
5020 // Make sure the response has an auth challenge.
5021 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
5022 ASSERT_TRUE(response_start != NULL);
5023 ASSERT_TRUE(response_start->headers.get() != NULL);
5024 EXPECT_EQ(401, response_start->headers->response_code());
5025 EXPECT_TRUE(response_start->was_fetched_via_spdy);
5026 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
5027 ASSERT_TRUE(auth_challenge != NULL);
5028 EXPECT_FALSE(auth_challenge->is_proxy);
5029 EXPECT_EQ("basic", auth_challenge->scheme);
5030 EXPECT_EQ("MyRealm", auth_challenge->realm);
5032 // Restart with a username/password.
5033 AuthCredentials credentials(base::ASCIIToUTF16("foo"),
5034 base::ASCIIToUTF16("bar"));
5035 TestCompletionCallback callback_restart;
5036 const int rv_restart = trans->RestartWithAuth(
5037 credentials, callback_restart.callback());
5038 EXPECT_EQ(ERR_IO_PENDING, rv_restart);
5039 const int rv_restart_complete = callback_restart.WaitForResult();
5040 EXPECT_EQ(OK, rv_restart_complete);
5041 // TODO(cbentzel): This is actually the same response object as before, but
5042 // data has changed.
5043 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
5044 ASSERT_TRUE(response_restart != NULL);
5045 ASSERT_TRUE(response_restart->headers.get() != NULL);
5046 EXPECT_EQ(200, response_restart->headers->response_code());
5047 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
5050 TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
5051 scoped_ptr<SpdyFrame> stream1_syn(
5052 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5053 scoped_ptr<SpdyFrame> stream1_body(
5054 spdy_util_.ConstructSpdyBodyFrame(1, true));
5055 MockWrite writes[] = {
5056 CreateMockWrite(*stream1_syn, 1),
5059 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5060 spdy_util_.AddUrlToHeaderBlock(
5061 "http://www.google.com/foo.dat", initial_headers.get());
5062 scoped_ptr<SpdyFrame> stream2_syn(
5063 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5065 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5066 (*late_headers)["hello"] = "bye";
5067 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5068 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5069 scoped_ptr<SpdyFrame> stream2_headers(
5070 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5071 false,
5073 LOWEST,
5074 HEADERS,
5075 CONTROL_FLAG_NONE,
5076 0));
5078 scoped_ptr<SpdyFrame>
5079 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5080 const char kPushedData[] = "pushed";
5081 scoped_ptr<SpdyFrame> stream2_body(
5082 spdy_util_.ConstructSpdyBodyFrame(
5083 2, kPushedData, strlen(kPushedData), true));
5084 MockRead reads[] = {
5085 CreateMockRead(*stream1_reply, 2),
5086 CreateMockRead(*stream2_syn, 3),
5087 CreateMockRead(*stream2_headers, 4),
5088 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5089 CreateMockRead(*stream2_body, 5),
5090 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5093 HttpResponseInfo response;
5094 HttpResponseInfo response2;
5095 std::string expected_push_result("pushed");
5096 OrderedSocketData data(reads, arraysize(reads),
5097 writes, arraysize(writes));
5098 RunServerPushTest(&data,
5099 &response,
5100 &response2,
5101 expected_push_result);
5103 // Verify the SYN_REPLY.
5104 EXPECT_TRUE(response.headers.get() != NULL);
5105 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5107 // Verify the pushed stream.
5108 EXPECT_TRUE(response2.headers.get() != NULL);
5109 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5112 TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
5113 // We push a stream and attempt to claim it before the headers come down.
5114 scoped_ptr<SpdyFrame> stream1_syn(
5115 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5116 scoped_ptr<SpdyFrame> stream1_body(
5117 spdy_util_.ConstructSpdyBodyFrame(1, true));
5118 MockWrite writes[] = {
5119 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5122 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5123 spdy_util_.AddUrlToHeaderBlock(
5124 "http://www.google.com/foo.dat", initial_headers.get());
5125 scoped_ptr<SpdyFrame> stream2_syn(
5126 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5128 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5129 (*late_headers)["hello"] = "bye";
5130 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5131 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5132 scoped_ptr<SpdyFrame> stream2_headers(
5133 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5134 false,
5136 LOWEST,
5137 HEADERS,
5138 CONTROL_FLAG_NONE,
5139 0));
5141 scoped_ptr<SpdyFrame>
5142 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5143 const char kPushedData[] = "pushed";
5144 scoped_ptr<SpdyFrame> stream2_body(
5145 spdy_util_.ConstructSpdyBodyFrame(
5146 2, kPushedData, strlen(kPushedData), true));
5147 MockRead reads[] = {
5148 CreateMockRead(*stream1_reply, 1),
5149 CreateMockRead(*stream2_syn, 2),
5150 CreateMockRead(*stream1_body, 3),
5151 CreateMockRead(*stream2_headers, 4),
5152 CreateMockRead(*stream2_body, 5),
5153 MockRead(ASYNC, 0, 6), // EOF
5156 HttpResponseInfo response;
5157 HttpResponseInfo response2;
5158 std::string expected_push_result("pushed");
5159 DeterministicSocketData data(reads, arraysize(reads),
5160 writes, arraysize(writes));
5162 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5163 BoundNetLog(), GetParam(), NULL);
5164 helper.SetDeterministic();
5165 helper.AddDeterministicData(&data);
5166 helper.RunPreTestSetup();
5168 HttpNetworkTransaction* trans = helper.trans();
5170 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5171 // and the body of the primary stream, but before we've received the HEADERS
5172 // for the pushed stream.
5173 data.SetStop(3);
5175 // Start the transaction.
5176 TestCompletionCallback callback;
5177 int rv = trans->Start(
5178 &CreateGetRequest(), callback.callback(), BoundNetLog());
5179 EXPECT_EQ(ERR_IO_PENDING, rv);
5180 data.Run();
5181 rv = callback.WaitForResult();
5182 EXPECT_EQ(0, rv);
5184 // Request the pushed path. At this point, we've received the push, but the
5185 // headers are not yet complete.
5186 scoped_ptr<HttpNetworkTransaction> trans2(
5187 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5188 rv = trans2->Start(
5189 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5190 EXPECT_EQ(ERR_IO_PENDING, rv);
5191 data.RunFor(3);
5192 base::RunLoop().RunUntilIdle();
5194 // Read the server push body.
5195 std::string result2;
5196 ReadResult(trans2.get(), &data, &result2);
5197 // Read the response body.
5198 std::string result;
5199 ReadResult(trans, &data, &result);
5201 // Verify that the received push data is same as the expected push data.
5202 EXPECT_EQ(result2.compare(expected_push_result), 0)
5203 << "Received data: "
5204 << result2
5205 << "||||| Expected data: "
5206 << expected_push_result;
5208 // Verify the SYN_REPLY.
5209 // Copy the response info, because trans goes away.
5210 response = *trans->GetResponseInfo();
5211 response2 = *trans2->GetResponseInfo();
5213 VerifyStreamsClosed(helper);
5215 // Verify the SYN_REPLY.
5216 EXPECT_TRUE(response.headers.get() != NULL);
5217 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5219 // Verify the pushed stream.
5220 EXPECT_TRUE(response2.headers.get() != NULL);
5221 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5223 // Read the final EOF (which will close the session)
5224 data.RunFor(1);
5226 // Verify that we consumed all test data.
5227 EXPECT_TRUE(data.at_read_eof());
5228 EXPECT_TRUE(data.at_write_eof());
5231 // TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
5232 TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
5233 // We push a stream and attempt to claim it before the headers come down.
5234 scoped_ptr<SpdyFrame> stream1_syn(
5235 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5236 scoped_ptr<SpdyFrame> stream1_body(
5237 spdy_util_.ConstructSpdyBodyFrame(1, true));
5238 MockWrite writes[] = {
5239 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5242 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5243 if (spdy_util_.spdy_version() < SPDY4) {
5244 // In SPDY4 PUSH_PROMISE headers won't show up in the response headers.
5245 (*initial_headers)["alpha"] = "beta";
5247 spdy_util_.AddUrlToHeaderBlock(
5248 "http://www.google.com/foo.dat", initial_headers.get());
5249 scoped_ptr<SpdyFrame> stream2_syn(
5250 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5252 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5253 (*middle_headers)["hello"] = "bye";
5254 scoped_ptr<SpdyFrame> stream2_headers1(
5255 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5256 false,
5258 LOWEST,
5259 HEADERS,
5260 CONTROL_FLAG_NONE,
5261 0));
5263 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5264 (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5265 if (spdy_util_.spdy_version() < SPDY4) {
5266 // SPDY4/HTTP2 eliminates use of the :version header.
5267 (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5269 scoped_ptr<SpdyFrame> stream2_headers2(
5270 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5271 false,
5273 LOWEST,
5274 HEADERS,
5275 CONTROL_FLAG_NONE,
5276 0));
5278 scoped_ptr<SpdyFrame>
5279 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5280 const char kPushedData[] = "pushed";
5281 scoped_ptr<SpdyFrame> stream2_body(
5282 spdy_util_.ConstructSpdyBodyFrame(
5283 2, kPushedData, strlen(kPushedData), true));
5284 MockRead reads[] = {
5285 CreateMockRead(*stream1_reply, 1),
5286 CreateMockRead(*stream2_syn, 2),
5287 CreateMockRead(*stream1_body, 3),
5288 CreateMockRead(*stream2_headers1, 4),
5289 CreateMockRead(*stream2_headers2, 5),
5290 CreateMockRead(*stream2_body, 6),
5291 MockRead(ASYNC, 0, 7), // EOF
5294 HttpResponseInfo response;
5295 HttpResponseInfo response2;
5296 std::string expected_push_result("pushed");
5297 DeterministicSocketData data(reads, arraysize(reads),
5298 writes, arraysize(writes));
5300 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5301 BoundNetLog(), GetParam(), NULL);
5302 helper.SetDeterministic();
5303 helper.AddDeterministicData(&data);
5304 helper.RunPreTestSetup();
5306 HttpNetworkTransaction* trans = helper.trans();
5308 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5309 // the first HEADERS frame, and the body of the primary stream, but before
5310 // we've received the final HEADERS for the pushed stream.
5311 data.SetStop(4);
5313 // Start the transaction.
5314 TestCompletionCallback callback;
5315 int rv = trans->Start(
5316 &CreateGetRequest(), callback.callback(), BoundNetLog());
5317 EXPECT_EQ(ERR_IO_PENDING, rv);
5318 data.Run();
5319 rv = callback.WaitForResult();
5320 EXPECT_EQ(0, rv);
5322 // Request the pushed path. At this point, we've received the push, but the
5323 // headers are not yet complete.
5324 scoped_ptr<HttpNetworkTransaction> trans2(
5325 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5326 rv = trans2->Start(
5327 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5328 EXPECT_EQ(ERR_IO_PENDING, rv);
5329 data.RunFor(3);
5330 base::RunLoop().RunUntilIdle();
5332 // Read the server push body.
5333 std::string result2;
5334 ReadResult(trans2.get(), &data, &result2);
5335 // Read the response body.
5336 std::string result;
5337 ReadResult(trans, &data, &result);
5339 // Verify that the received push data is same as the expected push data.
5340 EXPECT_EQ(expected_push_result, result2);
5342 // Verify the SYN_REPLY.
5343 // Copy the response info, because trans goes away.
5344 response = *trans->GetResponseInfo();
5345 response2 = *trans2->GetResponseInfo();
5347 VerifyStreamsClosed(helper);
5349 // Verify the SYN_REPLY.
5350 EXPECT_TRUE(response.headers.get() != NULL);
5351 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5353 // Verify the pushed stream.
5354 EXPECT_TRUE(response2.headers.get() != NULL);
5355 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5357 // Verify we got all the headers from all header blocks.
5358 if (spdy_util_.spdy_version() < SPDY4)
5359 EXPECT_TRUE(response2.headers->HasHeaderValue("alpha", "beta"));
5360 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5361 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
5363 // Read the final EOF (which will close the session)
5364 data.RunFor(1);
5366 // Verify that we consumed all test data.
5367 EXPECT_TRUE(data.at_read_eof());
5368 EXPECT_TRUE(data.at_write_eof());
5371 TEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
5372 // We push a stream and attempt to claim it before the headers come down.
5373 scoped_ptr<SpdyFrame> stream1_syn(
5374 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5375 scoped_ptr<SpdyFrame> stream1_body(
5376 spdy_util_.ConstructSpdyBodyFrame(1, true));
5377 MockWrite writes[] = {
5378 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5381 scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5382 spdy_util_.AddUrlToHeaderBlock(
5383 "http://www.google.com/foo.dat", initial_headers.get());
5384 scoped_ptr<SpdyFrame> stream2_syn(
5385 spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5387 scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5388 (*middle_headers)["hello"] = "bye";
5389 scoped_ptr<SpdyFrame> stream2_headers1(
5390 spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5391 false,
5393 LOWEST,
5394 HEADERS,
5395 CONTROL_FLAG_NONE,
5396 0));
5398 scoped_ptr<SpdyFrame>
5399 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5400 const char kPushedData[] = "pushed";
5401 scoped_ptr<SpdyFrame> stream2_body(
5402 spdy_util_.ConstructSpdyBodyFrame(
5403 2, kPushedData, strlen(kPushedData), true));
5404 MockRead reads[] = {
5405 CreateMockRead(*stream1_reply, 1),
5406 CreateMockRead(*stream2_syn, 2),
5407 CreateMockRead(*stream1_body, 3),
5408 CreateMockRead(*stream2_headers1, 4),
5409 CreateMockRead(*stream2_body, 5),
5410 MockRead(ASYNC, 0, 6), // EOF
5413 DeterministicSocketData data(reads, arraysize(reads),
5414 writes, arraysize(writes));
5416 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5417 BoundNetLog(), GetParam(), NULL);
5418 helper.SetDeterministic();
5419 helper.AddDeterministicData(&data);
5420 helper.RunPreTestSetup();
5422 HttpNetworkTransaction* trans = helper.trans();
5424 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5425 // the first HEADERS frame, and the body of the primary stream, but before
5426 // we've received the final HEADERS for the pushed stream.
5427 data.SetStop(4);
5429 // Start the transaction.
5430 TestCompletionCallback callback;
5431 int rv = trans->Start(
5432 &CreateGetRequest(), callback.callback(), BoundNetLog());
5433 EXPECT_EQ(ERR_IO_PENDING, rv);
5434 data.Run();
5435 rv = callback.WaitForResult();
5436 EXPECT_EQ(0, rv);
5438 // Request the pushed path. At this point, we've received the push, but the
5439 // headers are not yet complete.
5440 scoped_ptr<HttpNetworkTransaction> trans2(
5441 new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5442 rv = trans2->Start(
5443 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5444 EXPECT_EQ(ERR_IO_PENDING, rv);
5445 data.RunFor(2);
5446 base::RunLoop().RunUntilIdle();
5448 // Read the server push body.
5449 std::string result2;
5450 ReadResult(trans2.get(), &data, &result2);
5451 // Read the response body.
5452 std::string result;
5453 ReadResult(trans, &data, &result);
5454 EXPECT_EQ("hello!", result);
5456 // Verify that we haven't received any push data.
5457 EXPECT_EQ("", result2);
5459 // Verify the SYN_REPLY.
5460 // Copy the response info, because trans goes away.
5461 HttpResponseInfo response = *trans->GetResponseInfo();
5462 ASSERT_TRUE(trans2->GetResponseInfo() == NULL);
5464 VerifyStreamsClosed(helper);
5466 // Verify the SYN_REPLY.
5467 EXPECT_TRUE(response.headers.get() != NULL);
5468 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5470 // Read the final EOF (which will close the session).
5471 data.RunFor(1);
5473 // Verify that we consumed all test data.
5474 EXPECT_TRUE(data.at_read_eof());
5475 EXPECT_TRUE(data.at_write_eof());
5478 TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
5479 scoped_ptr<SpdyFrame> req(
5480 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5481 scoped_ptr<SpdyFrame> rst(
5482 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5483 MockWrite writes[] = {
5484 CreateMockWrite(*req), CreateMockWrite(*rst),
5487 scoped_ptr<SpdyFrame> stream1_reply(
5488 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5490 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5491 (*late_headers)["hello"] = "bye";
5492 scoped_ptr<SpdyFrame> stream1_headers(
5493 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5494 false,
5496 LOWEST,
5497 HEADERS,
5498 CONTROL_FLAG_NONE,
5499 0));
5500 scoped_ptr<SpdyFrame> stream1_body(
5501 spdy_util_.ConstructSpdyBodyFrame(1, true));
5502 MockRead reads[] = {
5503 CreateMockRead(*stream1_reply),
5504 CreateMockRead(*stream1_headers),
5505 CreateMockRead(*stream1_body),
5506 MockRead(ASYNC, 0, 0) // EOF
5509 DelayedSocketData data(1, reads, arraysize(reads),
5510 writes, arraysize(writes));
5511 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5512 BoundNetLog(), GetParam(), NULL);
5513 helper.RunToCompletion(&data);
5514 TransactionHelperResult out = helper.output();
5515 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5518 TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
5519 scoped_ptr<SpdyFrame> req(
5520 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5521 scoped_ptr<SpdyFrame> rst(
5522 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5523 MockWrite writes[] = {
5524 CreateMockWrite(*req),
5525 CreateMockWrite(*rst),
5528 scoped_ptr<SpdyFrame> stream1_reply(
5529 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5531 scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5532 (*late_headers)["hello"] = "bye";
5533 scoped_ptr<SpdyFrame> stream1_headers(
5534 spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5535 false,
5537 LOWEST,
5538 HEADERS,
5539 CONTROL_FLAG_NONE,
5540 0));
5541 scoped_ptr<SpdyFrame> stream1_body(
5542 spdy_util_.ConstructSpdyBodyFrame(1, false));
5543 scoped_ptr<SpdyFrame> stream1_body2(
5544 spdy_util_.ConstructSpdyBodyFrame(1, true));
5545 MockRead reads[] = {
5546 CreateMockRead(*stream1_reply),
5547 CreateMockRead(*stream1_body),
5548 CreateMockRead(*stream1_headers),
5549 CreateMockRead(*stream1_body2),
5550 MockRead(ASYNC, 0, 0) // EOF
5553 DelayedSocketData data(1, reads, arraysize(reads),
5554 writes, arraysize(writes));
5555 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5556 BoundNetLog(), GetParam(), NULL);
5557 helper.RunToCompletion(&data);
5558 TransactionHelperResult out = helper.output();
5559 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5562 TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
5563 // In this test we want to verify that we can't accidentally push content
5564 // which can't be pushed by this content server.
5565 // This test assumes that:
5566 // - if we're requesting http://www.foo.com/barbaz
5567 // - the browser has made a connection to "www.foo.com".
5569 // A list of the URL to fetch, followed by the URL being pushed.
5570 static const char* const kTestCases[] = {
5571 "http://www.google.com/foo.html",
5572 "http://www.google.com:81/foo.js", // Bad port
5574 "http://www.google.com/foo.html",
5575 "https://www.google.com/foo.js", // Bad protocol
5577 "http://www.google.com/foo.html",
5578 "ftp://www.google.com/foo.js", // Invalid Protocol
5580 "http://www.google.com/foo.html",
5581 "http://blat.www.google.com/foo.js", // Cross subdomain
5583 "http://www.google.com/foo.html",
5584 "http://www.foo.com/foo.js", // Cross domain
5587 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
5588 const char* url_to_fetch = kTestCases[index];
5589 const char* url_to_push = kTestCases[index + 1];
5591 scoped_ptr<SpdyFrame> stream1_syn(
5592 spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
5593 scoped_ptr<SpdyFrame> stream1_body(
5594 spdy_util_.ConstructSpdyBodyFrame(1, true));
5595 scoped_ptr<SpdyFrame> push_rst(
5596 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
5597 MockWrite writes[] = {
5598 CreateMockWrite(*stream1_syn, 1),
5599 CreateMockWrite(*push_rst, 4),
5602 scoped_ptr<SpdyFrame>
5603 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5604 scoped_ptr<SpdyFrame>
5605 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
5609 url_to_push));
5610 const char kPushedData[] = "pushed";
5611 scoped_ptr<SpdyFrame> stream2_body(
5612 spdy_util_.ConstructSpdyBodyFrame(
5613 2, kPushedData, strlen(kPushedData), true));
5614 scoped_ptr<SpdyFrame> rst(
5615 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
5617 MockRead reads[] = {
5618 CreateMockRead(*stream1_reply, 2),
5619 CreateMockRead(*stream2_syn, 3),
5620 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5621 CreateMockRead(*stream2_body, 6),
5622 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5625 HttpResponseInfo response;
5626 OrderedSocketData data(reads, arraysize(reads),
5627 writes, arraysize(writes));
5629 HttpRequestInfo request;
5630 request.method = "GET";
5631 request.url = GURL(url_to_fetch);
5632 request.load_flags = 0;
5634 // Enable cross-origin push. Since we are not using a proxy, this should
5635 // not actually enable cross-origin SPDY push.
5636 scoped_ptr<SpdySessionDependencies> session_deps(
5637 CreateSpdySessionDependencies(GetParam()));
5638 session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
5639 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5640 BoundNetLog(), GetParam(),
5641 session_deps.release());
5642 helper.RunPreTestSetup();
5643 helper.AddData(&data);
5645 HttpNetworkTransaction* trans = helper.trans();
5647 // Start the transaction with basic parameters.
5648 TestCompletionCallback callback;
5650 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5651 EXPECT_EQ(ERR_IO_PENDING, rv);
5652 rv = callback.WaitForResult();
5654 // Read the response body.
5655 std::string result;
5656 ReadResult(trans, &data, &result);
5658 // Verify that we consumed all test data.
5659 EXPECT_TRUE(data.at_read_eof());
5660 EXPECT_TRUE(data.at_write_eof());
5662 // Verify the SYN_REPLY.
5663 // Copy the response info, because trans goes away.
5664 response = *trans->GetResponseInfo();
5666 VerifyStreamsClosed(helper);
5668 // Verify the SYN_REPLY.
5669 EXPECT_TRUE(response.headers.get() != NULL);
5670 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5674 TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
5675 // Construct the request.
5676 scoped_ptr<SpdyFrame> req(
5677 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5678 scoped_ptr<SpdyFrame> req2(
5679 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
5680 MockWrite writes[] = {
5681 CreateMockWrite(*req, 1),
5682 CreateMockWrite(*req2, 3),
5685 scoped_ptr<SpdyFrame> refused(
5686 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
5687 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5688 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true));
5689 MockRead reads[] = {
5690 CreateMockRead(*refused, 2),
5691 CreateMockRead(*resp, 4),
5692 CreateMockRead(*body, 5),
5693 MockRead(ASYNC, 0, 6) // EOF
5696 OrderedSocketData data(reads, arraysize(reads),
5697 writes, arraysize(writes));
5698 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5699 BoundNetLog(), GetParam(), NULL);
5701 helper.RunPreTestSetup();
5702 helper.AddData(&data);
5704 HttpNetworkTransaction* trans = helper.trans();
5706 // Start the transaction with basic parameters.
5707 TestCompletionCallback callback;
5708 int rv = trans->Start(
5709 &CreateGetRequest(), callback.callback(), BoundNetLog());
5710 EXPECT_EQ(ERR_IO_PENDING, rv);
5711 rv = callback.WaitForResult();
5712 EXPECT_EQ(OK, rv);
5714 // Verify that we consumed all test data.
5715 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
5716 << data.read_count()
5717 << " Read index: "
5718 << data.read_index();
5719 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
5720 << data.write_count()
5721 << " Write index: "
5722 << data.write_index();
5724 // Verify the SYN_REPLY.
5725 HttpResponseInfo response = *trans->GetResponseInfo();
5726 EXPECT_TRUE(response.headers.get() != NULL);
5727 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5730 TEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) {
5731 // This first request will start to establish the SpdySession.
5732 // Then we will start the second (MEDIUM priority) and then third
5733 // (HIGHEST priority) request in such a way that the third will actually
5734 // start before the second, causing the second to be numbered differently
5735 // than the order they were created.
5736 scoped_ptr<SpdyFrame> req1(
5737 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5738 scoped_ptr<SpdyFrame> req2(
5739 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true));
5740 scoped_ptr<SpdyFrame> req3(
5741 spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true));
5742 MockWrite writes[] = {
5743 CreateMockWrite(*req1, 0),
5744 CreateMockWrite(*req2, 3),
5745 CreateMockWrite(*req3, 4),
5748 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5749 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
5750 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5751 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
5752 scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
5753 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
5754 MockRead reads[] = {
5755 CreateMockRead(*resp1, 1),
5756 CreateMockRead(*body1, 2),
5757 CreateMockRead(*resp2, 5),
5758 CreateMockRead(*body2, 6),
5759 CreateMockRead(*resp3, 7),
5760 CreateMockRead(*body3, 8),
5761 MockRead(ASYNC, 0, 9) // EOF
5764 DeterministicSocketData data(reads, arraysize(reads),
5765 writes, arraysize(writes));
5766 NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
5767 BoundNetLog(), GetParam(), NULL);
5768 helper.SetDeterministic();
5769 helper.RunPreTestSetup();
5770 helper.AddDeterministicData(&data);
5772 // Start the first transaction to set up the SpdySession
5773 HttpNetworkTransaction* trans = helper.trans();
5774 TestCompletionCallback callback;
5775 HttpRequestInfo info1 = CreateGetRequest();
5776 int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
5777 EXPECT_EQ(ERR_IO_PENDING, rv);
5779 // Run the message loop, but do not allow the write to complete.
5780 // This leaves the SpdySession with a write pending, which prevents
5781 // SpdySession from attempting subsequent writes until this write completes.
5782 base::RunLoop().RunUntilIdle();
5784 // Now, start both new transactions
5785 HttpRequestInfo info2 = CreateGetRequest();
5786 TestCompletionCallback callback2;
5787 scoped_ptr<HttpNetworkTransaction> trans2(
5788 new HttpNetworkTransaction(MEDIUM, helper.session().get()));
5789 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog());
5790 EXPECT_EQ(ERR_IO_PENDING, rv);
5791 base::RunLoop().RunUntilIdle();
5793 HttpRequestInfo info3 = CreateGetRequest();
5794 TestCompletionCallback callback3;
5795 scoped_ptr<HttpNetworkTransaction> trans3(
5796 new HttpNetworkTransaction(HIGHEST, helper.session().get()));
5797 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog());
5798 EXPECT_EQ(ERR_IO_PENDING, rv);
5799 base::RunLoop().RunUntilIdle();
5801 // We now have two SYN_STREAM frames queued up which will be
5802 // dequeued only once the first write completes, which we
5803 // now allow to happen.
5804 data.RunFor(2);
5805 EXPECT_EQ(OK, callback.WaitForResult());
5807 // And now we can allow everything else to run to completion.
5808 data.SetStop(10);
5809 data.Run();
5810 EXPECT_EQ(OK, callback2.WaitForResult());
5811 EXPECT_EQ(OK, callback3.WaitForResult());
5813 helper.VerifyDataConsumed();
5816 // The tests below are only for SPDY/3 and above.
5818 // Test that sent data frames and received WINDOW_UPDATE frames change
5819 // the send_window_size_ correctly.
5821 // WINDOW_UPDATE is different than most other frames in that it can arrive
5822 // while the client is still sending the request body. In order to enforce
5823 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
5824 // socket data provider, so that initial read that is done as soon as the
5825 // stream is created, succeeds and schedules another read. This way reads
5826 // and writes are interleaved; after doing a full frame write, SpdyStream
5827 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
5828 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5829 // since request has not been completely written, therefore we feed
5830 // enough number of WINDOW_UPDATEs to finish the first read and cause a
5831 // write, leading to a complete write of request body; after that we send
5832 // a reply with a body, to cause a graceful shutdown.
5834 // TODO(agayev): develop a socket data provider where both, reads and
5835 // writes are ordered so that writing tests like these are easy and rewrite
5836 // all these tests using it. Right now we are working around the
5837 // limitations as described above and it's not deterministic, tests may
5838 // fail under specific circumstances.
5839 TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
5840 static int kFrameCount = 2;
5841 scoped_ptr<std::string> content(
5842 new std::string(kMaxSpdyFrameChunkSize, 'a'));
5843 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
5844 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
5845 scoped_ptr<SpdyFrame> body(
5846 spdy_util_.ConstructSpdyBodyFrame(
5847 1, content->c_str(), content->size(), false));
5848 scoped_ptr<SpdyFrame> body_end(
5849 spdy_util_.ConstructSpdyBodyFrame(
5850 1, content->c_str(), content->size(), true));
5852 MockWrite writes[] = {
5853 CreateMockWrite(*req, 0),
5854 CreateMockWrite(*body, 1),
5855 CreateMockWrite(*body_end, 2),
5858 static const int32 kDeltaWindowSize = 0xff;
5859 static const int kDeltaCount = 4;
5860 scoped_ptr<SpdyFrame> window_update(
5861 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5862 scoped_ptr<SpdyFrame> window_update_dummy(
5863 spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
5864 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
5865 MockRead reads[] = {
5866 CreateMockRead(*window_update_dummy, 3),
5867 CreateMockRead(*window_update_dummy, 4),
5868 CreateMockRead(*window_update_dummy, 5),
5869 CreateMockRead(*window_update, 6), // Four updates, therefore window
5870 CreateMockRead(*window_update, 7), // size should increase by
5871 CreateMockRead(*window_update, 8), // kDeltaWindowSize * 4
5872 CreateMockRead(*window_update, 9),
5873 CreateMockRead(*resp, 10),
5874 CreateMockRead(*body_end, 11),
5875 MockRead(ASYNC, 0, 0, 12) // EOF
5878 DeterministicSocketData data(reads, arraysize(reads),
5879 writes, arraysize(writes));
5881 ScopedVector<UploadElementReader> element_readers;
5882 for (int i = 0; i < kFrameCount; ++i) {
5883 element_readers.push_back(
5884 new UploadBytesElementReader(content->c_str(), content->size()));
5886 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
5888 // Setup the request
5889 HttpRequestInfo request;
5890 request.method = "POST";
5891 request.url = GURL(kDefaultURL);
5892 request.upload_data_stream = &upload_data_stream;
5894 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5895 BoundNetLog(), GetParam(), NULL);
5896 helper.SetDeterministic();
5897 helper.AddDeterministicData(&data);
5898 helper.RunPreTestSetup();
5900 HttpNetworkTransaction* trans = helper.trans();
5902 TestCompletionCallback callback;
5903 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5905 EXPECT_EQ(ERR_IO_PENDING, rv);
5907 data.RunFor(11);
5909 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
5910 ASSERT_TRUE(stream != NULL);
5911 ASSERT_TRUE(stream->stream() != NULL);
5912 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize) +
5913 kDeltaWindowSize * kDeltaCount -
5914 kMaxSpdyFrameChunkSize * kFrameCount,
5915 stream->stream()->send_window_size());
5917 data.RunFor(1);
5919 rv = callback.WaitForResult();
5920 EXPECT_EQ(OK, rv);
5922 helper.VerifyDataConsumed();
5925 // Test that received data frames and sent WINDOW_UPDATE frames change
5926 // the recv_window_size_ correctly.
5927 TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
5928 // Amount of body required to trigger a sent window update.
5929 const size_t kTargetSize = kSpdyStreamInitialWindowSize / 2 + 1;
5931 scoped_ptr<SpdyFrame> req(
5932 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5933 scoped_ptr<SpdyFrame> session_window_update(
5934 spdy_util_.ConstructSpdyWindowUpdate(0, kTargetSize));
5935 scoped_ptr<SpdyFrame> window_update(
5936 spdy_util_.ConstructSpdyWindowUpdate(1, kTargetSize));
5938 std::vector<MockWrite> writes;
5939 writes.push_back(CreateMockWrite(*req));
5940 if (GetParam().protocol >= kProtoSPDY31)
5941 writes.push_back(CreateMockWrite(*session_window_update));
5942 writes.push_back(CreateMockWrite(*window_update));
5944 std::vector<MockRead> reads;
5945 scoped_ptr<SpdyFrame> resp(
5946 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5947 reads.push_back(CreateMockRead(*resp));
5949 ScopedVector<SpdyFrame> body_frames;
5950 const std::string body_data(4096, 'x');
5951 for (size_t remaining = kTargetSize; remaining != 0;) {
5952 size_t frame_size = std::min(remaining, body_data.size());
5953 body_frames.push_back(spdy_util_.ConstructSpdyBodyFrame(
5954 1, body_data.data(), frame_size, false));
5955 reads.push_back(CreateMockRead(*body_frames.back()));
5956 remaining -= frame_size;
5958 reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 0)); // Yield.
5960 DelayedSocketData data(1, vector_as_array(&reads), reads.size(),
5961 vector_as_array(&writes), writes.size());
5963 NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5964 BoundNetLog(), GetParam(), NULL);
5965 helper.AddData(&data);
5966 helper.RunPreTestSetup();
5967 HttpNetworkTransaction* trans = helper.trans();
5969 TestCompletionCallback callback;
5970 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5972 EXPECT_EQ(ERR_IO_PENDING, rv);
5973 rv = callback.WaitForResult();
5974 EXPECT_EQ(OK, rv);
5976 SpdyHttpStream* stream =
5977 static_cast<SpdyHttpStream*>(trans->stream_.get());
5978 ASSERT_TRUE(stream != NULL);
5979 ASSERT_TRUE(stream->stream() != NULL);
5981 // All data has been read, but not consumed. The window reflects this.
5982 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize - kTargetSize),
5983 stream->stream()->recv_window_size());
5985 const HttpResponseInfo* response = trans->GetResponseInfo();
5986 ASSERT_TRUE(response != NULL);
5987 ASSERT_TRUE(response->headers.get() != NULL);
5988 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5989 EXPECT_TRUE(response->was_fetched_via_spdy);
5991 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
5992 // size increased to default.
5993 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kTargetSize));
5994 EXPECT_EQ(static_cast<int>(kTargetSize),
5995 trans->Read(buf.get(), kTargetSize, CompletionCallback()));
5996 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize),
5997 stream->stream()->recv_window_size());
5998 EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x')));
6000 // Allow scheduled WINDOW_UPDATE frames to write.
6001 base::RunLoop().RunUntilIdle();
6002 helper.VerifyDataConsumed();
6005 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6006 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
6007 // Number of full frames we hope to write (but will not, used to
6008 // set content-length header correctly)
6009 static int kFrameCount = 3;
6011 scoped_ptr<std::string> content(
6012 new std::string(kMaxSpdyFrameChunkSize, 'a'));
6013 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6014 kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
6015 scoped_ptr<SpdyFrame> body(
6016 spdy_util_.ConstructSpdyBodyFrame(
6017 1, content->c_str(), content->size(), false));
6018 scoped_ptr<SpdyFrame> rst(
6019 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
6021 // We're not going to write a data frame with FIN, we'll receive a bad
6022 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6023 MockWrite writes[] = {
6024 CreateMockWrite(*req, 0),
6025 CreateMockWrite(*body, 2),
6026 CreateMockWrite(*rst, 3),
6029 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow
6030 scoped_ptr<SpdyFrame> window_update(
6031 spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
6032 MockRead reads[] = {
6033 CreateMockRead(*window_update, 1),
6034 MockRead(ASYNC, 0, 4) // EOF
6037 DeterministicSocketData data(reads, arraysize(reads),
6038 writes, arraysize(writes));
6040 ScopedVector<UploadElementReader> element_readers;
6041 for (int i = 0; i < kFrameCount; ++i) {
6042 element_readers.push_back(
6043 new UploadBytesElementReader(content->c_str(), content->size()));
6045 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6047 // Setup the request
6048 HttpRequestInfo request;
6049 request.method = "POST";
6050 request.url = GURL("http://www.google.com/");
6051 request.upload_data_stream = &upload_data_stream;
6053 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6054 BoundNetLog(), GetParam(), NULL);
6055 helper.SetDeterministic();
6056 helper.RunPreTestSetup();
6057 helper.AddDeterministicData(&data);
6058 HttpNetworkTransaction* trans = helper.trans();
6060 TestCompletionCallback callback;
6061 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6062 ASSERT_EQ(ERR_IO_PENDING, rv);
6064 data.RunFor(5);
6065 ASSERT_TRUE(callback.have_result());
6066 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
6067 helper.VerifyDataConsumed();
6070 // Test that after hitting a send window size of 0, the write process
6071 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
6073 // This test constructs a POST request followed by enough data frames
6074 // containing 'a' that would make the window size 0, followed by another
6075 // data frame containing default content (which is "hello!") and this frame
6076 // also contains a FIN flag. DelayedSocketData is used to enforce all
6077 // writes go through before a read could happen. However, the last frame
6078 // ("hello!") is not supposed to go through since by the time its turn
6079 // arrives, window size is 0. At this point MessageLoop::Run() called via
6080 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
6081 // which returns after performing all possible writes. We use DCHECKS to
6082 // ensure that last data frame is still there and stream has stalled.
6083 // After that, next read is artifically enforced, which causes a
6084 // WINDOW_UPDATE to be read and I/O process resumes.
6085 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
6086 // Number of frames we need to send to zero out the window size: data
6087 // frames plus SYN_STREAM plus the last data frame; also we need another
6088 // data frame that we will send once the WINDOW_UPDATE is received,
6089 // therefore +3.
6090 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
6092 // Calculate last frame's size; 0 size data frame is legal.
6093 size_t last_frame_size =
6094 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6096 // Construct content for a data frame of maximum size.
6097 std::string content(kMaxSpdyFrameChunkSize, 'a');
6099 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6100 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6101 LOWEST, NULL, 0));
6103 // Full frames.
6104 scoped_ptr<SpdyFrame> body1(
6105 spdy_util_.ConstructSpdyBodyFrame(
6106 1, content.c_str(), content.size(), false));
6108 // Last frame to zero out the window size.
6109 scoped_ptr<SpdyFrame> body2(
6110 spdy_util_.ConstructSpdyBodyFrame(
6111 1, content.c_str(), last_frame_size, false));
6113 // Data frame to be sent once WINDOW_UPDATE frame is received.
6114 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6116 // Fill in mock writes.
6117 scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
6118 size_t i = 0;
6119 writes[i] = CreateMockWrite(*req);
6120 for (i = 1; i < num_writes - 2; i++)
6121 writes[i] = CreateMockWrite(*body1);
6122 writes[i++] = CreateMockWrite(*body2);
6123 writes[i] = CreateMockWrite(*body3);
6125 // Construct read frame, give enough space to upload the rest of the
6126 // data.
6127 scoped_ptr<SpdyFrame> session_window_update(
6128 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6129 scoped_ptr<SpdyFrame> window_update(
6130 spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
6131 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6132 MockRead reads[] = {
6133 CreateMockRead(*session_window_update),
6134 CreateMockRead(*session_window_update),
6135 CreateMockRead(*window_update),
6136 CreateMockRead(*window_update),
6137 CreateMockRead(*reply),
6138 CreateMockRead(*body2),
6139 CreateMockRead(*body3),
6140 MockRead(ASYNC, 0, 0) // EOF
6143 // Skip the session window updates unless we're using SPDY/3.1 and
6144 // above.
6145 size_t read_offset = (GetParam().protocol >= kProtoSPDY31) ? 0 : 2;
6146 size_t num_reads = arraysize(reads) - read_offset;
6148 // Force all writes to happen before any read, last write will not
6149 // actually queue a frame, due to window size being 0.
6150 DelayedSocketData data(num_writes, reads + read_offset, num_reads,
6151 writes.get(), num_writes);
6153 ScopedVector<UploadElementReader> element_readers;
6154 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6155 upload_data_string.append(kUploadData, kUploadDataSize);
6156 element_readers.push_back(new UploadBytesElementReader(
6157 upload_data_string.c_str(), upload_data_string.size()));
6158 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6160 HttpRequestInfo request;
6161 request.method = "POST";
6162 request.url = GURL("http://www.google.com/");
6163 request.upload_data_stream = &upload_data_stream;
6164 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6165 BoundNetLog(), GetParam(), NULL);
6166 helper.AddData(&data);
6167 helper.RunPreTestSetup();
6169 HttpNetworkTransaction* trans = helper.trans();
6171 TestCompletionCallback callback;
6172 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6173 EXPECT_EQ(ERR_IO_PENDING, rv);
6175 base::RunLoop().RunUntilIdle(); // Write as much as we can.
6177 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6178 ASSERT_TRUE(stream != NULL);
6179 ASSERT_TRUE(stream->stream() != NULL);
6180 EXPECT_EQ(0, stream->stream()->send_window_size());
6181 // All the body data should have been read.
6182 // TODO(satorux): This is because of the weirdness in reading the request
6183 // body in OnSendBodyComplete(). See crbug.com/113107.
6184 EXPECT_TRUE(upload_data_stream.IsEOF());
6185 // But the body is not yet fully sent (kUploadData is not yet sent)
6186 // since we're send-stalled.
6187 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6189 data.ForceNextRead(); // Read in WINDOW_UPDATE frame.
6190 rv = callback.WaitForResult();
6191 helper.VerifyDataConsumed();
6194 // Test we correctly handle the case where the SETTINGS frame results in
6195 // unstalling the send window.
6196 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
6197 // Number of frames we need to send to zero out the window size: data
6198 // frames plus SYN_STREAM plus the last data frame; also we need another
6199 // data frame that we will send once the SETTING is received, therefore +3.
6200 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
6202 // Calculate last frame's size; 0 size data frame is legal.
6203 size_t last_frame_size =
6204 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6206 // Construct content for a data frame of maximum size.
6207 std::string content(kMaxSpdyFrameChunkSize, 'a');
6209 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6210 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6211 LOWEST, NULL, 0));
6213 // Full frames.
6214 scoped_ptr<SpdyFrame> body1(
6215 spdy_util_.ConstructSpdyBodyFrame(
6216 1, content.c_str(), content.size(), false));
6218 // Last frame to zero out the window size.
6219 scoped_ptr<SpdyFrame> body2(
6220 spdy_util_.ConstructSpdyBodyFrame(
6221 1, content.c_str(), last_frame_size, false));
6223 // Data frame to be sent once SETTINGS frame is received.
6224 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6226 // Fill in mock reads/writes.
6227 std::vector<MockRead> reads;
6228 std::vector<MockWrite> writes;
6229 size_t i = 0;
6230 writes.push_back(CreateMockWrite(*req, i++));
6231 while (i < num_writes - 2)
6232 writes.push_back(CreateMockWrite(*body1, i++));
6233 writes.push_back(CreateMockWrite(*body2, i++));
6235 // Construct read frame for SETTINGS that gives enough space to upload the
6236 // rest of the data.
6237 SettingsMap settings;
6238 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6239 SettingsFlagsAndValue(
6240 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize * 2);
6241 scoped_ptr<SpdyFrame> settings_frame_large(
6242 spdy_util_.ConstructSpdySettings(settings));
6244 reads.push_back(CreateMockRead(*settings_frame_large, i++));
6246 scoped_ptr<SpdyFrame> session_window_update(
6247 spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6248 if (GetParam().protocol >= kProtoSPDY31)
6249 reads.push_back(CreateMockRead(*session_window_update, i++));
6251 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6252 writes.push_back(CreateMockWrite(*settings_ack, i++));
6254 writes.push_back(CreateMockWrite(*body3, i++));
6256 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6257 reads.push_back(CreateMockRead(*reply, i++));
6258 reads.push_back(CreateMockRead(*body2, i++));
6259 reads.push_back(CreateMockRead(*body3, i++));
6260 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6262 // Force all writes to happen before any read, last write will not
6263 // actually queue a frame, due to window size being 0.
6264 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6265 vector_as_array(&writes), writes.size());
6267 ScopedVector<UploadElementReader> element_readers;
6268 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6269 upload_data_string.append(kUploadData, kUploadDataSize);
6270 element_readers.push_back(new UploadBytesElementReader(
6271 upload_data_string.c_str(), upload_data_string.size()));
6272 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6274 HttpRequestInfo request;
6275 request.method = "POST";
6276 request.url = GURL("http://www.google.com/");
6277 request.upload_data_stream = &upload_data_stream;
6278 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6279 BoundNetLog(), GetParam(), NULL);
6280 helper.SetDeterministic();
6281 helper.RunPreTestSetup();
6282 helper.AddDeterministicData(&data);
6284 HttpNetworkTransaction* trans = helper.trans();
6286 TestCompletionCallback callback;
6287 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6288 EXPECT_EQ(ERR_IO_PENDING, rv);
6290 data.RunFor(num_writes - 1); // Write as much as we can.
6292 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6293 ASSERT_TRUE(stream != NULL);
6294 ASSERT_TRUE(stream->stream() != NULL);
6295 EXPECT_EQ(0, stream->stream()->send_window_size());
6297 // All the body data should have been read.
6298 // TODO(satorux): This is because of the weirdness in reading the request
6299 // body in OnSendBodyComplete(). See crbug.com/113107.
6300 EXPECT_TRUE(upload_data_stream.IsEOF());
6301 // But the body is not yet fully sent (kUploadData is not yet sent)
6302 // since we're send-stalled.
6303 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6305 data.RunFor(7); // Read in SETTINGS frame to unstall.
6306 rv = callback.WaitForResult();
6307 helper.VerifyDataConsumed();
6308 // If stream is NULL, that means it was unstalled and closed.
6309 EXPECT_TRUE(stream->stream() == NULL);
6312 // Test we correctly handle the case where the SETTINGS frame results in a
6313 // negative send window size.
6314 TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
6315 // Number of frames we need to send to zero out the window size: data
6316 // frames plus SYN_STREAM plus the last data frame; also we need another
6317 // data frame that we will send once the SETTING is received, therefore +3.
6318 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
6320 // Calculate last frame's size; 0 size data frame is legal.
6321 size_t last_frame_size =
6322 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
6324 // Construct content for a data frame of maximum size.
6325 std::string content(kMaxSpdyFrameChunkSize, 'a');
6327 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6328 kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6329 LOWEST, NULL, 0));
6331 // Full frames.
6332 scoped_ptr<SpdyFrame> body1(
6333 spdy_util_.ConstructSpdyBodyFrame(
6334 1, content.c_str(), content.size(), false));
6336 // Last frame to zero out the window size.
6337 scoped_ptr<SpdyFrame> body2(
6338 spdy_util_.ConstructSpdyBodyFrame(
6339 1, content.c_str(), last_frame_size, false));
6341 // Data frame to be sent once SETTINGS frame is received.
6342 scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6344 // Fill in mock reads/writes.
6345 std::vector<MockRead> reads;
6346 std::vector<MockWrite> writes;
6347 size_t i = 0;
6348 writes.push_back(CreateMockWrite(*req, i++));
6349 while (i < num_writes - 2)
6350 writes.push_back(CreateMockWrite(*body1, i++));
6351 writes.push_back(CreateMockWrite(*body2, i++));
6353 // Construct read frame for SETTINGS that makes the send_window_size
6354 // negative.
6355 SettingsMap new_settings;
6356 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6357 SettingsFlagsAndValue(
6358 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize / 2);
6359 scoped_ptr<SpdyFrame> settings_frame_small(
6360 spdy_util_.ConstructSpdySettings(new_settings));
6361 // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6362 // positive.
6363 scoped_ptr<SpdyFrame> session_window_update_init_size(
6364 spdy_util_.ConstructSpdyWindowUpdate(0, kSpdyStreamInitialWindowSize));
6365 scoped_ptr<SpdyFrame> window_update_init_size(
6366 spdy_util_.ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize));
6368 reads.push_back(CreateMockRead(*settings_frame_small, i++));
6369 reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
6370 reads.push_back(CreateMockRead(*window_update_init_size, i++));
6372 scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6373 writes.push_back(CreateMockWrite(*settings_ack, i++));
6375 writes.push_back(CreateMockWrite(*body3, i++));
6377 scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6378 reads.push_back(CreateMockRead(*reply, i++));
6379 reads.push_back(CreateMockRead(*body2, i++));
6380 reads.push_back(CreateMockRead(*body3, i++));
6381 reads.push_back(MockRead(ASYNC, 0, i++)); // EOF
6383 // Force all writes to happen before any read, last write will not
6384 // actually queue a frame, due to window size being 0.
6385 DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6386 vector_as_array(&writes), writes.size());
6388 ScopedVector<UploadElementReader> element_readers;
6389 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6390 upload_data_string.append(kUploadData, kUploadDataSize);
6391 element_readers.push_back(new UploadBytesElementReader(
6392 upload_data_string.c_str(), upload_data_string.size()));
6393 ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0);
6395 HttpRequestInfo request;
6396 request.method = "POST";
6397 request.url = GURL("http://www.google.com/");
6398 request.upload_data_stream = &upload_data_stream;
6399 NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6400 BoundNetLog(), GetParam(), NULL);
6401 helper.SetDeterministic();
6402 helper.RunPreTestSetup();
6403 helper.AddDeterministicData(&data);
6405 HttpNetworkTransaction* trans = helper.trans();
6407 TestCompletionCallback callback;
6408 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6409 EXPECT_EQ(ERR_IO_PENDING, rv);
6411 data.RunFor(num_writes - 1); // Write as much as we can.
6413 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6414 ASSERT_TRUE(stream != NULL);
6415 ASSERT_TRUE(stream->stream() != NULL);
6416 EXPECT_EQ(0, stream->stream()->send_window_size());
6418 // All the body data should have been read.
6419 // TODO(satorux): This is because of the weirdness in reading the request
6420 // body in OnSendBodyComplete(). See crbug.com/113107.
6421 EXPECT_TRUE(upload_data_stream.IsEOF());
6422 // But the body is not yet fully sent (kUploadData is not yet sent)
6423 // since we're send-stalled.
6424 EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6426 // Read in WINDOW_UPDATE or SETTINGS frame.
6427 data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 9 : 8);
6428 rv = callback.WaitForResult();
6429 helper.VerifyDataConsumed();
6432 TEST_P(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
6433 if (spdy_util_.spdy_version() < SPDY3)
6434 return;
6436 scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
6437 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/a.dat",
6438 push_headers.get());
6439 scoped_ptr<SpdyFrame> push(
6440 spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 3, 1));
6441 MockRead reads[] = {CreateMockRead(*push, 1)};
6443 scoped_ptr<SpdyFrame> req(
6444 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6445 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6446 0, GOAWAY_PROTOCOL_ERROR, "Odd push stream id."));
6447 MockWrite writes[] = {
6448 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2),
6451 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
6452 NormalSpdyTransactionHelper helper(
6453 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6454 helper.RunToCompletion(&data);
6455 TransactionHelperResult out = helper.output();
6456 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6459 TEST_P(SpdyNetworkTransactionTest,
6460 GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
6461 if (spdy_util_.spdy_version() < SPDY3)
6462 return;
6464 scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
6465 NULL, 0, 4, 1, "http://www.google.com/a.dat"));
6466 scoped_ptr<SpdyHeaderBlock> push_b_headers(new SpdyHeaderBlock);
6467 spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
6468 push_b_headers.get());
6469 scoped_ptr<SpdyFrame> push_b(
6470 spdy_util_.ConstructInitialSpdyPushFrame(push_b_headers.Pass(), 2, 1));
6471 MockRead reads[] = {
6472 CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
6475 scoped_ptr<SpdyFrame> req(
6476 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6477 scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
6479 GOAWAY_PROTOCOL_ERROR,
6480 "New push stream id must be greater than the last accepted."));
6481 MockWrite writes[] = {
6482 CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
6485 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
6486 NormalSpdyTransactionHelper helper(
6487 CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6488 helper.RunToCompletion(&data);
6489 TransactionHelperResult out = helper.output();
6490 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6493 class SpdyNetworkTransactionNoTLSUsageCheckTest
6494 : public SpdyNetworkTransactionTest {
6495 protected:
6496 void RunNoTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6497 // Construct the request.
6498 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyGet(
6499 "https://www.google.com/", false, 1, LOWEST));
6500 MockWrite writes[] = {CreateMockWrite(*req)};
6502 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6503 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6504 MockRead reads[] = {
6505 CreateMockRead(*resp), CreateMockRead(*body),
6506 MockRead(ASYNC, 0, 0) // EOF
6509 DelayedSocketData data(
6510 1, reads, arraysize(reads), writes, arraysize(writes));
6511 HttpRequestInfo request;
6512 request.method = "GET";
6513 request.url = GURL("https://www.google.com/");
6514 NormalSpdyTransactionHelper helper(
6515 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6516 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6517 TransactionHelperResult out = helper.output();
6518 EXPECT_EQ(OK, out.rv);
6519 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
6520 EXPECT_EQ("hello!", out.response_data);
6524 //-----------------------------------------------------------------------------
6525 // All tests are run with three different connection types: SPDY after NPN
6526 // negotiation, SPDY without SSL, and SPDY with SSL.
6528 // TODO(akalin): Use ::testing::Combine() when we are able to use
6529 // <tr1/tuple>.
6530 INSTANTIATE_TEST_CASE_P(
6531 Spdy,
6532 SpdyNetworkTransactionNoTLSUsageCheckTest,
6533 ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN)));
6535 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSVersionTooOld) {
6536 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6537 new SSLSocketDataProvider(ASYNC, OK));
6538 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6539 &ssl_provider->connection_status);
6541 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6544 TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSCipherSuiteSucky) {
6545 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6546 new SSLSocketDataProvider(ASYNC, OK));
6547 // Set to TLS_RSA_WITH_NULL_MD5
6548 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6550 RunNoTLSUsageCheckTest(ssl_provider.Pass());
6553 class SpdyNetworkTransactionTLSUsageCheckTest
6554 : public SpdyNetworkTransactionTest {
6555 protected:
6556 void RunTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6557 scoped_ptr<SpdyFrame> goaway(
6558 spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
6559 MockWrite writes[] = {CreateMockWrite(*goaway)};
6561 DelayedSocketData data(1, NULL, 0, writes, arraysize(writes));
6562 HttpRequestInfo request;
6563 request.method = "GET";
6564 request.url = GURL("https://www.google.com/");
6565 NormalSpdyTransactionHelper helper(
6566 request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6567 helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6568 TransactionHelperResult out = helper.output();
6569 EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, out.rv);
6573 INSTANTIATE_TEST_CASE_P(
6574 Spdy,
6575 SpdyNetworkTransactionTLSUsageCheckTest,
6576 ::testing::Values(
6577 SpdyNetworkTransactionTestParams(kProtoSPDY4_14, SPDYNPN),
6578 SpdyNetworkTransactionTestParams(kProtoSPDY4_15, SPDYNPN)));
6580 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
6581 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6582 new SSLSocketDataProvider(ASYNC, OK));
6583 SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6584 &ssl_provider->connection_status);
6586 RunTLSUsageCheckTest(ssl_provider.Pass());
6589 TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
6590 scoped_ptr<SSLSocketDataProvider> ssl_provider(
6591 new SSLSocketDataProvider(ASYNC, OK));
6592 // Set to TLS_RSA_WITH_NULL_MD5
6593 SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6595 RunTLSUsageCheckTest(ssl_provider.Pass());
6598 } // namespace net