Enables compositing support for webview.
[chromium-blink-merge.git] / net / spdy / spdy_network_transaction_spdy3_unittest.cc
blobf81876e3e9521ff7e01c0abb899a5424431dc432
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 "net/http/http_network_transaction.h"
7 #include <string>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/memory/scoped_vector.h"
15 #include "net/base/auth.h"
16 #include "net/base/net_log_unittest.h"
17 #include "net/base/upload_bytes_element_reader.h"
18 #include "net/base/upload_data_stream.h"
19 #include "net/base/upload_file_element_reader.h"
20 #include "net/http/http_network_session_peer.h"
21 #include "net/http/http_transaction_unittest.h"
22 #include "net/socket/client_socket_pool_base.h"
23 #include "net/spdy/buffered_spdy_framer.h"
24 #include "net/spdy/spdy_http_stream.h"
25 #include "net/spdy/spdy_http_utils.h"
26 #include "net/spdy/spdy_session.h"
27 #include "net/spdy/spdy_session_pool.h"
28 #include "net/spdy/spdy_test_util_spdy3.h"
29 #include "net/url_request/url_request_test_util.h"
30 #include "testing/platform_test.h"
32 using namespace net::test_spdy3;
34 //-----------------------------------------------------------------------------
36 namespace net {
38 enum SpdyNetworkTransactionSpdy3TestTypes {
39 SPDYNPN,
40 SPDYNOSSL,
41 SPDYSSL,
44 class SpdyNetworkTransactionSpdy3Test
45 : public ::testing::TestWithParam<SpdyNetworkTransactionSpdy3TestTypes> {
46 protected:
48 virtual void SetUp() {
49 google_get_request_initialized_ = false;
50 google_post_request_initialized_ = false;
51 google_chunked_post_request_initialized_ = false;
52 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
55 virtual void TearDown() {
56 UploadDataStream::ResetMergeChunks();
57 // Empty the current queue.
58 MessageLoop::current()->RunUntilIdle();
61 void set_merge_chunks(bool merge) {
62 UploadDataStream::set_merge_chunks(merge);
65 struct TransactionHelperResult {
66 int rv;
67 std::string status_line;
68 std::string response_data;
69 HttpResponseInfo response_info;
72 // A helper class that handles all the initial npn/ssl setup.
73 class NormalSpdyTransactionHelper {
74 public:
75 NormalSpdyTransactionHelper(const HttpRequestInfo& request,
76 const BoundNetLog& log,
77 SpdyNetworkTransactionSpdy3TestTypes test_type,
78 SpdySessionDependencies* session_deps)
79 : request_(request),
80 session_deps_(session_deps == NULL ?
81 new SpdySessionDependencies() : session_deps),
82 session_(SpdySessionDependencies::SpdyCreateSession(
83 session_deps_.get())),
84 log_(log),
85 test_type_(test_type),
86 deterministic_(false),
87 spdy_enabled_(true) {
88 switch (test_type_) {
89 case SPDYNOSSL:
90 case SPDYSSL:
91 port_ = 80;
92 break;
93 case SPDYNPN:
94 port_ = 443;
95 break;
96 default:
97 NOTREACHED();
101 ~NormalSpdyTransactionHelper() {
102 // Any test which doesn't close the socket by sending it an EOF will
103 // have a valid session left open, which leaks the entire session pool.
104 // This is just fine - in fact, some of our tests intentionally do this
105 // so that we can check consistency of the SpdySessionPool as the test
106 // finishes. If we had put an EOF on the socket, the SpdySession would
107 // have closed and we wouldn't be able to check the consistency.
109 // Forcefully close existing sessions here.
110 session()->spdy_session_pool()->CloseAllSessions();
113 void SetDeterministic() {
114 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
115 session_deps_.get());
116 deterministic_ = true;
119 void SetSpdyDisabled() {
120 spdy_enabled_ = false;
121 port_ = 80;
124 void RunPreTestSetup() {
125 if (!session_deps_.get())
126 session_deps_.reset(new SpdySessionDependencies());
127 if (!session_.get())
128 session_ = SpdySessionDependencies::SpdyCreateSession(
129 session_deps_.get());
130 HttpStreamFactory::set_use_alternate_protocols(false);
131 HttpStreamFactory::set_force_spdy_over_ssl(false);
132 HttpStreamFactory::set_force_spdy_always(false);
134 std::vector<std::string> next_protos;
135 next_protos.push_back("http/1.1");
136 next_protos.push_back("spdy/2");
137 next_protos.push_back("spdy/3");
139 switch (test_type_) {
140 case SPDYNPN:
141 session_->http_server_properties()->SetAlternateProtocol(
142 HostPortPair("www.google.com", 80), 443,
143 NPN_SPDY_3);
144 HttpStreamFactory::set_use_alternate_protocols(true);
145 HttpStreamFactory::SetNextProtos(next_protos);
146 break;
147 case SPDYNOSSL:
148 HttpStreamFactory::set_force_spdy_over_ssl(false);
149 HttpStreamFactory::set_force_spdy_always(true);
150 break;
151 case SPDYSSL:
152 HttpStreamFactory::set_force_spdy_over_ssl(true);
153 HttpStreamFactory::set_force_spdy_always(true);
154 break;
155 default:
156 NOTREACHED();
159 // We're now ready to use SSL-npn SPDY.
160 trans_.reset(new HttpNetworkTransaction(session_));
163 // Start the transaction, read some data, finish.
164 void RunDefaultTest() {
165 output_.rv = trans_->Start(&request_, callback.callback(), log_);
167 // We expect an IO Pending or some sort of error.
168 EXPECT_LT(output_.rv, 0);
169 if (output_.rv != ERR_IO_PENDING)
170 return;
172 output_.rv = callback.WaitForResult();
173 if (output_.rv != OK) {
174 session_->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED);
175 return;
178 // Verify responses.
179 const HttpResponseInfo* response = trans_->GetResponseInfo();
180 ASSERT_TRUE(response != NULL);
181 ASSERT_TRUE(response->headers != NULL);
182 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
183 EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
184 if (test_type_ == SPDYNPN && spdy_enabled_) {
185 EXPECT_TRUE(response->was_npn_negotiated);
186 } else {
187 EXPECT_TRUE(!response->was_npn_negotiated);
189 // If SPDY is not enabled, a HTTP request should not be diverted
190 // over a SSL session.
191 if (!spdy_enabled_) {
192 EXPECT_EQ(request_.url.SchemeIs("https"),
193 response->was_npn_negotiated);
195 EXPECT_EQ("127.0.0.1", response->socket_address.host());
196 EXPECT_EQ(port_, response->socket_address.port());
197 output_.status_line = response->headers->GetStatusLine();
198 output_.response_info = *response; // Make a copy so we can verify.
199 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
202 // Most tests will want to call this function. In particular, the MockReads
203 // should end with an empty read, and that read needs to be processed to
204 // ensure proper deletion of the spdy_session_pool.
205 void VerifyDataConsumed() {
206 for (DataVector::iterator it = data_vector_.begin();
207 it != data_vector_.end(); ++it) {
208 EXPECT_TRUE((*it)->at_read_eof()) << "Read count: "
209 << (*it)->read_count()
210 << " Read index: "
211 << (*it)->read_index();
212 EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
213 << (*it)->write_count()
214 << " Write index: "
215 << (*it)->write_index();
219 // Occasionally a test will expect to error out before certain reads are
220 // processed. In that case we want to explicitly ensure that the reads were
221 // not processed.
222 void VerifyDataNotConsumed() {
223 for (DataVector::iterator it = data_vector_.begin();
224 it != data_vector_.end(); ++it) {
225 EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: "
226 << (*it)->read_count()
227 << " Read index: "
228 << (*it)->read_index();
229 EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
230 << (*it)->write_count()
231 << " Write index: "
232 << (*it)->write_index();
236 void RunToCompletion(StaticSocketDataProvider* data) {
237 RunPreTestSetup();
238 AddData(data);
239 RunDefaultTest();
240 VerifyDataConsumed();
243 void AddData(StaticSocketDataProvider* data) {
244 DCHECK(!deterministic_);
245 data_vector_.push_back(data);
246 SSLSocketDataProvider* ssl_provider =
247 new SSLSocketDataProvider(ASYNC, OK);
248 if (test_type_ == SPDYNPN)
249 ssl_provider->SetNextProto(kProtoSPDY3);
251 ssl_vector_.push_back(ssl_provider);
252 if (test_type_ == SPDYNPN || test_type_ == SPDYSSL)
253 session_deps_->socket_factory->AddSSLSocketDataProvider(ssl_provider);
255 session_deps_->socket_factory->AddSocketDataProvider(data);
256 if (test_type_ == SPDYNPN) {
257 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
258 StaticSocketDataProvider* hanging_non_alternate_protocol_socket =
259 new StaticSocketDataProvider(NULL, 0, NULL, 0);
260 hanging_non_alternate_protocol_socket->set_connect_data(
261 never_finishing_connect);
262 session_deps_->socket_factory->AddSocketDataProvider(
263 hanging_non_alternate_protocol_socket);
264 alternate_vector_.push_back(hanging_non_alternate_protocol_socket);
268 void AddDeterministicData(DeterministicSocketData* data) {
269 DCHECK(deterministic_);
270 data_vector_.push_back(data);
271 SSLSocketDataProvider* ssl_provider =
272 new SSLSocketDataProvider(ASYNC, OK);
273 if (test_type_ == SPDYNPN)
274 ssl_provider->SetNextProto(kProtoSPDY3);
276 ssl_vector_.push_back(ssl_provider);
277 if (test_type_ == SPDYNPN || test_type_ == SPDYSSL) {
278 session_deps_->deterministic_socket_factory->
279 AddSSLSocketDataProvider(ssl_provider);
281 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
282 if (test_type_ == SPDYNPN) {
283 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
284 DeterministicSocketData* hanging_non_alternate_protocol_socket =
285 new DeterministicSocketData(NULL, 0, NULL, 0);
286 hanging_non_alternate_protocol_socket->set_connect_data(
287 never_finishing_connect);
288 session_deps_->deterministic_socket_factory->AddSocketDataProvider(
289 hanging_non_alternate_protocol_socket);
290 alternate_deterministic_vector_.push_back(
291 hanging_non_alternate_protocol_socket);
295 void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
296 session_ = session;
298 HttpNetworkTransaction* trans() { return trans_.get(); }
299 void ResetTrans() { trans_.reset(); }
300 TransactionHelperResult& output() { return output_; }
301 const HttpRequestInfo& request() const { return request_; }
302 const scoped_refptr<HttpNetworkSession>& session() const {
303 return session_;
305 scoped_ptr<SpdySessionDependencies>& session_deps() {
306 return session_deps_;
308 int port() const { return port_; }
309 SpdyNetworkTransactionSpdy3TestTypes test_type() const {
310 return test_type_;
313 private:
314 typedef std::vector<StaticSocketDataProvider*> DataVector;
315 typedef ScopedVector<SSLSocketDataProvider> SSLVector;
316 typedef ScopedVector<StaticSocketDataProvider> AlternateVector;
317 typedef ScopedVector<DeterministicSocketData> AlternateDeterministicVector;
318 HttpRequestInfo request_;
319 scoped_ptr<SpdySessionDependencies> session_deps_;
320 scoped_refptr<HttpNetworkSession> session_;
321 TransactionHelperResult output_;
322 scoped_ptr<StaticSocketDataProvider> first_transaction_;
323 SSLVector ssl_vector_;
324 TestCompletionCallback callback;
325 scoped_ptr<HttpNetworkTransaction> trans_;
326 scoped_ptr<HttpNetworkTransaction> trans_http_;
327 DataVector data_vector_;
328 AlternateVector alternate_vector_;
329 AlternateDeterministicVector alternate_deterministic_vector_;
330 const BoundNetLog& log_;
331 SpdyNetworkTransactionSpdy3TestTypes test_type_;
332 int port_;
333 bool deterministic_;
334 bool spdy_enabled_;
337 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
338 int expected_status);
340 void ConnectStatusHelper(const MockRead& status);
342 const HttpRequestInfo& CreateGetPushRequest() {
343 google_get_push_request_.method = "GET";
344 google_get_push_request_.url = GURL("http://www.google.com/foo.dat");
345 google_get_push_request_.load_flags = 0;
346 return google_get_push_request_;
349 const HttpRequestInfo& CreateGetRequest() {
350 if (!google_get_request_initialized_) {
351 google_get_request_.method = "GET";
352 google_get_request_.url = GURL(kDefaultURL);
353 google_get_request_.load_flags = 0;
354 google_get_request_initialized_ = true;
356 return google_get_request_;
359 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
360 if (!google_get_request_initialized_) {
361 google_get_request_.method = "GET";
362 google_get_request_.url = GURL(kDefaultURL);
363 google_get_request_.load_flags = 0;
364 google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
365 google_get_request_initialized_ = true;
367 return google_get_request_;
370 const HttpRequestInfo& CreatePostRequest() {
371 if (!google_post_request_initialized_) {
372 ScopedVector<UploadElementReader> element_readers;
373 element_readers.push_back(
374 new UploadBytesElementReader(kUploadData, kUploadDataSize));
375 upload_data_stream_.reset(new UploadDataStream(&element_readers, 0));
377 google_post_request_.method = "POST";
378 google_post_request_.url = GURL(kDefaultURL);
379 google_post_request_.upload_data_stream = upload_data_stream_.get();
380 google_post_request_initialized_ = true;
382 return google_post_request_;
385 const HttpRequestInfo& CreateFilePostRequest() {
386 if (!google_post_request_initialized_) {
387 FilePath file_path;
388 CHECK(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
389 CHECK_EQ(static_cast<int>(kUploadDataSize),
390 file_util::WriteFile(file_path, kUploadData, kUploadDataSize));
392 ScopedVector<UploadElementReader> element_readers;
393 element_readers.push_back(new UploadFileElementReader(
394 base::MessageLoopProxy::current(),
395 file_path, 0, kUploadDataSize, base::Time()));
396 upload_data_stream_.reset(new UploadDataStream(&element_readers, 0));
398 google_post_request_.method = "POST";
399 google_post_request_.url = GURL(kDefaultURL);
400 google_post_request_.upload_data_stream = upload_data_stream_.get();
401 google_post_request_initialized_ = true;
403 return google_post_request_;
406 const HttpRequestInfo& CreateComplexPostRequest() {
407 if (!google_post_request_initialized_) {
408 const int kFileRangeOffset = 1;
409 const int kFileRangeLength = 3;
410 CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
412 FilePath file_path;
413 CHECK(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
414 CHECK_EQ(static_cast<int>(kUploadDataSize),
415 file_util::WriteFile(file_path, kUploadData, kUploadDataSize));
417 ScopedVector<UploadElementReader> element_readers;
418 element_readers.push_back(
419 new UploadBytesElementReader(kUploadData, kFileRangeOffset));
420 element_readers.push_back(new UploadFileElementReader(
421 base::MessageLoopProxy::current(),
422 file_path, kFileRangeOffset, kFileRangeLength, base::Time()));
423 element_readers.push_back(new UploadBytesElementReader(
424 kUploadData + kFileRangeOffset + kFileRangeLength,
425 kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
426 upload_data_stream_.reset(new UploadDataStream(&element_readers, 0));
428 google_post_request_.method = "POST";
429 google_post_request_.url = GURL(kDefaultURL);
430 google_post_request_.upload_data_stream = upload_data_stream_.get();
431 google_post_request_initialized_ = true;
433 return google_post_request_;
436 const HttpRequestInfo& CreateChunkedPostRequest() {
437 if (!google_chunked_post_request_initialized_) {
438 upload_data_stream_.reset(
439 new UploadDataStream(UploadDataStream::CHUNKED, 0));
440 upload_data_stream_->AppendChunk(kUploadData, kUploadDataSize, false);
441 upload_data_stream_->AppendChunk(kUploadData, kUploadDataSize, true);
443 google_chunked_post_request_.method = "POST";
444 google_chunked_post_request_.url = GURL(kDefaultURL);
445 google_chunked_post_request_.upload_data_stream =
446 upload_data_stream_.get();
447 google_chunked_post_request_initialized_ = true;
449 return google_chunked_post_request_;
452 // Read the result of a particular transaction, knowing that we've got
453 // multiple transactions in the read pipeline; so as we read, we may have
454 // to skip over data destined for other transactions while we consume
455 // the data for |trans|.
456 int ReadResult(HttpNetworkTransaction* trans,
457 StaticSocketDataProvider* data,
458 std::string* result) {
459 const int kSize = 3000;
461 int bytes_read = 0;
462 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
463 TestCompletionCallback callback;
464 while (true) {
465 int rv = trans->Read(buf, kSize, callback.callback());
466 if (rv == ERR_IO_PENDING) {
467 // Multiple transactions may be in the data set. Keep pulling off
468 // reads until we complete our callback.
469 while (!callback.have_result()) {
470 data->CompleteRead();
471 MessageLoop::current()->RunUntilIdle();
473 rv = callback.WaitForResult();
474 } else if (rv <= 0) {
475 break;
477 result->append(buf->data(), rv);
478 bytes_read += rv;
480 return bytes_read;
483 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
484 // This lengthy block is reaching into the pool to dig out the active
485 // session. Once we have the session, we verify that the streams are
486 // all closed and not leaked at this point.
487 const GURL& url = helper.request().url;
488 int port = helper.test_type() == SPDYNPN ? 443 : 80;
489 HostPortPair host_port_pair(url.host(), port);
490 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
491 BoundNetLog log;
492 const scoped_refptr<HttpNetworkSession>& session = helper.session();
493 SpdySessionPool* pool(session->spdy_session_pool());
494 EXPECT_TRUE(pool->HasSession(pair));
495 scoped_refptr<SpdySession> spdy_session(pool->Get(pair, log));
496 ASSERT_TRUE(spdy_session.get() != NULL);
497 EXPECT_EQ(0u, spdy_session->num_active_streams());
498 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
501 void RunServerPushTest(OrderedSocketData* data,
502 HttpResponseInfo* response,
503 HttpResponseInfo* push_response,
504 std::string& expected) {
505 NormalSpdyTransactionHelper helper(CreateGetRequest(),
506 BoundNetLog(), GetParam(), NULL);
507 helper.RunPreTestSetup();
508 helper.AddData(data);
510 HttpNetworkTransaction* trans = helper.trans();
512 // Start the transaction with basic parameters.
513 TestCompletionCallback callback;
514 int rv = trans->Start(
515 &CreateGetRequest(), callback.callback(), BoundNetLog());
516 EXPECT_EQ(ERR_IO_PENDING, rv);
517 rv = callback.WaitForResult();
519 // Request the pushed path.
520 scoped_ptr<HttpNetworkTransaction> trans2(
521 new HttpNetworkTransaction(helper.session()));
522 rv = trans2->Start(
523 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
524 EXPECT_EQ(ERR_IO_PENDING, rv);
525 MessageLoop::current()->RunUntilIdle();
527 // The data for the pushed path may be coming in more than 1 packet. Compile
528 // the results into a single string.
530 // Read the server push body.
531 std::string result2;
532 ReadResult(trans2.get(), data, &result2);
533 // Read the response body.
534 std::string result;
535 ReadResult(trans, data, &result);
537 // Verify that we consumed all test data.
538 EXPECT_TRUE(data->at_read_eof());
539 EXPECT_TRUE(data->at_write_eof());
541 // Verify that the received push data is same as the expected push data.
542 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
543 << result2
544 << "||||| Expected data: "
545 << expected;
547 // Verify the SYN_REPLY.
548 // Copy the response info, because trans goes away.
549 *response = *trans->GetResponseInfo();
550 *push_response = *trans2->GetResponseInfo();
552 VerifyStreamsClosed(helper);
555 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
556 int result) {
557 helper->ResetTrans();
560 static void StartTransactionCallback(
561 const scoped_refptr<HttpNetworkSession>& session,
562 int result) {
563 scoped_ptr<HttpNetworkTransaction> trans(
564 new HttpNetworkTransaction(session));
565 TestCompletionCallback callback;
566 HttpRequestInfo request;
567 request.method = "GET";
568 request.url = GURL("http://www.google.com/");
569 request.load_flags = 0;
570 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
571 EXPECT_EQ(ERR_IO_PENDING, rv);
572 callback.WaitForResult();
575 private:
576 scoped_ptr<UploadDataStream> upload_data_stream_;
577 bool google_get_request_initialized_;
578 bool google_post_request_initialized_;
579 bool google_chunked_post_request_initialized_;
580 HttpRequestInfo google_get_request_;
581 HttpRequestInfo google_post_request_;
582 HttpRequestInfo google_chunked_post_request_;
583 HttpRequestInfo google_get_push_request_;
584 base::ScopedTempDir temp_dir_;
587 //-----------------------------------------------------------------------------
588 // All tests are run with three different connection types: SPDY after NPN
589 // negotiation, SPDY without SSL, and SPDY with SSL.
590 INSTANTIATE_TEST_CASE_P(Spdy,
591 SpdyNetworkTransactionSpdy3Test,
592 ::testing::Values(SPDYNOSSL, SPDYSSL, SPDYNPN));
595 // Verify HttpNetworkTransaction constructor.
596 TEST_P(SpdyNetworkTransactionSpdy3Test, Constructor) {
597 SpdySessionDependencies session_deps;
598 scoped_refptr<HttpNetworkSession> session(
599 SpdySessionDependencies::SpdyCreateSession(&session_deps));
600 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
603 TEST_P(SpdyNetworkTransactionSpdy3Test, Get) {
604 // Construct the request.
605 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
606 MockWrite writes[] = { CreateMockWrite(*req) };
608 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
609 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
610 MockRead reads[] = {
611 CreateMockRead(*resp),
612 CreateMockRead(*body),
613 MockRead(ASYNC, 0, 0) // EOF
616 DelayedSocketData data(1, reads, arraysize(reads),
617 writes, arraysize(writes));
618 NormalSpdyTransactionHelper helper(CreateGetRequest(),
619 BoundNetLog(), GetParam(), NULL);
620 helper.RunToCompletion(&data);
621 TransactionHelperResult out = helper.output();
622 EXPECT_EQ(OK, out.rv);
623 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
624 EXPECT_EQ("hello!", out.response_data);
627 TEST_P(SpdyNetworkTransactionSpdy3Test, GetAtEachPriority) {
628 for (RequestPriority p = MINIMUM_PRIORITY; p < NUM_PRIORITIES;
629 p = RequestPriority(p + 1)) {
630 // Construct the request.
631 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, p));
632 MockWrite writes[] = { CreateMockWrite(*req) };
634 const int spdy_prio = reinterpret_cast<SpdySynStreamControlFrame*>(
635 req.get())->priority();
636 // this repeats the RequestPriority-->SpdyPriority mapping from
637 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
638 // sure it's being done right.
639 switch(p) {
640 case HIGHEST:
641 EXPECT_EQ(0, spdy_prio);
642 break;
643 case MEDIUM:
644 EXPECT_EQ(1, spdy_prio);
645 break;
646 case LOW:
647 EXPECT_EQ(2, spdy_prio);
648 break;
649 case LOWEST:
650 EXPECT_EQ(3, spdy_prio);
651 break;
652 case IDLE:
653 EXPECT_EQ(4, spdy_prio);
654 break;
655 default:
656 FAIL();
659 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
660 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
661 MockRead reads[] = {
662 CreateMockRead(*resp),
663 CreateMockRead(*body),
664 MockRead(ASYNC, 0, 0) // EOF
667 DelayedSocketData data(1, reads, arraysize(reads),
668 writes, arraysize(writes));
669 HttpRequestInfo http_req = CreateGetRequest();
670 http_req.priority = p;
672 NormalSpdyTransactionHelper helper(http_req, BoundNetLog(),
673 GetParam(), NULL);
674 helper.RunToCompletion(&data);
675 TransactionHelperResult out = helper.output();
676 EXPECT_EQ(OK, out.rv);
677 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
678 EXPECT_EQ("hello!", out.response_data);
682 // Start three gets simultaniously; making sure that multiplexed
683 // streams work properly.
685 // This can't use the TransactionHelper method, since it only
686 // handles a single transaction, and finishes them as soon
687 // as it launches them.
689 // TODO(gavinp): create a working generalized TransactionHelper that
690 // can allow multiple streams in flight.
692 TEST_P(SpdyNetworkTransactionSpdy3Test, ThreeGets) {
693 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
694 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
695 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
696 scoped_ptr<SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
698 scoped_ptr<SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
699 scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
700 scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
701 scoped_ptr<SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
703 scoped_ptr<SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
704 scoped_ptr<SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
705 scoped_ptr<SpdyFrame> body3(ConstructSpdyBodyFrame(5, false));
706 scoped_ptr<SpdyFrame> fbody3(ConstructSpdyBodyFrame(5, true));
708 MockWrite writes[] = {
709 CreateMockWrite(*req),
710 CreateMockWrite(*req2),
711 CreateMockWrite(*req3),
713 MockRead reads[] = {
714 CreateMockRead(*resp, 1),
715 CreateMockRead(*body),
716 CreateMockRead(*resp2, 4),
717 CreateMockRead(*body2),
718 CreateMockRead(*resp3, 7),
719 CreateMockRead(*body3),
721 CreateMockRead(*fbody),
722 CreateMockRead(*fbody2),
723 CreateMockRead(*fbody3),
725 MockRead(ASYNC, 0, 0), // EOF
727 OrderedSocketData data(reads, arraysize(reads),
728 writes, arraysize(writes));
729 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
731 BoundNetLog log;
732 TransactionHelperResult out;
733 NormalSpdyTransactionHelper helper(CreateGetRequest(),
734 BoundNetLog(), GetParam(), NULL);
735 helper.RunPreTestSetup();
736 helper.AddData(&data);
737 // We require placeholder data because three get requests are sent out, so
738 // there needs to be three sets of SSL connection data.
739 helper.AddData(&data_placeholder);
740 helper.AddData(&data_placeholder);
741 scoped_ptr<HttpNetworkTransaction> trans1(
742 new HttpNetworkTransaction(helper.session()));
743 scoped_ptr<HttpNetworkTransaction> trans2(
744 new HttpNetworkTransaction(helper.session()));
745 scoped_ptr<HttpNetworkTransaction> trans3(
746 new HttpNetworkTransaction(helper.session()));
748 TestCompletionCallback callback1;
749 TestCompletionCallback callback2;
750 TestCompletionCallback callback3;
752 HttpRequestInfo httpreq1 = CreateGetRequest();
753 HttpRequestInfo httpreq2 = CreateGetRequest();
754 HttpRequestInfo httpreq3 = CreateGetRequest();
756 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
757 ASSERT_EQ(ERR_IO_PENDING, out.rv);
758 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
759 ASSERT_EQ(ERR_IO_PENDING, out.rv);
760 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
761 ASSERT_EQ(ERR_IO_PENDING, out.rv);
763 out.rv = callback1.WaitForResult();
764 ASSERT_EQ(OK, out.rv);
765 out.rv = callback3.WaitForResult();
766 ASSERT_EQ(OK, out.rv);
768 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
769 EXPECT_TRUE(response1->headers != NULL);
770 EXPECT_TRUE(response1->was_fetched_via_spdy);
771 out.status_line = response1->headers->GetStatusLine();
772 out.response_info = *response1;
774 trans2->GetResponseInfo();
776 out.rv = ReadTransaction(trans1.get(), &out.response_data);
777 helper.VerifyDataConsumed();
778 EXPECT_EQ(OK, out.rv);
780 EXPECT_EQ(OK, out.rv);
781 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
782 EXPECT_EQ("hello!hello!", out.response_data);
785 TEST_P(SpdyNetworkTransactionSpdy3Test, TwoGetsLateBinding) {
786 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
787 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
788 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
789 scoped_ptr<SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
791 scoped_ptr<SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
792 scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
793 scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
794 scoped_ptr<SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
796 MockWrite writes[] = {
797 CreateMockWrite(*req),
798 CreateMockWrite(*req2),
800 MockRead reads[] = {
801 CreateMockRead(*resp, 1),
802 CreateMockRead(*body),
803 CreateMockRead(*resp2, 4),
804 CreateMockRead(*body2),
805 CreateMockRead(*fbody),
806 CreateMockRead(*fbody2),
807 MockRead(ASYNC, 0, 0), // EOF
809 OrderedSocketData data(reads, arraysize(reads),
810 writes, arraysize(writes));
812 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
814 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
815 data_placeholder.set_connect_data(never_finishing_connect);
817 BoundNetLog log;
818 TransactionHelperResult out;
819 NormalSpdyTransactionHelper helper(CreateGetRequest(),
820 BoundNetLog(), GetParam(), NULL);
821 helper.RunPreTestSetup();
822 helper.AddData(&data);
823 // We require placeholder data because two get requests are sent out, so
824 // there needs to be two sets of SSL connection data.
825 helper.AddData(&data_placeholder);
826 scoped_ptr<HttpNetworkTransaction> trans1(
827 new HttpNetworkTransaction(helper.session()));
828 scoped_ptr<HttpNetworkTransaction> trans2(
829 new HttpNetworkTransaction(helper.session()));
831 TestCompletionCallback callback1;
832 TestCompletionCallback callback2;
834 HttpRequestInfo httpreq1 = CreateGetRequest();
835 HttpRequestInfo httpreq2 = CreateGetRequest();
837 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
838 ASSERT_EQ(ERR_IO_PENDING, out.rv);
839 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
840 ASSERT_EQ(ERR_IO_PENDING, out.rv);
842 out.rv = callback1.WaitForResult();
843 ASSERT_EQ(OK, out.rv);
844 out.rv = callback2.WaitForResult();
845 ASSERT_EQ(OK, out.rv);
847 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
848 EXPECT_TRUE(response1->headers != NULL);
849 EXPECT_TRUE(response1->was_fetched_via_spdy);
850 out.status_line = response1->headers->GetStatusLine();
851 out.response_info = *response1;
852 out.rv = ReadTransaction(trans1.get(), &out.response_data);
853 EXPECT_EQ(OK, out.rv);
854 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
855 EXPECT_EQ("hello!hello!", out.response_data);
857 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
858 EXPECT_TRUE(response2->headers != NULL);
859 EXPECT_TRUE(response2->was_fetched_via_spdy);
860 out.status_line = response2->headers->GetStatusLine();
861 out.response_info = *response2;
862 out.rv = ReadTransaction(trans2.get(), &out.response_data);
863 EXPECT_EQ(OK, out.rv);
864 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
865 EXPECT_EQ("hello!hello!", out.response_data);
867 helper.VerifyDataConsumed();
870 TEST_P(SpdyNetworkTransactionSpdy3Test, TwoGetsLateBindingFromPreconnect) {
871 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
872 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
873 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
874 scoped_ptr<SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
876 scoped_ptr<SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
877 scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
878 scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
879 scoped_ptr<SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
881 MockWrite writes[] = {
882 CreateMockWrite(*req),
883 CreateMockWrite(*req2),
885 MockRead reads[] = {
886 CreateMockRead(*resp, 1),
887 CreateMockRead(*body),
888 CreateMockRead(*resp2, 4),
889 CreateMockRead(*body2),
890 CreateMockRead(*fbody),
891 CreateMockRead(*fbody2),
892 MockRead(ASYNC, 0, 0), // EOF
894 OrderedSocketData preconnect_data(reads, arraysize(reads),
895 writes, arraysize(writes));
897 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
899 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
900 data_placeholder.set_connect_data(never_finishing_connect);
902 BoundNetLog log;
903 TransactionHelperResult out;
904 NormalSpdyTransactionHelper helper(CreateGetRequest(),
905 BoundNetLog(), GetParam(), NULL);
906 helper.RunPreTestSetup();
907 helper.AddData(&preconnect_data);
908 // We require placeholder data because 3 connections are attempted (first is
909 // the preconnect, 2nd and 3rd are the never finished connections.
910 helper.AddData(&data_placeholder);
911 helper.AddData(&data_placeholder);
913 scoped_ptr<HttpNetworkTransaction> trans1(
914 new HttpNetworkTransaction(helper.session()));
915 scoped_ptr<HttpNetworkTransaction> trans2(
916 new HttpNetworkTransaction(helper.session()));
918 TestCompletionCallback callback1;
919 TestCompletionCallback callback2;
921 HttpRequestInfo httpreq = CreateGetRequest();
923 // Preconnect the first.
924 SSLConfig preconnect_ssl_config;
925 helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
926 HttpStreamFactory* http_stream_factory =
927 helper.session()->http_stream_factory();
928 if (http_stream_factory->has_next_protos()) {
929 preconnect_ssl_config.next_protos = http_stream_factory->next_protos();
932 http_stream_factory->PreconnectStreams(
933 1, httpreq, preconnect_ssl_config, preconnect_ssl_config);
935 out.rv = trans1->Start(&httpreq, callback1.callback(), log);
936 ASSERT_EQ(ERR_IO_PENDING, out.rv);
937 out.rv = trans2->Start(&httpreq, callback2.callback(), log);
938 ASSERT_EQ(ERR_IO_PENDING, out.rv);
940 out.rv = callback1.WaitForResult();
941 ASSERT_EQ(OK, out.rv);
942 out.rv = callback2.WaitForResult();
943 ASSERT_EQ(OK, out.rv);
945 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
946 EXPECT_TRUE(response1->headers != NULL);
947 EXPECT_TRUE(response1->was_fetched_via_spdy);
948 out.status_line = response1->headers->GetStatusLine();
949 out.response_info = *response1;
950 out.rv = ReadTransaction(trans1.get(), &out.response_data);
951 EXPECT_EQ(OK, out.rv);
952 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
953 EXPECT_EQ("hello!hello!", out.response_data);
955 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
956 EXPECT_TRUE(response2->headers != NULL);
957 EXPECT_TRUE(response2->was_fetched_via_spdy);
958 out.status_line = response2->headers->GetStatusLine();
959 out.response_info = *response2;
960 out.rv = ReadTransaction(trans2.get(), &out.response_data);
961 EXPECT_EQ(OK, out.rv);
962 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
963 EXPECT_EQ("hello!hello!", out.response_data);
965 helper.VerifyDataConsumed();
968 // Similar to ThreeGets above, however this test adds a SETTINGS
969 // frame. The SETTINGS frame is read during the IO loop waiting on
970 // the first transaction completion, and sets a maximum concurrent
971 // stream limit of 1. This means that our IO loop exists after the
972 // second transaction completes, so we can assert on read_index().
973 TEST_P(SpdyNetworkTransactionSpdy3Test, ThreeGetsWithMaxConcurrent) {
974 // Construct the request.
975 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
976 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
977 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
978 scoped_ptr<SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
980 scoped_ptr<SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
981 scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
982 scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
983 scoped_ptr<SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
985 scoped_ptr<SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
986 scoped_ptr<SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
987 scoped_ptr<SpdyFrame> body3(ConstructSpdyBodyFrame(5, false));
988 scoped_ptr<SpdyFrame> fbody3(ConstructSpdyBodyFrame(5, true));
990 SettingsMap settings;
991 const uint32 max_concurrent_streams = 1;
992 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
993 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
994 scoped_ptr<SpdyFrame> settings_frame(ConstructSpdySettings(settings));
996 MockWrite writes[] = {
997 CreateMockWrite(*req),
998 CreateMockWrite(*req2),
999 CreateMockWrite(*req3),
1002 MockRead reads[] = {
1003 CreateMockRead(*settings_frame, 1),
1004 CreateMockRead(*resp),
1005 CreateMockRead(*body),
1006 CreateMockRead(*fbody),
1007 CreateMockRead(*resp2, 7),
1008 CreateMockRead(*body2),
1009 CreateMockRead(*fbody2),
1010 CreateMockRead(*resp3, 12),
1011 CreateMockRead(*body3),
1012 CreateMockRead(*fbody3),
1014 MockRead(ASYNC, 0, 0), // EOF
1017 OrderedSocketData data(reads, arraysize(reads),
1018 writes, arraysize(writes));
1019 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1021 BoundNetLog log;
1022 TransactionHelperResult out;
1024 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1025 BoundNetLog(), GetParam(), NULL);
1026 helper.RunPreTestSetup();
1027 helper.AddData(&data);
1028 // We require placeholder data because three get requests are sent out, so
1029 // there needs to be three sets of SSL connection data.
1030 helper.AddData(&data_placeholder);
1031 helper.AddData(&data_placeholder);
1032 scoped_ptr<HttpNetworkTransaction> trans1(
1033 new HttpNetworkTransaction(helper.session()));
1034 scoped_ptr<HttpNetworkTransaction> trans2(
1035 new HttpNetworkTransaction(helper.session()));
1036 scoped_ptr<HttpNetworkTransaction> trans3(
1037 new HttpNetworkTransaction(helper.session()));
1039 TestCompletionCallback callback1;
1040 TestCompletionCallback callback2;
1041 TestCompletionCallback callback3;
1043 HttpRequestInfo httpreq1 = CreateGetRequest();
1044 HttpRequestInfo httpreq2 = CreateGetRequest();
1045 HttpRequestInfo httpreq3 = CreateGetRequest();
1047 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1048 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1049 // run transaction 1 through quickly to force a read of our SETTINGS
1050 // frame
1051 out.rv = callback1.WaitForResult();
1052 ASSERT_EQ(OK, out.rv);
1054 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1055 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1056 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1057 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1058 out.rv = callback2.WaitForResult();
1059 ASSERT_EQ(OK, out.rv);
1060 EXPECT_EQ(7U, data.read_index()); // i.e. the third trans was queued
1062 out.rv = callback3.WaitForResult();
1063 ASSERT_EQ(OK, out.rv);
1065 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1066 ASSERT_TRUE(response1 != NULL);
1067 EXPECT_TRUE(response1->headers != NULL);
1068 EXPECT_TRUE(response1->was_fetched_via_spdy);
1069 out.status_line = response1->headers->GetStatusLine();
1070 out.response_info = *response1;
1071 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1072 EXPECT_EQ(OK, out.rv);
1073 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1074 EXPECT_EQ("hello!hello!", out.response_data);
1076 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1077 out.status_line = response2->headers->GetStatusLine();
1078 out.response_info = *response2;
1079 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1080 EXPECT_EQ(OK, out.rv);
1081 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1082 EXPECT_EQ("hello!hello!", out.response_data);
1084 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1085 out.status_line = response3->headers->GetStatusLine();
1086 out.response_info = *response3;
1087 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1088 EXPECT_EQ(OK, out.rv);
1089 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1090 EXPECT_EQ("hello!hello!", out.response_data);
1092 helper.VerifyDataConsumed();
1094 EXPECT_EQ(OK, out.rv);
1097 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1098 // a fourth transaction. The third and fourth transactions have
1099 // different data ("hello!" vs "hello!hello!") and because of the
1100 // user specified priority, we expect to see them inverted in
1101 // the response from the server.
1102 TEST_P(SpdyNetworkTransactionSpdy3Test, FourGetsWithMaxConcurrentPriority) {
1103 // Construct the request.
1104 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1105 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1106 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
1107 scoped_ptr<SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
1109 scoped_ptr<SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
1110 scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
1111 scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
1112 scoped_ptr<SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
1114 scoped_ptr<SpdyFrame> req4(
1115 ConstructSpdyGet(NULL, 0, false, 5, HIGHEST));
1116 scoped_ptr<SpdyFrame> resp4(ConstructSpdyGetSynReply(NULL, 0, 5));
1117 scoped_ptr<SpdyFrame> fbody4(ConstructSpdyBodyFrame(5, true));
1119 scoped_ptr<SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 7, LOWEST));
1120 scoped_ptr<SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 7));
1121 scoped_ptr<SpdyFrame> body3(ConstructSpdyBodyFrame(7, false));
1122 scoped_ptr<SpdyFrame> fbody3(ConstructSpdyBodyFrame(7, true));
1124 SettingsMap settings;
1125 const uint32 max_concurrent_streams = 1;
1126 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1127 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1128 scoped_ptr<SpdyFrame> settings_frame(ConstructSpdySettings(settings));
1130 MockWrite writes[] = { CreateMockWrite(*req),
1131 CreateMockWrite(*req2),
1132 CreateMockWrite(*req4),
1133 CreateMockWrite(*req3),
1135 MockRead reads[] = {
1136 CreateMockRead(*settings_frame, 1),
1137 CreateMockRead(*resp),
1138 CreateMockRead(*body),
1139 CreateMockRead(*fbody),
1140 CreateMockRead(*resp2, 7),
1141 CreateMockRead(*body2),
1142 CreateMockRead(*fbody2),
1143 CreateMockRead(*resp4, 13),
1144 CreateMockRead(*fbody4),
1145 CreateMockRead(*resp3, 16),
1146 CreateMockRead(*body3),
1147 CreateMockRead(*fbody3),
1149 MockRead(ASYNC, 0, 0), // EOF
1152 OrderedSocketData data(reads, arraysize(reads),
1153 writes, arraysize(writes));
1154 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1156 BoundNetLog log;
1157 TransactionHelperResult out;
1158 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1159 BoundNetLog(), GetParam(), NULL);
1160 helper.RunPreTestSetup();
1161 helper.AddData(&data);
1162 // We require placeholder data because four get requests are sent out, so
1163 // there needs to be four sets of SSL connection data.
1164 helper.AddData(&data_placeholder);
1165 helper.AddData(&data_placeholder);
1166 helper.AddData(&data_placeholder);
1167 scoped_ptr<HttpNetworkTransaction> trans1(
1168 new HttpNetworkTransaction(helper.session()));
1169 scoped_ptr<HttpNetworkTransaction> trans2(
1170 new HttpNetworkTransaction(helper.session()));
1171 scoped_ptr<HttpNetworkTransaction> trans3(
1172 new HttpNetworkTransaction(helper.session()));
1173 scoped_ptr<HttpNetworkTransaction> trans4(
1174 new HttpNetworkTransaction(helper.session()));
1176 TestCompletionCallback callback1;
1177 TestCompletionCallback callback2;
1178 TestCompletionCallback callback3;
1179 TestCompletionCallback callback4;
1181 HttpRequestInfo httpreq1 = CreateGetRequest();
1182 HttpRequestInfo httpreq2 = CreateGetRequest();
1183 HttpRequestInfo httpreq3 = CreateGetRequest();
1184 HttpRequestInfo httpreq4 = CreateGetRequest();
1185 httpreq4.priority = HIGHEST;
1187 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1188 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1189 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1190 out.rv = callback1.WaitForResult();
1191 ASSERT_EQ(OK, out.rv);
1193 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1194 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1195 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1196 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1197 out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
1198 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1200 out.rv = callback2.WaitForResult();
1201 ASSERT_EQ(OK, out.rv);
1202 EXPECT_EQ(data.read_index(), 7U); // i.e. the third & fourth trans queued
1204 out.rv = callback3.WaitForResult();
1205 ASSERT_EQ(OK, out.rv);
1207 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1208 EXPECT_TRUE(response1->headers != NULL);
1209 EXPECT_TRUE(response1->was_fetched_via_spdy);
1210 out.status_line = response1->headers->GetStatusLine();
1211 out.response_info = *response1;
1212 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1213 EXPECT_EQ(OK, out.rv);
1214 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1215 EXPECT_EQ("hello!hello!", out.response_data);
1217 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1218 out.status_line = response2->headers->GetStatusLine();
1219 out.response_info = *response2;
1220 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1221 EXPECT_EQ(OK, out.rv);
1222 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1223 EXPECT_EQ("hello!hello!", out.response_data);
1225 // notice: response3 gets two hellos, response4 gets one
1226 // hello, so we know dequeuing priority was respected.
1227 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1228 out.status_line = response3->headers->GetStatusLine();
1229 out.response_info = *response3;
1230 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1231 EXPECT_EQ(OK, out.rv);
1232 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1233 EXPECT_EQ("hello!hello!", out.response_data);
1235 out.rv = callback4.WaitForResult();
1236 EXPECT_EQ(OK, out.rv);
1237 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
1238 out.status_line = response4->headers->GetStatusLine();
1239 out.response_info = *response4;
1240 out.rv = ReadTransaction(trans4.get(), &out.response_data);
1241 EXPECT_EQ(OK, out.rv);
1242 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1243 EXPECT_EQ("hello!", out.response_data);
1244 helper.VerifyDataConsumed();
1245 EXPECT_EQ(OK, out.rv);
1248 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1249 // deletes a session in the middle of the transaction to insure
1250 // that we properly remove pendingcreatestream objects from
1251 // the spdy_session
1252 TEST_P(SpdyNetworkTransactionSpdy3Test, ThreeGetsWithMaxConcurrentDelete) {
1253 // Construct the request.
1254 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1255 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1256 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
1257 scoped_ptr<SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
1259 scoped_ptr<SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
1260 scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
1261 scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
1262 scoped_ptr<SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
1264 SettingsMap settings;
1265 const uint32 max_concurrent_streams = 1;
1266 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1267 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1268 scoped_ptr<SpdyFrame> settings_frame(ConstructSpdySettings(settings));
1270 MockWrite writes[] = { CreateMockWrite(*req),
1271 CreateMockWrite(*req2),
1273 MockRead reads[] = {
1274 CreateMockRead(*settings_frame, 1),
1275 CreateMockRead(*resp),
1276 CreateMockRead(*body),
1277 CreateMockRead(*fbody),
1278 CreateMockRead(*resp2, 7),
1279 CreateMockRead(*body2),
1280 CreateMockRead(*fbody2),
1281 MockRead(ASYNC, 0, 0), // EOF
1284 OrderedSocketData data(reads, arraysize(reads),
1285 writes, arraysize(writes));
1286 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1288 BoundNetLog log;
1289 TransactionHelperResult out;
1290 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1291 BoundNetLog(), GetParam(), NULL);
1292 helper.RunPreTestSetup();
1293 helper.AddData(&data);
1294 // We require placeholder data because three get requests are sent out, so
1295 // there needs to be three sets of SSL connection data.
1296 helper.AddData(&data_placeholder);
1297 helper.AddData(&data_placeholder);
1298 scoped_ptr<HttpNetworkTransaction> trans1(
1299 new HttpNetworkTransaction(helper.session()));
1300 scoped_ptr<HttpNetworkTransaction> trans2(
1301 new HttpNetworkTransaction(helper.session()));
1302 scoped_ptr<HttpNetworkTransaction> trans3(
1303 new HttpNetworkTransaction(helper.session()));
1305 TestCompletionCallback callback1;
1306 TestCompletionCallback callback2;
1307 TestCompletionCallback callback3;
1309 HttpRequestInfo httpreq1 = CreateGetRequest();
1310 HttpRequestInfo httpreq2 = CreateGetRequest();
1311 HttpRequestInfo httpreq3 = CreateGetRequest();
1313 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1314 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1315 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1316 out.rv = callback1.WaitForResult();
1317 ASSERT_EQ(OK, out.rv);
1319 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1320 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1321 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1322 delete trans3.release();
1323 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1324 out.rv = callback2.WaitForResult();
1325 ASSERT_EQ(OK, out.rv);
1327 EXPECT_EQ(8U, data.read_index());
1329 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1330 ASSERT_TRUE(response1 != NULL);
1331 EXPECT_TRUE(response1->headers != NULL);
1332 EXPECT_TRUE(response1->was_fetched_via_spdy);
1333 out.status_line = response1->headers->GetStatusLine();
1334 out.response_info = *response1;
1335 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1336 EXPECT_EQ(OK, out.rv);
1337 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1338 EXPECT_EQ("hello!hello!", out.response_data);
1340 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1341 ASSERT_TRUE(response2 != NULL);
1342 out.status_line = response2->headers->GetStatusLine();
1343 out.response_info = *response2;
1344 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1345 EXPECT_EQ(OK, out.rv);
1346 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1347 EXPECT_EQ("hello!hello!", out.response_data);
1348 helper.VerifyDataConsumed();
1349 EXPECT_EQ(OK, out.rv);
1352 namespace {
1354 // The KillerCallback will delete the transaction on error as part of the
1355 // callback.
1356 class KillerCallback : public TestCompletionCallbackBase {
1357 public:
1358 explicit KillerCallback(HttpNetworkTransaction* transaction)
1359 : transaction_(transaction),
1360 ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
1361 base::Bind(&KillerCallback::OnComplete, base::Unretained(this)))) {
1364 virtual ~KillerCallback() {}
1366 const CompletionCallback& callback() const { return callback_; }
1368 private:
1369 void OnComplete(int result) {
1370 if (result < 0)
1371 delete transaction_;
1373 SetResult(result);
1376 HttpNetworkTransaction* transaction_;
1377 CompletionCallback callback_;
1380 } // namespace
1382 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1383 // closes the socket while we have a pending transaction waiting for
1384 // a pending stream creation. http://crbug.com/52901
1385 TEST_P(SpdyNetworkTransactionSpdy3Test, ThreeGetsWithMaxConcurrentSocketClose) {
1386 // Construct the request.
1387 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1388 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1389 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
1390 scoped_ptr<SpdyFrame> fin_body(ConstructSpdyBodyFrame(1, true));
1392 scoped_ptr<SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
1393 scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
1395 SettingsMap settings;
1396 const uint32 max_concurrent_streams = 1;
1397 settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
1398 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
1399 scoped_ptr<SpdyFrame> settings_frame(ConstructSpdySettings(settings));
1401 MockWrite writes[] = { CreateMockWrite(*req),
1402 CreateMockWrite(*req2),
1404 MockRead reads[] = {
1405 CreateMockRead(*settings_frame, 1),
1406 CreateMockRead(*resp),
1407 CreateMockRead(*body),
1408 CreateMockRead(*fin_body),
1409 CreateMockRead(*resp2, 7),
1410 MockRead(ASYNC, ERR_CONNECTION_RESET, 0), // Abort!
1413 OrderedSocketData data(reads, arraysize(reads),
1414 writes, arraysize(writes));
1415 OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
1417 BoundNetLog log;
1418 TransactionHelperResult out;
1419 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1420 BoundNetLog(), GetParam(), NULL);
1421 helper.RunPreTestSetup();
1422 helper.AddData(&data);
1423 // We require placeholder data because three get requests are sent out, so
1424 // there needs to be three sets of SSL connection data.
1425 helper.AddData(&data_placeholder);
1426 helper.AddData(&data_placeholder);
1427 HttpNetworkTransaction trans1(helper.session());
1428 HttpNetworkTransaction trans2(helper.session());
1429 HttpNetworkTransaction* trans3(new HttpNetworkTransaction(helper.session()));
1431 TestCompletionCallback callback1;
1432 TestCompletionCallback callback2;
1433 KillerCallback callback3(trans3);
1435 HttpRequestInfo httpreq1 = CreateGetRequest();
1436 HttpRequestInfo httpreq2 = CreateGetRequest();
1437 HttpRequestInfo httpreq3 = CreateGetRequest();
1439 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
1440 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1441 // Run transaction 1 through quickly to force a read of our SETTINGS frame.
1442 out.rv = callback1.WaitForResult();
1443 ASSERT_EQ(OK, out.rv);
1445 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
1446 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1447 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1448 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1449 out.rv = callback3.WaitForResult();
1450 ASSERT_EQ(ERR_ABORTED, out.rv);
1452 EXPECT_EQ(6U, data.read_index());
1454 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1455 ASSERT_TRUE(response1 != NULL);
1456 EXPECT_TRUE(response1->headers != NULL);
1457 EXPECT_TRUE(response1->was_fetched_via_spdy);
1458 out.status_line = response1->headers->GetStatusLine();
1459 out.response_info = *response1;
1460 out.rv = ReadTransaction(&trans1, &out.response_data);
1461 EXPECT_EQ(OK, out.rv);
1463 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1464 ASSERT_TRUE(response2 != NULL);
1465 out.status_line = response2->headers->GetStatusLine();
1466 out.response_info = *response2;
1467 out.rv = ReadTransaction(&trans2, &out.response_data);
1468 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1470 helper.VerifyDataConsumed();
1473 // Test that a simple PUT request works.
1474 TEST_P(SpdyNetworkTransactionSpdy3Test, Put) {
1475 // Setup the request
1476 HttpRequestInfo request;
1477 request.method = "PUT";
1478 request.url = GURL("http://www.google.com/");
1480 const SpdyHeaderInfo kSynStartHeader = {
1481 SYN_STREAM, // Kind = Syn
1482 1, // Stream ID
1483 0, // Associated stream ID
1484 ConvertRequestPriorityToSpdyPriority(LOWEST, 3), // Priority
1485 0, // Credential Slot
1486 CONTROL_FLAG_FIN, // Control Flags
1487 false, // Compressed
1488 INVALID, // Status
1489 NULL, // Data
1490 0, // Length
1491 DATA_FLAG_NONE // Data Flags
1493 const char* const kPutHeaders[] = {
1494 ":method", "PUT",
1495 ":path", "/",
1496 ":host", "www.google.com",
1497 ":scheme", "http",
1498 ":version", "HTTP/1.1",
1499 "content-length", "0"
1501 scoped_ptr<SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0,
1502 kPutHeaders, arraysize(kPutHeaders) / 2));
1503 MockWrite writes[] = {
1504 CreateMockWrite(*req)
1507 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1508 const SpdyHeaderInfo kSynReplyHeader = {
1509 SYN_REPLY, // Kind = SynReply
1510 1, // Stream ID
1511 0, // Associated stream ID
1512 ConvertRequestPriorityToSpdyPriority(LOWEST, 3), // Priority
1513 0, // Credential Slot
1514 CONTROL_FLAG_NONE, // Control Flags
1515 false, // Compressed
1516 INVALID, // Status
1517 NULL, // Data
1518 0, // Length
1519 DATA_FLAG_NONE // Data Flags
1521 static const char* const kStandardRespHeaders[] = {
1522 ":status", "200",
1523 ":version", "HTTP/1.1"
1524 "content-length", "1234"
1526 scoped_ptr<SpdyFrame> resp(ConstructSpdyPacket(kSynReplyHeader,
1527 NULL, 0, kStandardRespHeaders, arraysize(kStandardRespHeaders) / 2));
1528 MockRead reads[] = {
1529 CreateMockRead(*resp),
1530 CreateMockRead(*body),
1531 MockRead(ASYNC, 0, 0) // EOF
1534 DelayedSocketData data(1, reads, arraysize(reads),
1535 writes, arraysize(writes));
1536 NormalSpdyTransactionHelper helper(request,
1537 BoundNetLog(), GetParam(), NULL);
1538 helper.RunToCompletion(&data);
1539 TransactionHelperResult out = helper.output();
1541 EXPECT_EQ(OK, out.rv);
1542 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1545 // Test that a simple HEAD request works.
1546 TEST_P(SpdyNetworkTransactionSpdy3Test, Head) {
1547 // Setup the request
1548 HttpRequestInfo request;
1549 request.method = "HEAD";
1550 request.url = GURL("http://www.google.com/");
1552 const SpdyHeaderInfo kSynStartHeader = {
1553 SYN_STREAM, // Kind = Syn
1554 1, // Stream ID
1555 0, // Associated stream ID
1556 ConvertRequestPriorityToSpdyPriority(LOWEST, 3), // Priority
1557 0, // Credential Slot
1558 CONTROL_FLAG_FIN, // Control Flags
1559 false, // Compressed
1560 INVALID, // Status
1561 NULL, // Data
1562 0, // Length
1563 DATA_FLAG_NONE // Data Flags
1565 const char* const kHeadHeaders[] = {
1566 ":method", "HEAD",
1567 ":path", "/",
1568 ":host", "www.google.com",
1569 ":scheme", "http",
1570 ":version", "HTTP/1.1",
1571 "content-length", "0"
1573 scoped_ptr<SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0,
1574 kHeadHeaders, arraysize(kHeadHeaders) / 2));
1575 MockWrite writes[] = {
1576 CreateMockWrite(*req)
1579 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1580 const SpdyHeaderInfo kSynReplyHeader = {
1581 SYN_REPLY, // Kind = SynReply
1582 1, // Stream ID
1583 0, // Associated stream ID
1584 ConvertRequestPriorityToSpdyPriority(LOWEST, 3), // Priority
1585 0, // Credential Slot
1586 CONTROL_FLAG_NONE, // Control Flags
1587 false, // Compressed
1588 INVALID, // Status
1589 NULL, // Data
1590 0, // Length
1591 DATA_FLAG_NONE // Data Flags
1593 static const char* const kStandardRespHeaders[] = {
1594 ":status", "200",
1595 ":version", "HTTP/1.1"
1596 "content-length", "1234"
1598 scoped_ptr<SpdyFrame> resp(ConstructSpdyPacket(kSynReplyHeader,
1599 NULL, 0, kStandardRespHeaders, arraysize(kStandardRespHeaders) / 2));
1600 MockRead reads[] = {
1601 CreateMockRead(*resp),
1602 CreateMockRead(*body),
1603 MockRead(ASYNC, 0, 0) // EOF
1606 DelayedSocketData data(1, reads, arraysize(reads),
1607 writes, arraysize(writes));
1608 NormalSpdyTransactionHelper helper(request,
1609 BoundNetLog(), GetParam(), NULL);
1610 helper.RunToCompletion(&data);
1611 TransactionHelperResult out = helper.output();
1613 EXPECT_EQ(OK, out.rv);
1614 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1617 // Test that a simple POST works.
1618 TEST_P(SpdyNetworkTransactionSpdy3Test, Post) {
1619 scoped_ptr<SpdyFrame> req(ConstructSpdyPost(kUploadDataSize, NULL, 0));
1620 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1621 MockWrite writes[] = {
1622 CreateMockWrite(*req),
1623 CreateMockWrite(*body), // POST upload frame
1626 scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1627 MockRead reads[] = {
1628 CreateMockRead(*resp),
1629 CreateMockRead(*body),
1630 MockRead(ASYNC, 0, 0) // EOF
1633 DelayedSocketData data(2, reads, arraysize(reads),
1634 writes, arraysize(writes));
1635 NormalSpdyTransactionHelper helper(CreatePostRequest(),
1636 BoundNetLog(), GetParam(), NULL);
1637 helper.RunToCompletion(&data);
1638 TransactionHelperResult out = helper.output();
1639 EXPECT_EQ(OK, out.rv);
1640 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1641 EXPECT_EQ("hello!", out.response_data);
1644 // Test that a POST with a file works.
1645 TEST_P(SpdyNetworkTransactionSpdy3Test, FilePost) {
1646 scoped_ptr<SpdyFrame> req(ConstructSpdyPost(kUploadDataSize, NULL, 0));
1647 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1648 MockWrite writes[] = {
1649 CreateMockWrite(*req),
1650 CreateMockWrite(*body), // POST upload frame
1653 scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1654 MockRead reads[] = {
1655 CreateMockRead(*resp),
1656 CreateMockRead(*body),
1657 MockRead(ASYNC, 0, 0) // EOF
1660 DelayedSocketData data(2, reads, arraysize(reads),
1661 writes, arraysize(writes));
1663 NormalSpdyTransactionHelper helper(CreateFilePostRequest(),
1664 BoundNetLog(), GetParam(), NULL);
1665 helper.RunToCompletion(&data);
1666 TransactionHelperResult out = helper.output();
1667 EXPECT_EQ(OK, out.rv);
1668 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1669 EXPECT_EQ("hello!", out.response_data);
1672 // Test that a complex POST works.
1673 TEST_P(SpdyNetworkTransactionSpdy3Test, ComplexPost) {
1674 scoped_ptr<SpdyFrame> req(ConstructSpdyPost(kUploadDataSize, NULL, 0));
1675 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1676 MockWrite writes[] = {
1677 CreateMockWrite(*req),
1678 CreateMockWrite(*body), // POST upload frame
1681 scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1682 MockRead reads[] = {
1683 CreateMockRead(*resp),
1684 CreateMockRead(*body),
1685 MockRead(ASYNC, 0, 0) // EOF
1688 DelayedSocketData data(2, reads, arraysize(reads),
1689 writes, arraysize(writes));
1691 NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
1692 BoundNetLog(), GetParam(), NULL);
1693 helper.RunToCompletion(&data);
1694 TransactionHelperResult out = helper.output();
1695 EXPECT_EQ(OK, out.rv);
1696 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1697 EXPECT_EQ("hello!", out.response_data);
1700 // Test that a chunked POST works.
1701 TEST_P(SpdyNetworkTransactionSpdy3Test, ChunkedPost) {
1702 set_merge_chunks(false);
1704 scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
1705 scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
1706 scoped_ptr<SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true));
1707 MockWrite writes[] = {
1708 CreateMockWrite(*req),
1709 CreateMockWrite(*chunk1),
1710 CreateMockWrite(*chunk2),
1713 scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1714 MockRead reads[] = {
1715 CreateMockRead(*resp),
1716 CreateMockRead(*chunk1),
1717 CreateMockRead(*chunk2),
1718 MockRead(ASYNC, 0, 0) // EOF
1721 DelayedSocketData data(2, reads, arraysize(reads),
1722 writes, arraysize(writes));
1723 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1724 BoundNetLog(), GetParam(), NULL);
1725 helper.RunToCompletion(&data);
1726 TransactionHelperResult out = helper.output();
1727 EXPECT_EQ(OK, out.rv);
1728 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1729 EXPECT_EQ("hello!hello!", out.response_data);
1732 // Test that a POST without any post data works.
1733 TEST_P(SpdyNetworkTransactionSpdy3Test, NullPost) {
1734 // Setup the request
1735 HttpRequestInfo request;
1736 request.method = "POST";
1737 request.url = GURL("http://www.google.com/");
1738 // Create an empty UploadData.
1739 request.upload_data_stream = NULL;
1741 // When request.upload_data_stream is NULL for post, content-length is
1742 // expected to be 0.
1743 scoped_ptr<SpdyFrame> req(ConstructSpdyPost(0, NULL, 0));
1744 // Set the FIN bit since there will be no body.
1745 req->set_flags(CONTROL_FLAG_FIN);
1746 MockWrite writes[] = {
1747 CreateMockWrite(*req),
1750 scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1751 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1752 MockRead reads[] = {
1753 CreateMockRead(*resp),
1754 CreateMockRead(*body),
1755 MockRead(ASYNC, 0, 0) // EOF
1758 DelayedSocketData data(1, reads, arraysize(reads),
1759 writes, arraysize(writes));
1761 NormalSpdyTransactionHelper helper(request,
1762 BoundNetLog(), GetParam(), NULL);
1763 helper.RunToCompletion(&data);
1764 TransactionHelperResult out = helper.output();
1765 EXPECT_EQ(OK, out.rv);
1766 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1767 EXPECT_EQ("hello!", out.response_data);
1770 // Test that a simple POST works.
1771 TEST_P(SpdyNetworkTransactionSpdy3Test, EmptyPost) {
1772 // Create an empty UploadDataStream.
1773 ScopedVector<UploadElementReader> element_readers;
1774 UploadDataStream stream(&element_readers, 0);
1776 // Setup the request
1777 HttpRequestInfo request;
1778 request.method = "POST";
1779 request.url = GURL("http://www.google.com/");
1780 request.upload_data_stream = &stream;
1782 const uint64 kContentLength = 0;
1783 scoped_ptr<SpdyFrame> req(ConstructSpdyPost(kContentLength, NULL, 0));
1784 // Set the FIN bit since there will be no body.
1785 req->set_flags(CONTROL_FLAG_FIN);
1786 MockWrite writes[] = {
1787 CreateMockWrite(*req),
1790 scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1791 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1792 MockRead reads[] = {
1793 CreateMockRead(*resp),
1794 CreateMockRead(*body),
1795 MockRead(ASYNC, 0, 0) // EOF
1798 DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
1800 NormalSpdyTransactionHelper helper(request, BoundNetLog(), GetParam(), NULL);
1801 helper.RunToCompletion(&data);
1802 TransactionHelperResult out = helper.output();
1803 EXPECT_EQ(OK, out.rv);
1804 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1805 EXPECT_EQ("hello!", out.response_data);
1808 // While we're doing a post, the server sends back a SYN_REPLY.
1809 TEST_P(SpdyNetworkTransactionSpdy3Test, PostWithEarlySynReply) {
1810 static const char upload[] = { "hello!" };
1811 ScopedVector<UploadElementReader> element_readers;
1812 element_readers.push_back(
1813 new UploadBytesElementReader(upload, sizeof(upload)));
1814 UploadDataStream stream(&element_readers, 0);
1816 // Setup the request
1817 HttpRequestInfo request;
1818 request.method = "POST";
1819 request.url = GURL("http://www.google.com/");
1820 request.upload_data_stream = &stream;
1822 scoped_ptr<SpdyFrame> stream_reply(ConstructSpdyPostSynReply(NULL, 0));
1823 scoped_ptr<SpdyFrame> stream_body(ConstructSpdyBodyFrame(1, true));
1824 MockRead reads[] = {
1825 CreateMockRead(*stream_reply, 1),
1826 MockRead(ASYNC, 0, 3) // EOF
1829 scoped_ptr<SpdyFrame> req(ConstructSpdyPost(kUploadDataSize, NULL, 0));
1830 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1831 MockWrite writes[] = {
1832 CreateMockWrite(*req, 0),
1833 CreateMockWrite(*body, 2),
1836 DeterministicSocketData data(reads, arraysize(reads),
1837 writes, arraysize(writes));
1838 NormalSpdyTransactionHelper helper(CreatePostRequest(),
1839 BoundNetLog(), GetParam(), NULL);
1840 helper.SetDeterministic();
1841 helper.RunPreTestSetup();
1842 helper.AddDeterministicData(&data);
1843 HttpNetworkTransaction* trans = helper.trans();
1845 TestCompletionCallback callback;
1846 int rv = trans->Start(
1847 &CreatePostRequest(), callback.callback(), BoundNetLog());
1848 EXPECT_EQ(ERR_IO_PENDING, rv);
1850 data.RunFor(2);
1851 rv = callback.WaitForResult();
1852 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
1853 data.RunFor(1);
1856 // The client upon cancellation tries to send a RST_STREAM frame. The mock
1857 // socket causes the TCP write to return zero. This test checks that the client
1858 // tries to queue up the RST_STREAM frame again.
1859 TEST_P(SpdyNetworkTransactionSpdy3Test, SocketWriteReturnsZero) {
1860 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1861 scoped_ptr<SpdyFrame> rst(
1862 ConstructSpdyRstStream(1, CANCEL));
1863 MockWrite writes[] = {
1864 CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
1865 MockWrite(SYNCHRONOUS, 0, 0, 2),
1866 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
1869 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1870 MockRead reads[] = {
1871 CreateMockRead(*resp.get(), 1, ASYNC),
1872 MockRead(ASYNC, 0, 0, 4) // EOF
1875 DeterministicSocketData data(reads, arraysize(reads),
1876 writes, arraysize(writes));
1877 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1878 BoundNetLog(), GetParam(), NULL);
1879 helper.SetDeterministic();
1880 helper.RunPreTestSetup();
1881 helper.AddDeterministicData(&data);
1882 HttpNetworkTransaction* trans = helper.trans();
1884 TestCompletionCallback callback;
1885 int rv = trans->Start(
1886 &CreateGetRequest(), callback.callback(), BoundNetLog());
1887 EXPECT_EQ(ERR_IO_PENDING, rv);
1889 data.SetStop(2);
1890 data.Run();
1891 helper.ResetTrans();
1892 data.SetStop(20);
1893 data.Run();
1895 helper.VerifyDataConsumed();
1898 // Test that the transaction doesn't crash when we don't have a reply.
1899 TEST_P(SpdyNetworkTransactionSpdy3Test, ResponseWithoutSynReply) {
1900 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1901 MockRead reads[] = {
1902 CreateMockRead(*body),
1903 MockRead(ASYNC, 0, 0) // EOF
1906 DelayedSocketData data(1, reads, arraysize(reads), NULL, 0);
1907 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1908 BoundNetLog(), GetParam(), NULL);
1909 helper.RunToCompletion(&data);
1910 TransactionHelperResult out = helper.output();
1911 EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED, out.rv);
1914 // Test that the transaction doesn't crash when we get two replies on the same
1915 // stream ID. See http://crbug.com/45639.
1916 TEST_P(SpdyNetworkTransactionSpdy3Test, ResponseWithTwoSynReplies) {
1917 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1918 MockWrite writes[] = { CreateMockWrite(*req) };
1920 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1921 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1922 MockRead reads[] = {
1923 CreateMockRead(*resp),
1924 CreateMockRead(*resp),
1925 CreateMockRead(*body),
1926 MockRead(ASYNC, 0, 0) // EOF
1929 DelayedSocketData data(1, reads, arraysize(reads),
1930 writes, arraysize(writes));
1932 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1933 BoundNetLog(), GetParam(), NULL);
1934 helper.RunPreTestSetup();
1935 helper.AddData(&data);
1937 HttpNetworkTransaction* trans = helper.trans();
1939 TestCompletionCallback callback;
1940 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
1941 EXPECT_EQ(ERR_IO_PENDING, rv);
1942 rv = callback.WaitForResult();
1943 EXPECT_EQ(OK, rv);
1945 const HttpResponseInfo* response = trans->GetResponseInfo();
1946 ASSERT_TRUE(response != NULL);
1947 EXPECT_TRUE(response->headers != NULL);
1948 EXPECT_TRUE(response->was_fetched_via_spdy);
1949 std::string response_data;
1950 rv = ReadTransaction(trans, &response_data);
1951 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
1953 helper.VerifyDataConsumed();
1956 // Test that sent data frames and received WINDOW_UPDATE frames change
1957 // the send_window_size_ correctly.
1959 // WINDOW_UPDATE is different than most other frames in that it can arrive
1960 // while the client is still sending the request body. In order to enforce
1961 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
1962 // socket data provider, so that initial read that is done as soon as the
1963 // stream is created, succeeds and schedules another read. This way reads
1964 // and writes are interleaved; after doing a full frame write, SpdyStream
1965 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
1966 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
1967 // since request has not been completely written, therefore we feed
1968 // enough number of WINDOW_UPDATEs to finish the first read and cause a
1969 // write, leading to a complete write of request body; after that we send
1970 // a reply with a body, to cause a graceful shutdown.
1972 // TODO(agayev): develop a socket data provider where both, reads and
1973 // writes are ordered so that writing tests like these are easy and rewrite
1974 // all these tests using it. Right now we are working around the
1975 // limitations as described above and it's not deterministic, tests may
1976 // fail under specific circumstances.
1977 TEST_P(SpdyNetworkTransactionSpdy3Test, WindowUpdateReceived) {
1978 static int kFrameCount = 2;
1979 scoped_ptr<std::string> content(
1980 new std::string(kMaxSpdyFrameChunkSize, 'a'));
1981 scoped_ptr<SpdyFrame> req(ConstructSpdyPost(
1982 kMaxSpdyFrameChunkSize * kFrameCount, NULL, 0));
1983 scoped_ptr<SpdyFrame> body(
1984 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
1985 scoped_ptr<SpdyFrame> body_end(
1986 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), true));
1988 MockWrite writes[] = {
1989 CreateMockWrite(*req),
1990 CreateMockWrite(*body),
1991 CreateMockWrite(*body_end),
1994 static const int32 kDeltaWindowSize = 0xff;
1995 static const int kDeltaCount = 4;
1996 scoped_ptr<SpdyFrame> window_update(
1997 ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
1998 scoped_ptr<SpdyFrame> window_update_dummy(
1999 ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
2000 scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
2001 MockRead reads[] = {
2002 CreateMockRead(*window_update_dummy),
2003 CreateMockRead(*window_update_dummy),
2004 CreateMockRead(*window_update_dummy),
2005 CreateMockRead(*window_update), // Four updates, therefore window
2006 CreateMockRead(*window_update), // size should increase by
2007 CreateMockRead(*window_update), // kDeltaWindowSize * 4
2008 CreateMockRead(*window_update),
2009 CreateMockRead(*resp),
2010 CreateMockRead(*body_end),
2011 MockRead(ASYNC, 0, 0) // EOF
2014 DelayedSocketData data(0, reads, arraysize(reads),
2015 writes, arraysize(writes));
2017 ScopedVector<UploadElementReader> element_readers;
2018 for (int i = 0; i < kFrameCount; ++i) {
2019 element_readers.push_back(
2020 new UploadBytesElementReader(content->c_str(), content->size()));
2022 UploadDataStream upload_data_stream(&element_readers, 0);
2024 // Setup the request
2025 HttpRequestInfo request;
2026 request.method = "POST";
2027 request.url = GURL(kDefaultURL);
2028 request.upload_data_stream = &upload_data_stream;
2030 NormalSpdyTransactionHelper helper(request, BoundNetLog(), GetParam(), NULL);
2031 helper.AddData(&data);
2032 helper.RunPreTestSetup();
2034 HttpNetworkTransaction* trans = helper.trans();
2036 TestCompletionCallback callback;
2037 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2039 EXPECT_EQ(ERR_IO_PENDING, rv);
2040 rv = callback.WaitForResult();
2041 EXPECT_EQ(OK, rv);
2043 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
2044 ASSERT_TRUE(stream != NULL);
2045 ASSERT_TRUE(stream->stream() != NULL);
2046 EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize) +
2047 kDeltaWindowSize * kDeltaCount -
2048 kMaxSpdyFrameChunkSize * kFrameCount,
2049 stream->stream()->send_window_size());
2050 helper.VerifyDataConsumed();
2053 // Test that received data frames and sent WINDOW_UPDATE frames change
2054 // the recv_window_size_ correctly.
2055 TEST_P(SpdyNetworkTransactionSpdy3Test, WindowUpdateSent) {
2056 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2057 scoped_ptr<SpdyFrame> window_update(
2058 ConstructSpdyWindowUpdate(1, kUploadDataSize));
2060 MockWrite writes[] = {
2061 CreateMockWrite(*req),
2062 CreateMockWrite(*window_update),
2065 scoped_ptr<SpdyFrame> resp(
2066 ConstructSpdyGetSynReply(NULL, 0, 1));
2067 scoped_ptr<SpdyFrame> body_no_fin(
2068 ConstructSpdyBodyFrame(1, false));
2069 scoped_ptr<SpdyFrame> body_fin(
2070 ConstructSpdyBodyFrame(1, NULL, 0, true));
2071 MockRead reads[] = {
2072 CreateMockRead(*resp),
2073 CreateMockRead(*body_no_fin),
2074 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause
2075 CreateMockRead(*body_fin),
2076 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause
2077 MockRead(ASYNC, 0, 0) // EOF
2080 DelayedSocketData data(1, reads, arraysize(reads),
2081 writes, arraysize(writes));
2083 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2084 BoundNetLog(), GetParam(), NULL);
2085 helper.AddData(&data);
2086 helper.RunPreTestSetup();
2087 HttpNetworkTransaction* trans = helper.trans();
2089 TestCompletionCallback callback;
2090 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2092 EXPECT_EQ(ERR_IO_PENDING, rv);
2093 rv = callback.WaitForResult();
2094 EXPECT_EQ(OK, rv);
2096 SpdyHttpStream* stream =
2097 static_cast<SpdyHttpStream*>(trans->stream_.get());
2098 ASSERT_TRUE(stream != NULL);
2099 ASSERT_TRUE(stream->stream() != NULL);
2101 EXPECT_EQ(
2102 static_cast<int>(kSpdyStreamInitialWindowSize) - kUploadDataSize,
2103 stream->stream()->recv_window_size());
2105 const HttpResponseInfo* response = trans->GetResponseInfo();
2106 ASSERT_TRUE(response != NULL);
2107 ASSERT_TRUE(response->headers != NULL);
2108 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2109 EXPECT_TRUE(response->was_fetched_via_spdy);
2111 // Force sending of WINDOW_UPDATE by setting initial_recv_window_size to a
2112 // small value.
2113 stream->stream()->set_initial_recv_window_size(kUploadDataSize / 2);
2115 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
2116 // size increased to default.
2117 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kUploadDataSize));
2118 rv = trans->Read(buf, kUploadDataSize, CompletionCallback());
2119 EXPECT_EQ(kUploadDataSize, rv);
2120 std::string content(buf->data(), buf->data()+kUploadDataSize);
2121 EXPECT_STREQ(kUploadData, content.c_str());
2123 // Schedule the reading of empty data frame with FIN
2124 data.CompleteRead();
2126 // Force write of WINDOW_UPDATE which was scheduled during the above
2127 // read.
2128 MessageLoop::current()->RunUntilIdle();
2130 // Read EOF.
2131 data.CompleteRead();
2133 helper.VerifyDataConsumed();
2136 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.
2137 TEST_P(SpdyNetworkTransactionSpdy3Test, WindowUpdateOverflow) {
2138 // Number of full frames we hope to write (but will not, used to
2139 // set content-length header correctly)
2140 static int kFrameCount = 3;
2142 scoped_ptr<std::string> content(
2143 new std::string(kMaxSpdyFrameChunkSize, 'a'));
2144 scoped_ptr<SpdyFrame> req(ConstructSpdyPost(
2145 kMaxSpdyFrameChunkSize * kFrameCount, NULL, 0));
2146 scoped_ptr<SpdyFrame> body(
2147 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
2148 scoped_ptr<SpdyFrame> rst(
2149 ConstructSpdyRstStream(1, FLOW_CONTROL_ERROR));
2151 // We're not going to write a data frame with FIN, we'll receive a bad
2152 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
2153 MockWrite writes[] = {
2154 CreateMockWrite(*req, 0),
2155 CreateMockWrite(*body, 2),
2156 CreateMockWrite(*rst, 3),
2159 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow
2160 scoped_ptr<SpdyFrame> window_update(
2161 ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
2162 MockRead reads[] = {
2163 CreateMockRead(*window_update, 1),
2164 MockRead(ASYNC, 0, 4) // EOF
2167 DeterministicSocketData data(reads, arraysize(reads),
2168 writes, arraysize(writes));
2170 ScopedVector<UploadElementReader> element_readers;
2171 for (int i = 0; i < kFrameCount; ++i) {
2172 element_readers.push_back(
2173 new UploadBytesElementReader(content->c_str(), content->size()));
2175 UploadDataStream upload_data_stream(&element_readers, 0);
2177 // Setup the request
2178 HttpRequestInfo request;
2179 request.method = "POST";
2180 request.url = GURL("http://www.google.com/");
2181 request.upload_data_stream = &upload_data_stream;
2183 NormalSpdyTransactionHelper helper(request,
2184 BoundNetLog(), GetParam(), NULL);
2185 helper.SetDeterministic();
2186 helper.RunPreTestSetup();
2187 helper.AddDeterministicData(&data);
2188 HttpNetworkTransaction* trans = helper.trans();
2190 TestCompletionCallback callback;
2191 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2192 ASSERT_EQ(ERR_IO_PENDING, rv);
2194 data.RunFor(5);
2195 ASSERT_TRUE(callback.have_result());
2196 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
2197 helper.VerifyDataConsumed();
2200 // Test that after hitting a send window size of 0, the write process
2201 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
2203 // This test constructs a POST request followed by enough data frames
2204 // containing 'a' that would make the window size 0, followed by another
2205 // data frame containing default content (which is "hello!") and this frame
2206 // also contains a FIN flag. DelayedSocketData is used to enforce all
2207 // writes go through before a read could happen. However, the last frame
2208 // ("hello!") is not supposed to go through since by the time its turn
2209 // arrives, window size is 0. At this point MessageLoop::Run() called via
2210 // callback would block. Therefore we call MessageLoop::RunUntilIdle()
2211 // which returns after performing all possible writes. We use DCHECKS to
2212 // ensure that last data frame is still there and stream has stalled.
2213 // After that, next read is artifically enforced, which causes a
2214 // WINDOW_UPDATE to be read and I/O process resumes.
2215 TEST_P(SpdyNetworkTransactionSpdy3Test, FlowControlStallResume) {
2216 // Number of frames we need to send to zero out the window size: data
2217 // frames plus SYN_STREAM plus the last data frame; also we need another
2218 // data frame that we will send once the WINDOW_UPDATE is received,
2219 // therefore +3.
2220 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
2222 // Calculate last frame's size; 0 size data frame is legal.
2223 size_t last_frame_size =
2224 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
2226 // Construct content for a data frame of maximum size.
2227 std::string content(kMaxSpdyFrameChunkSize, 'a');
2229 scoped_ptr<SpdyFrame> req(ConstructSpdyPost(
2230 kSpdyStreamInitialWindowSize + kUploadDataSize, NULL, 0));
2232 // Full frames.
2233 scoped_ptr<SpdyFrame> body1(
2234 ConstructSpdyBodyFrame(1, content.c_str(), content.size(), false));
2236 // Last frame to zero out the window size.
2237 scoped_ptr<SpdyFrame> body2(
2238 ConstructSpdyBodyFrame(1, content.c_str(), last_frame_size, false));
2240 // Data frame to be sent once WINDOW_UPDATE frame is received.
2241 scoped_ptr<SpdyFrame> body3(ConstructSpdyBodyFrame(1, true));
2243 // Fill in mock writes.
2244 scoped_array<MockWrite> writes(new MockWrite[num_writes]);
2245 size_t i = 0;
2246 writes[i] = CreateMockWrite(*req);
2247 for (i = 1; i < num_writes - 2; i++)
2248 writes[i] = CreateMockWrite(*body1);
2249 writes[i++] = CreateMockWrite(*body2);
2250 writes[i] = CreateMockWrite(*body3);
2252 // Construct read frame, give enough space to upload the rest of the
2253 // data.
2254 scoped_ptr<SpdyFrame> window_update(
2255 ConstructSpdyWindowUpdate(1, kUploadDataSize));
2256 scoped_ptr<SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
2257 MockRead reads[] = {
2258 CreateMockRead(*window_update),
2259 CreateMockRead(*window_update),
2260 CreateMockRead(*reply),
2261 CreateMockRead(*body2),
2262 CreateMockRead(*body3),
2263 MockRead(ASYNC, 0, 0) // EOF
2266 // Force all writes to happen before any read, last write will not
2267 // actually queue a frame, due to window size being 0.
2268 DelayedSocketData data(num_writes, reads, arraysize(reads),
2269 writes.get(), num_writes);
2271 ScopedVector<UploadElementReader> element_readers;
2272 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
2273 upload_data_string.append(kUploadData, kUploadDataSize);
2274 element_readers.push_back(new UploadBytesElementReader(
2275 upload_data_string.c_str(), upload_data_string.size()));
2276 UploadDataStream upload_data_stream(&element_readers, 0);
2278 HttpRequestInfo request;
2279 request.method = "POST";
2280 request.url = GURL("http://www.google.com/");
2281 request.upload_data_stream = &upload_data_stream;
2282 NormalSpdyTransactionHelper helper(request, BoundNetLog(), GetParam(), NULL);
2283 helper.AddData(&data);
2284 helper.RunPreTestSetup();
2286 HttpNetworkTransaction* trans = helper.trans();
2288 TestCompletionCallback callback;
2289 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2290 EXPECT_EQ(ERR_IO_PENDING, rv);
2292 MessageLoop::current()->RunUntilIdle(); // Write as much as we can.
2294 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
2295 ASSERT_TRUE(stream != NULL);
2296 ASSERT_TRUE(stream->stream() != NULL);
2297 EXPECT_EQ(0, stream->stream()->send_window_size());
2298 // All the body data should have been read.
2299 // TODO(satorux): This is because of the weirdness in reading the request
2300 // body in OnSendBodyComplete(). See crbug.com/113107.
2301 EXPECT_TRUE(upload_data_stream.IsEOF());
2302 // But the body is not yet fully sent (kUploadData is not yet sent).
2303 EXPECT_FALSE(stream->stream()->body_sent());
2305 data.ForceNextRead(); // Read in WINDOW_UPDATE frame.
2306 rv = callback.WaitForResult();
2307 helper.VerifyDataConsumed();
2310 // Test we correctly handle the case where the SETTINGS frame results in
2311 // unstalling the send window.
2312 TEST_P(SpdyNetworkTransactionSpdy3Test, FlowControlStallResumeAfterSettings) {
2313 // Number of frames we need to send to zero out the window size: data
2314 // frames plus SYN_STREAM plus the last data frame; also we need another
2315 // data frame that we will send once the SETTING is received, therefore +3.
2316 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
2318 // Calculate last frame's size; 0 size data frame is legal.
2319 size_t last_frame_size =
2320 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
2322 // Construct content for a data frame of maximum size.
2323 std::string content(kMaxSpdyFrameChunkSize, 'a');
2325 scoped_ptr<SpdyFrame> req(ConstructSpdyPost(
2326 kSpdyStreamInitialWindowSize + kUploadDataSize, NULL, 0));
2328 // Full frames.
2329 scoped_ptr<SpdyFrame> body1(
2330 ConstructSpdyBodyFrame(1, content.c_str(), content.size(), false));
2332 // Last frame to zero out the window size.
2333 scoped_ptr<SpdyFrame> body2(
2334 ConstructSpdyBodyFrame(1, content.c_str(), last_frame_size, false));
2336 // Data frame to be sent once SETTINGS frame is received.
2337 scoped_ptr<SpdyFrame> body3(ConstructSpdyBodyFrame(1, true));
2339 // Fill in mock writes.
2340 scoped_array<MockWrite> writes(new MockWrite[num_writes]);
2341 size_t i = 0;
2342 writes[i] = CreateMockWrite(*req);
2343 for (i = 1; i < num_writes - 2; i++)
2344 writes[i] = CreateMockWrite(*body1);
2345 writes[i++] = CreateMockWrite(*body2);
2346 writes[i] = CreateMockWrite(*body3);
2348 // Construct read frame for SETTINGS that gives enough space to upload the
2349 // rest of the data.
2350 SettingsMap settings;
2351 settings[SETTINGS_INITIAL_WINDOW_SIZE] =
2352 SettingsFlagsAndValue(
2353 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize * 2);
2354 scoped_ptr<SpdyFrame> settings_frame_large(ConstructSpdySettings(settings));
2355 scoped_ptr<SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
2356 MockRead reads[] = {
2357 CreateMockRead(*settings_frame_large),
2358 CreateMockRead(*reply),
2359 CreateMockRead(*body2),
2360 CreateMockRead(*body3),
2361 MockRead(ASYNC, 0, 0) // EOF
2364 // Force all writes to happen before any read, last write will not
2365 // actually queue a frame, due to window size being 0.
2366 DelayedSocketData data(num_writes, reads, arraysize(reads),
2367 writes.get(), num_writes);
2369 ScopedVector<UploadElementReader> element_readers;
2370 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
2371 upload_data_string.append(kUploadData, kUploadDataSize);
2372 element_readers.push_back(new UploadBytesElementReader(
2373 upload_data_string.c_str(), upload_data_string.size()));
2374 UploadDataStream upload_data_stream(&element_readers, 0);
2376 HttpRequestInfo request;
2377 request.method = "POST";
2378 request.url = GURL("http://www.google.com/");
2379 request.upload_data_stream = &upload_data_stream;
2380 NormalSpdyTransactionHelper helper(request, BoundNetLog(), GetParam(), NULL);
2381 helper.AddData(&data);
2382 helper.RunPreTestSetup();
2384 HttpNetworkTransaction* trans = helper.trans();
2386 TestCompletionCallback callback;
2387 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2388 EXPECT_EQ(ERR_IO_PENDING, rv);
2390 MessageLoop::current()->RunUntilIdle(); // Write as much as we can.
2392 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
2393 ASSERT_TRUE(stream != NULL);
2394 ASSERT_TRUE(stream->stream() != NULL);
2395 EXPECT_EQ(0, stream->stream()->send_window_size());
2397 // All the body data should have been read.
2398 // TODO(satorux): This is because of the weirdness in reading the request
2399 // body in OnSendBodyComplete(). See crbug.com/113107.
2400 EXPECT_TRUE(upload_data_stream.IsEOF());
2401 // But the body is not yet fully sent (kUploadData is not yet sent).
2402 EXPECT_FALSE(stream->stream()->body_sent());
2403 EXPECT_TRUE(stream->stream()->stalled_by_flow_control());
2405 data.ForceNextRead(); // Read in SETTINGS frame to unstall.
2406 rv = callback.WaitForResult();
2407 helper.VerifyDataConsumed();
2408 EXPECT_FALSE(stream->stream()->stalled_by_flow_control());
2411 // Test we correctly handle the case where the SETTINGS frame results in a
2412 // negative send window size.
2413 TEST_P(SpdyNetworkTransactionSpdy3Test, FlowControlNegativeSendWindowSize) {
2414 // Number of frames we need to send to zero out the window size: data
2415 // frames plus SYN_STREAM plus the last data frame; also we need another
2416 // data frame that we will send once the SETTING is received, therefore +3.
2417 size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
2419 // Calculate last frame's size; 0 size data frame is legal.
2420 size_t last_frame_size =
2421 kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
2423 // Construct content for a data frame of maximum size.
2424 std::string content(kMaxSpdyFrameChunkSize, 'a');
2426 scoped_ptr<SpdyFrame> req(ConstructSpdyPost(
2427 kSpdyStreamInitialWindowSize + kUploadDataSize, NULL, 0));
2429 // Full frames.
2430 scoped_ptr<SpdyFrame> body1(
2431 ConstructSpdyBodyFrame(1, content.c_str(), content.size(), false));
2433 // Last frame to zero out the window size.
2434 scoped_ptr<SpdyFrame> body2(
2435 ConstructSpdyBodyFrame(1, content.c_str(), last_frame_size, false));
2437 // Data frame to be sent once SETTINGS frame is received.
2438 scoped_ptr<SpdyFrame> body3(ConstructSpdyBodyFrame(1, true));
2440 // Fill in mock writes.
2441 scoped_array<MockWrite> writes(new MockWrite[num_writes]);
2442 size_t i = 0;
2443 writes[i] = CreateMockWrite(*req);
2444 for (i = 1; i < num_writes - 2; i++)
2445 writes[i] = CreateMockWrite(*body1);
2446 writes[i++] = CreateMockWrite(*body2);
2447 writes[i] = CreateMockWrite(*body3);
2449 // Construct read frame for SETTINGS that makes the send_window_size
2450 // negative.
2451 SettingsMap new_settings;
2452 new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
2453 SettingsFlagsAndValue(
2454 SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize / 2);
2455 scoped_ptr<SpdyFrame> settings_frame_small(
2456 ConstructSpdySettings(new_settings));
2457 // Construct read frame for WINDOW_UPDATE that makes the send_window_size
2458 // postive.
2459 scoped_ptr<SpdyFrame> window_update_init_size(
2460 ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize));
2461 scoped_ptr<SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
2462 MockRead reads[] = {
2463 CreateMockRead(*settings_frame_small),
2464 CreateMockRead(*window_update_init_size),
2465 CreateMockRead(*reply),
2466 CreateMockRead(*body2),
2467 CreateMockRead(*body3),
2468 MockRead(ASYNC, 0, 0) // EOF
2471 // Force all writes to happen before any read, last write will not actually
2472 // queue a frame, due to window size being 0.
2473 DelayedSocketData data(num_writes, reads, arraysize(reads),
2474 writes.get(), num_writes);
2476 ScopedVector<UploadElementReader> element_readers;
2477 std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
2478 upload_data_string.append(kUploadData, kUploadDataSize);
2479 element_readers.push_back(new UploadBytesElementReader(
2480 upload_data_string.c_str(), upload_data_string.size()));
2481 UploadDataStream upload_data_stream(&element_readers, 0);
2483 HttpRequestInfo request;
2484 request.method = "POST";
2485 request.url = GURL("http://www.google.com/");
2486 request.upload_data_stream = &upload_data_stream;
2487 NormalSpdyTransactionHelper helper(request, BoundNetLog(), GetParam(), NULL);
2488 helper.AddData(&data);
2489 helper.RunPreTestSetup();
2491 HttpNetworkTransaction* trans = helper.trans();
2493 TestCompletionCallback callback;
2494 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2495 EXPECT_EQ(ERR_IO_PENDING, rv);
2497 MessageLoop::current()->RunUntilIdle(); // Write as much as we can.
2499 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
2500 ASSERT_TRUE(stream != NULL);
2501 ASSERT_TRUE(stream->stream() != NULL);
2502 EXPECT_EQ(0, stream->stream()->send_window_size());
2504 // All the body data should have been read.
2505 // TODO(satorux): This is because of the weirdness in reading the request
2506 // body in OnSendBodyComplete(). See crbug.com/113107.
2507 EXPECT_TRUE(upload_data_stream.IsEOF());
2508 // But the body is not yet fully sent (kUploadData is not yet sent).
2509 EXPECT_FALSE(stream->stream()->body_sent());
2511 data.ForceNextRead(); // Read in WINDOW_UPDATE or SETTINGS frame.
2512 rv = callback.WaitForResult();
2513 helper.VerifyDataConsumed();
2516 TEST_P(SpdyNetworkTransactionSpdy3Test, ResetReplyWithTransferEncoding) {
2517 // Construct the request.
2518 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2519 scoped_ptr<SpdyFrame> rst(ConstructSpdyRstStream(1, PROTOCOL_ERROR));
2520 MockWrite writes[] = {
2521 CreateMockWrite(*req),
2522 CreateMockWrite(*rst),
2525 const char* const headers[] = {
2526 "transfer-encoding", "chuncked"
2528 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(headers, 1, 1));
2529 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2530 MockRead reads[] = {
2531 CreateMockRead(*resp),
2532 CreateMockRead(*body),
2533 MockRead(ASYNC, 0, 0) // EOF
2536 DelayedSocketData data(1, reads, arraysize(reads),
2537 writes, arraysize(writes));
2538 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2539 BoundNetLog(), GetParam(), NULL);
2540 helper.RunToCompletion(&data);
2541 TransactionHelperResult out = helper.output();
2542 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2544 helper.session()->spdy_session_pool()->CloseAllSessions();
2545 helper.VerifyDataConsumed();
2548 TEST_P(SpdyNetworkTransactionSpdy3Test, ResetPushWithTransferEncoding) {
2549 // Construct the request.
2550 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2551 scoped_ptr<SpdyFrame> rst(ConstructSpdyRstStream(2, PROTOCOL_ERROR));
2552 MockWrite writes[] = {
2553 CreateMockWrite(*req),
2554 CreateMockWrite(*rst),
2557 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2558 const char* const headers[] = {":scheme", "http",
2559 ":host", "www.google.com",
2560 ":path", "/1",
2561 "transfer-encoding", "chunked"};
2562 scoped_ptr<SpdyFrame> push(ConstructSpdyPush(headers, arraysize(headers) / 2,
2563 2, 1));
2564 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2565 MockRead reads[] = {
2566 CreateMockRead(*resp),
2567 CreateMockRead(*push),
2568 CreateMockRead(*body),
2569 MockRead(ASYNC, 0, 0) // EOF
2572 DelayedSocketData data(1, reads, arraysize(reads),
2573 writes, arraysize(writes));
2574 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2575 BoundNetLog(), GetParam(), NULL);
2576 helper.RunToCompletion(&data);
2577 TransactionHelperResult out = helper.output();
2578 EXPECT_EQ(OK, out.rv);
2579 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2580 EXPECT_EQ("hello!", out.response_data);
2582 helper.session()->spdy_session_pool()->CloseAllSessions();
2583 helper.VerifyDataConsumed();
2586 TEST_P(SpdyNetworkTransactionSpdy3Test, CancelledTransaction) {
2587 // Construct the request.
2588 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2589 MockWrite writes[] = {
2590 CreateMockWrite(*req),
2593 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2594 MockRead reads[] = {
2595 CreateMockRead(*resp),
2596 // This following read isn't used by the test, except during the
2597 // RunUntilIdle() call at the end since the SpdySession survives the
2598 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2599 // MockRead will do here.
2600 MockRead(ASYNC, 0, 0) // EOF
2603 StaticSocketDataProvider data(reads, arraysize(reads),
2604 writes, arraysize(writes));
2606 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2607 BoundNetLog(), GetParam(), NULL);
2608 helper.RunPreTestSetup();
2609 helper.AddData(&data);
2610 HttpNetworkTransaction* trans = helper.trans();
2612 TestCompletionCallback callback;
2613 int rv = trans->Start(
2614 &CreateGetRequest(), callback.callback(), BoundNetLog());
2615 EXPECT_EQ(ERR_IO_PENDING, rv);
2616 helper.ResetTrans(); // Cancel the transaction.
2618 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2619 // MockClientSocketFactory) are still alive.
2620 MessageLoop::current()->RunUntilIdle();
2621 helper.VerifyDataNotConsumed();
2624 // Verify that the client sends a Rst Frame upon cancelling the stream.
2625 TEST_P(SpdyNetworkTransactionSpdy3Test, CancelledTransactionSendRst) {
2626 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2627 scoped_ptr<SpdyFrame> rst(
2628 ConstructSpdyRstStream(1, CANCEL));
2629 MockWrite writes[] = {
2630 CreateMockWrite(*req, 0, SYNCHRONOUS),
2631 CreateMockWrite(*rst, 2, SYNCHRONOUS),
2634 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2635 MockRead reads[] = {
2636 CreateMockRead(*resp, 1, ASYNC),
2637 MockRead(ASYNC, 0, 0, 3) // EOF
2640 DeterministicSocketData data(reads, arraysize(reads),
2641 writes, arraysize(writes));
2643 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2644 BoundNetLog(),
2645 GetParam(), NULL);
2646 helper.SetDeterministic();
2647 helper.RunPreTestSetup();
2648 helper.AddDeterministicData(&data);
2649 HttpNetworkTransaction* trans = helper.trans();
2651 TestCompletionCallback callback;
2653 int rv = trans->Start(
2654 &CreateGetRequest(), callback.callback(), BoundNetLog());
2655 EXPECT_EQ(ERR_IO_PENDING, rv);
2657 data.SetStop(2);
2658 data.Run();
2659 helper.ResetTrans();
2660 data.SetStop(20);
2661 data.Run();
2663 helper.VerifyDataConsumed();
2666 // Verify that the client can correctly deal with the user callback attempting
2667 // to start another transaction on a session that is closing down. See
2668 // http://crbug.com/47455
2669 TEST_P(SpdyNetworkTransactionSpdy3Test, StartTransactionOnReadCallback) {
2670 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2671 MockWrite writes[] = { CreateMockWrite(*req) };
2672 MockWrite writes2[] = { CreateMockWrite(*req) };
2674 // The indicated length of this packet is longer than its actual length. When
2675 // the session receives an empty packet after this one, it shuts down the
2676 // session, and calls the read callback with the incomplete data.
2677 const uint8 kGetBodyFrame2[] = {
2678 0x00, 0x00, 0x00, 0x01,
2679 0x01, 0x00, 0x00, 0x07,
2680 'h', 'e', 'l', 'l', 'o', '!',
2683 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2684 MockRead reads[] = {
2685 CreateMockRead(*resp, 2),
2686 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2687 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2688 arraysize(kGetBodyFrame2), 4),
2689 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2690 MockRead(ASYNC, 0, 0, 6), // EOF
2692 MockRead reads2[] = {
2693 CreateMockRead(*resp, 2),
2694 MockRead(ASYNC, 0, 0, 3), // EOF
2697 OrderedSocketData data(reads, arraysize(reads),
2698 writes, arraysize(writes));
2699 DelayedSocketData data2(1, reads2, arraysize(reads2),
2700 writes2, arraysize(writes2));
2702 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2703 BoundNetLog(), GetParam(), NULL);
2704 helper.RunPreTestSetup();
2705 helper.AddData(&data);
2706 helper.AddData(&data2);
2707 HttpNetworkTransaction* trans = helper.trans();
2709 // Start the transaction with basic parameters.
2710 TestCompletionCallback callback;
2711 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2712 EXPECT_EQ(ERR_IO_PENDING, rv);
2713 rv = callback.WaitForResult();
2715 const int kSize = 3000;
2716 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2717 rv = trans->Read(
2718 buf, kSize,
2719 base::Bind(&SpdyNetworkTransactionSpdy3Test::StartTransactionCallback,
2720 helper.session()));
2721 // This forces an err_IO_pending, which sets the callback.
2722 data.CompleteRead();
2723 // This finishes the read.
2724 data.CompleteRead();
2725 helper.VerifyDataConsumed();
2728 // Verify that the client can correctly deal with the user callback deleting the
2729 // transaction. Failures will usually be valgrind errors. See
2730 // http://crbug.com/46925
2731 TEST_P(SpdyNetworkTransactionSpdy3Test, DeleteSessionOnReadCallback) {
2732 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2733 MockWrite writes[] = { CreateMockWrite(*req) };
2735 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2736 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2737 MockRead reads[] = {
2738 CreateMockRead(*resp.get(), 2),
2739 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2740 CreateMockRead(*body.get(), 4),
2741 MockRead(ASYNC, 0, 0, 5), // EOF
2744 OrderedSocketData data(reads, arraysize(reads),
2745 writes, arraysize(writes));
2747 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2748 BoundNetLog(), GetParam(), NULL);
2749 helper.RunPreTestSetup();
2750 helper.AddData(&data);
2751 HttpNetworkTransaction* trans = helper.trans();
2753 // Start the transaction with basic parameters.
2754 TestCompletionCallback callback;
2755 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2756 EXPECT_EQ(ERR_IO_PENDING, rv);
2757 rv = callback.WaitForResult();
2759 // Setup a user callback which will delete the session, and clear out the
2760 // memory holding the stream object. Note that the callback deletes trans.
2761 const int kSize = 3000;
2762 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2763 rv = trans->Read(
2764 buf, kSize,
2765 base::Bind(&SpdyNetworkTransactionSpdy3Test::DeleteSessionCallback,
2766 base::Unretained(&helper)));
2767 ASSERT_EQ(ERR_IO_PENDING, rv);
2768 data.CompleteRead();
2770 // Finish running rest of tasks.
2771 MessageLoop::current()->RunUntilIdle();
2772 helper.VerifyDataConsumed();
2775 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2776 TEST_P(SpdyNetworkTransactionSpdy3Test, RedirectGetRequest) {
2777 // These are headers which the net::URLRequest tacks on.
2778 const char* const kExtraHeaders[] = {
2779 "accept-encoding",
2780 "gzip,deflate",
2782 const SpdyHeaderInfo kSynStartHeader = MakeSpdyHeader(SYN_STREAM);
2783 const char* const kStandardGetHeaders[] = {
2784 ":host",
2785 "www.google.com",
2786 ":method",
2787 "GET",
2788 ":scheme",
2789 "http",
2790 ":path",
2791 "/",
2792 "user-agent",
2794 ":version",
2795 "HTTP/1.1"
2797 const char* const kStandardGetHeaders2[] = {
2798 ":host",
2799 "www.foo.com",
2800 ":method",
2801 "GET",
2802 ":scheme",
2803 "http",
2804 ":path",
2805 "/index.php",
2806 "user-agent",
2808 ":version",
2809 "HTTP/1.1"
2812 // Setup writes/reads to www.google.com
2813 scoped_ptr<SpdyFrame> req(ConstructSpdyPacket(
2814 kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders) / 2,
2815 kStandardGetHeaders, arraysize(kStandardGetHeaders) / 2));
2816 scoped_ptr<SpdyFrame> req2(ConstructSpdyPacket(
2817 kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders) / 2,
2818 kStandardGetHeaders2, arraysize(kStandardGetHeaders2) / 2));
2819 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReplyRedirect(1));
2820 MockWrite writes[] = {
2821 CreateMockWrite(*req, 1),
2823 MockRead reads[] = {
2824 CreateMockRead(*resp, 2),
2825 MockRead(ASYNC, 0, 0, 3) // EOF
2828 // Setup writes/reads to www.foo.com
2829 scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
2830 scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
2831 MockWrite writes2[] = {
2832 CreateMockWrite(*req2, 1),
2834 MockRead reads2[] = {
2835 CreateMockRead(*resp2, 2),
2836 CreateMockRead(*body2, 3),
2837 MockRead(ASYNC, 0, 0, 4) // EOF
2839 OrderedSocketData data(reads, arraysize(reads),
2840 writes, arraysize(writes));
2841 OrderedSocketData data2(reads2, arraysize(reads2),
2842 writes2, arraysize(writes2));
2844 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2845 HttpStreamFactory::set_force_spdy_over_ssl(false);
2846 HttpStreamFactory::set_force_spdy_always(true);
2847 TestDelegate d;
2849 SpdyURLRequestContext spdy_url_request_context;
2850 net::URLRequest r(
2851 GURL("http://www.google.com/"), &d, &spdy_url_request_context);
2852 spdy_url_request_context.socket_factory().
2853 AddSocketDataProvider(&data);
2854 spdy_url_request_context.socket_factory().
2855 AddSocketDataProvider(&data2);
2857 d.set_quit_on_redirect(true);
2858 r.Start();
2859 MessageLoop::current()->Run();
2860 EXPECT_EQ(1, d.received_redirect_count());
2862 r.FollowDeferredRedirect();
2863 MessageLoop::current()->Run();
2864 EXPECT_EQ(1, d.response_started_count());
2865 EXPECT_FALSE(d.received_data_before_response());
2866 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r.status().status());
2867 std::string contents("hello!");
2868 EXPECT_EQ(contents, d.data_received());
2870 EXPECT_TRUE(data.at_read_eof());
2871 EXPECT_TRUE(data.at_write_eof());
2872 EXPECT_TRUE(data2.at_read_eof());
2873 EXPECT_TRUE(data2.at_write_eof());
2876 // Detect response with upper case headers and reset the stream.
2877 TEST_P(SpdyNetworkTransactionSpdy3Test, UpperCaseHeaders) {
2878 scoped_ptr<SpdyFrame>
2879 syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2880 scoped_ptr<SpdyFrame>
2881 rst(ConstructSpdyRstStream(1, PROTOCOL_ERROR));
2882 MockWrite writes[] = {
2883 CreateMockWrite(*syn, 0),
2884 CreateMockWrite(*rst, 2),
2887 const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
2888 scoped_ptr<SpdyFrame>
2889 reply(ConstructSpdyGetSynReply(kExtraHeaders, 1, 1));
2890 MockRead reads[] = {
2891 CreateMockRead(*reply, 1),
2892 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2895 HttpResponseInfo response;
2896 HttpResponseInfo response2;
2897 OrderedSocketData data(reads, arraysize(reads),
2898 writes, arraysize(writes));
2899 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2900 BoundNetLog(), GetParam(), NULL);
2901 helper.RunToCompletion(&data);
2902 TransactionHelperResult out = helper.output();
2903 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2906 // Detect response with upper case headers in a HEADERS frame and reset the
2907 // stream.
2908 TEST_P(SpdyNetworkTransactionSpdy3Test, UpperCaseHeadersInHeadersFrame) {
2909 scoped_ptr<SpdyFrame>
2910 syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2911 scoped_ptr<SpdyFrame>
2912 rst(ConstructSpdyRstStream(1, PROTOCOL_ERROR));
2913 MockWrite writes[] = {
2914 CreateMockWrite(*syn, 0),
2915 CreateMockWrite(*rst, 2),
2918 static const char* const kInitialHeaders[] = {
2919 ":status", "200 OK",
2920 ":version", "HTTP/1.1"
2922 static const char* const kLateHeaders[] = {
2923 "X-UpperCase", "yes",
2925 scoped_ptr<SpdyFrame>
2926 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
2927 arraysize(kInitialHeaders) / 2,
2928 false,
2930 LOWEST,
2931 SYN_REPLY,
2932 CONTROL_FLAG_NONE,
2933 NULL,
2935 0));
2936 scoped_ptr<SpdyFrame>
2937 stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
2938 arraysize(kLateHeaders) / 2,
2939 false,
2941 LOWEST,
2942 HEADERS,
2943 CONTROL_FLAG_NONE,
2944 NULL,
2946 0));
2947 scoped_ptr<SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, true));
2948 MockRead reads[] = {
2949 CreateMockRead(*stream1_reply),
2950 CreateMockRead(*stream1_headers),
2951 CreateMockRead(*stream1_body),
2952 MockRead(ASYNC, 0, 0) // EOF
2955 DelayedSocketData data(1, reads, arraysize(reads),
2956 writes, arraysize(writes));
2957 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2958 BoundNetLog(), GetParam(), NULL);
2959 helper.RunToCompletion(&data);
2960 TransactionHelperResult out = helper.output();
2961 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2964 // Detect push stream with upper case headers and reset the stream.
2965 TEST_P(SpdyNetworkTransactionSpdy3Test, UpperCaseHeadersOnPush) {
2966 scoped_ptr<SpdyFrame>
2967 syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2968 scoped_ptr<SpdyFrame>
2969 rst(ConstructSpdyRstStream(2, PROTOCOL_ERROR));
2970 MockWrite writes[] = {
2971 CreateMockWrite(*syn, 0),
2972 CreateMockWrite(*rst, 2),
2975 scoped_ptr<SpdyFrame>
2976 reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2977 const char* const extra_headers[] = {
2978 "X-UpperCase", "yes"
2980 scoped_ptr<SpdyFrame>
2981 push(ConstructSpdyPush(extra_headers, arraysize(extra_headers) / 2,
2982 2, 1));
2983 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2984 MockRead reads[] = {
2985 CreateMockRead(*reply, 1),
2986 CreateMockRead(*push, 1),
2987 CreateMockRead(*body, 1),
2988 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2991 HttpResponseInfo response;
2992 HttpResponseInfo response2;
2993 OrderedSocketData data(reads, arraysize(reads),
2994 writes, arraysize(writes));
2995 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2996 BoundNetLog(), GetParam(), NULL);
2997 helper.RunToCompletion(&data);
2998 TransactionHelperResult out = helper.output();
2999 EXPECT_EQ(OK, out.rv);
3002 // Send a spdy request to www.google.com. Get a pushed stream that redirects to
3003 // www.foo.com.
3004 TEST_P(SpdyNetworkTransactionSpdy3Test, RedirectServerPush) {
3005 // These are headers which the net::URLRequest tacks on.
3006 const char* const kExtraHeaders[] = {
3007 "accept-encoding",
3008 "gzip,deflate",
3010 const SpdyHeaderInfo kSynStartHeader = MakeSpdyHeader(SYN_STREAM);
3011 const char* const kStandardGetHeaders[] = {
3012 ":host",
3013 "www.google.com",
3014 ":method",
3015 "GET",
3016 ":scheme",
3017 "http",
3018 ":path",
3019 "/",
3020 "user-agent",
3022 ":version",
3023 "HTTP/1.1"
3026 // Setup writes/reads to www.google.com
3027 scoped_ptr<SpdyFrame> req(
3028 ConstructSpdyPacket(kSynStartHeader,
3029 kExtraHeaders,
3030 arraysize(kExtraHeaders) / 2,
3031 kStandardGetHeaders,
3032 arraysize(kStandardGetHeaders) / 2));
3033 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3034 scoped_ptr<SpdyFrame> rep(
3035 ConstructSpdyPush(NULL,
3039 "http://www.google.com/foo.dat",
3040 "301 Moved Permanently",
3041 "http://www.foo.com/index.php"));
3042 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3043 scoped_ptr<SpdyFrame> rst(ConstructSpdyRstStream(2, CANCEL));
3044 MockWrite writes[] = {
3045 CreateMockWrite(*req, 1),
3046 CreateMockWrite(*rst, 6),
3048 MockRead reads[] = {
3049 CreateMockRead(*resp, 2),
3050 CreateMockRead(*rep, 3),
3051 CreateMockRead(*body, 4),
3052 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
3053 MockRead(ASYNC, 0, 0, 7) // EOF
3056 // Setup writes/reads to www.foo.com
3057 const char* const kStandardGetHeaders2[] = {
3058 ":host",
3059 "www.foo.com",
3060 ":method",
3061 "GET",
3062 ":scheme",
3063 "http",
3064 ":path",
3065 "/index.php",
3066 "user-agent",
3068 ":version",
3069 "HTTP/1.1"
3071 scoped_ptr<SpdyFrame> req2(
3072 ConstructSpdyPacket(kSynStartHeader,
3073 kExtraHeaders,
3074 arraysize(kExtraHeaders) / 2,
3075 kStandardGetHeaders2,
3076 arraysize(kStandardGetHeaders2) / 2));
3077 scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
3078 scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
3079 MockWrite writes2[] = {
3080 CreateMockWrite(*req2, 1),
3082 MockRead reads2[] = {
3083 CreateMockRead(*resp2, 2),
3084 CreateMockRead(*body2, 3),
3085 MockRead(ASYNC, 0, 0, 5) // EOF
3087 OrderedSocketData data(reads, arraysize(reads),
3088 writes, arraysize(writes));
3089 OrderedSocketData data2(reads2, arraysize(reads2),
3090 writes2, arraysize(writes2));
3092 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
3093 HttpStreamFactory::set_force_spdy_over_ssl(false);
3094 HttpStreamFactory::set_force_spdy_always(true);
3095 TestDelegate d;
3096 TestDelegate d2;
3097 SpdyURLRequestContext spdy_url_request_context;
3099 net::URLRequest r(
3100 GURL("http://www.google.com/"), &d, &spdy_url_request_context);
3101 spdy_url_request_context.socket_factory().
3102 AddSocketDataProvider(&data);
3104 r.Start();
3105 MessageLoop::current()->Run();
3107 EXPECT_EQ(0, d.received_redirect_count());
3108 std::string contents("hello!");
3109 EXPECT_EQ(contents, d.data_received());
3111 net::URLRequest r2(
3112 GURL("http://www.google.com/foo.dat"), &d2, &spdy_url_request_context);
3113 spdy_url_request_context.socket_factory().
3114 AddSocketDataProvider(&data2);
3116 d2.set_quit_on_redirect(true);
3117 r2.Start();
3118 MessageLoop::current()->Run();
3119 EXPECT_EQ(1, d2.received_redirect_count());
3121 r2.FollowDeferredRedirect();
3122 MessageLoop::current()->Run();
3123 EXPECT_EQ(1, d2.response_started_count());
3124 EXPECT_FALSE(d2.received_data_before_response());
3125 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2.status().status());
3126 std::string contents2("hello!");
3127 EXPECT_EQ(contents2, d2.data_received());
3129 data.CompleteRead();
3130 data2.CompleteRead();
3131 EXPECT_TRUE(data.at_read_eof());
3132 EXPECT_TRUE(data.at_write_eof());
3133 EXPECT_TRUE(data2.at_read_eof());
3134 EXPECT_TRUE(data2.at_write_eof());
3137 TEST_P(SpdyNetworkTransactionSpdy3Test, ServerPushSingleDataFrame) {
3138 static const unsigned char kPushBodyFrame[] = {
3139 0x00, 0x00, 0x00, 0x02, // header, ID
3140 0x01, 0x00, 0x00, 0x06, // FIN, length
3141 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3143 scoped_ptr<SpdyFrame>
3144 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3145 scoped_ptr<SpdyFrame>
3146 stream1_body(ConstructSpdyBodyFrame(1, true));
3147 MockWrite writes[] = {
3148 CreateMockWrite(*stream1_syn, 1),
3151 scoped_ptr<SpdyFrame>
3152 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3153 scoped_ptr<SpdyFrame>
3154 stream2_syn(ConstructSpdyPush(NULL,
3158 "http://www.google.com/foo.dat"));
3159 MockRead reads[] = {
3160 CreateMockRead(*stream1_reply, 2),
3161 CreateMockRead(*stream2_syn, 3),
3162 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
3163 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
3164 arraysize(kPushBodyFrame), 5),
3165 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
3168 HttpResponseInfo response;
3169 HttpResponseInfo response2;
3170 std::string expected_push_result("pushed");
3171 OrderedSocketData data(reads, arraysize(reads),
3172 writes, arraysize(writes));
3173 RunServerPushTest(&data,
3174 &response,
3175 &response2,
3176 expected_push_result);
3178 // Verify the SYN_REPLY.
3179 EXPECT_TRUE(response.headers != NULL);
3180 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3182 // Verify the pushed stream.
3183 EXPECT_TRUE(response2.headers != NULL);
3184 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3187 TEST_P(SpdyNetworkTransactionSpdy3Test, ServerPushBeforeSynReply) {
3188 static const unsigned char kPushBodyFrame[] = {
3189 0x00, 0x00, 0x00, 0x02, // header, ID
3190 0x01, 0x00, 0x00, 0x06, // FIN, length
3191 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3193 scoped_ptr<SpdyFrame>
3194 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3195 scoped_ptr<SpdyFrame>
3196 stream1_body(ConstructSpdyBodyFrame(1, true));
3197 MockWrite writes[] = {
3198 CreateMockWrite(*stream1_syn, 1),
3201 scoped_ptr<SpdyFrame>
3202 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3203 scoped_ptr<SpdyFrame>
3204 stream2_syn(ConstructSpdyPush(NULL,
3208 "http://www.google.com/foo.dat"));
3209 MockRead reads[] = {
3210 CreateMockRead(*stream2_syn, 2),
3211 CreateMockRead(*stream1_reply, 3),
3212 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
3213 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
3214 arraysize(kPushBodyFrame), 5),
3215 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
3218 HttpResponseInfo response;
3219 HttpResponseInfo response2;
3220 std::string expected_push_result("pushed");
3221 OrderedSocketData data(reads, arraysize(reads),
3222 writes, arraysize(writes));
3223 RunServerPushTest(&data,
3224 &response,
3225 &response2,
3226 expected_push_result);
3228 // Verify the SYN_REPLY.
3229 EXPECT_TRUE(response.headers != NULL);
3230 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3232 // Verify the pushed stream.
3233 EXPECT_TRUE(response2.headers != NULL);
3234 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3237 TEST_P(SpdyNetworkTransactionSpdy3Test, ServerPushSingleDataFrame2) {
3238 static const unsigned char kPushBodyFrame[] = {
3239 0x00, 0x00, 0x00, 0x02, // header, ID
3240 0x01, 0x00, 0x00, 0x06, // FIN, length
3241 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3243 scoped_ptr<SpdyFrame>
3244 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3245 MockWrite writes[] = {
3246 CreateMockWrite(*stream1_syn, 1),
3249 scoped_ptr<SpdyFrame>
3250 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3251 scoped_ptr<SpdyFrame>
3252 stream2_syn(ConstructSpdyPush(NULL,
3256 "http://www.google.com/foo.dat"));
3257 scoped_ptr<SpdyFrame>
3258 stream1_body(ConstructSpdyBodyFrame(1, true));
3259 MockRead reads[] = {
3260 CreateMockRead(*stream1_reply, 2),
3261 CreateMockRead(*stream2_syn, 3),
3262 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
3263 arraysize(kPushBodyFrame), 5),
3264 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
3265 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
3268 HttpResponseInfo response;
3269 HttpResponseInfo response2;
3270 std::string expected_push_result("pushed");
3271 OrderedSocketData data(reads, arraysize(reads),
3272 writes, arraysize(writes));
3273 RunServerPushTest(&data,
3274 &response,
3275 &response2,
3276 expected_push_result);
3278 // Verify the SYN_REPLY.
3279 EXPECT_TRUE(response.headers != NULL);
3280 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3282 // Verify the pushed stream.
3283 EXPECT_TRUE(response2.headers != NULL);
3284 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3287 TEST_P(SpdyNetworkTransactionSpdy3Test, ServerPushServerAborted) {
3288 scoped_ptr<SpdyFrame>
3289 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3290 scoped_ptr<SpdyFrame>
3291 stream1_body(ConstructSpdyBodyFrame(1, true));
3292 MockWrite writes[] = {
3293 CreateMockWrite(*stream1_syn, 1),
3296 scoped_ptr<SpdyFrame>
3297 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3298 scoped_ptr<SpdyFrame>
3299 stream2_syn(ConstructSpdyPush(NULL,
3303 "http://www.google.com/foo.dat"));
3304 scoped_ptr<SpdyFrame>
3305 stream2_rst(ConstructSpdyRstStream(2, PROTOCOL_ERROR));
3306 MockRead reads[] = {
3307 CreateMockRead(*stream1_reply, 2),
3308 CreateMockRead(*stream2_syn, 3),
3309 CreateMockRead(*stream2_rst, 4),
3310 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
3311 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
3314 OrderedSocketData data(reads, arraysize(reads),
3315 writes, arraysize(writes));
3316 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3317 BoundNetLog(), GetParam(), NULL);
3319 helper.RunPreTestSetup();
3320 helper.AddData(&data);
3322 HttpNetworkTransaction* trans = helper.trans();
3324 // Start the transaction with basic parameters.
3325 TestCompletionCallback callback;
3326 int rv = trans->Start(
3327 &CreateGetRequest(), callback.callback(), BoundNetLog());
3328 EXPECT_EQ(ERR_IO_PENDING, rv);
3329 rv = callback.WaitForResult();
3330 EXPECT_EQ(OK, rv);
3332 // Verify that we consumed all test data.
3333 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3334 << data.read_count()
3335 << " Read index: "
3336 << data.read_index();
3337 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3338 << data.write_count()
3339 << " Write index: "
3340 << data.write_index();
3342 // Verify the SYN_REPLY.
3343 HttpResponseInfo response = *trans->GetResponseInfo();
3344 EXPECT_TRUE(response.headers != NULL);
3345 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3348 TEST_P(SpdyNetworkTransactionSpdy3Test, ServerPushDuplicate) {
3349 // Verify that we don't leak streams and that we properly send a reset
3350 // if the server pushes the same stream twice.
3351 static const unsigned char kPushBodyFrame[] = {
3352 0x00, 0x00, 0x00, 0x02, // header, ID
3353 0x01, 0x00, 0x00, 0x06, // FIN, length
3354 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3357 scoped_ptr<SpdyFrame>
3358 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3359 scoped_ptr<SpdyFrame>
3360 stream1_body(ConstructSpdyBodyFrame(1, true));
3361 scoped_ptr<SpdyFrame>
3362 stream3_rst(ConstructSpdyRstStream(4, PROTOCOL_ERROR));
3363 MockWrite writes[] = {
3364 CreateMockWrite(*stream1_syn, 1),
3365 CreateMockWrite(*stream3_rst, 5),
3368 scoped_ptr<SpdyFrame>
3369 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3370 scoped_ptr<SpdyFrame>
3371 stream2_syn(ConstructSpdyPush(NULL,
3375 "http://www.google.com/foo.dat"));
3376 scoped_ptr<SpdyFrame>
3377 stream3_syn(ConstructSpdyPush(NULL,
3381 "http://www.google.com/foo.dat"));
3382 MockRead reads[] = {
3383 CreateMockRead(*stream1_reply, 2),
3384 CreateMockRead(*stream2_syn, 3),
3385 CreateMockRead(*stream3_syn, 4),
3386 CreateMockRead(*stream1_body, 6, SYNCHRONOUS),
3387 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
3388 arraysize(kPushBodyFrame), 7),
3389 MockRead(ASYNC, ERR_IO_PENDING, 8), // Force a pause
3392 HttpResponseInfo response;
3393 HttpResponseInfo response2;
3394 std::string expected_push_result("pushed");
3395 OrderedSocketData data(reads, arraysize(reads),
3396 writes, arraysize(writes));
3397 RunServerPushTest(&data,
3398 &response,
3399 &response2,
3400 expected_push_result);
3402 // Verify the SYN_REPLY.
3403 EXPECT_TRUE(response.headers != NULL);
3404 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3406 // Verify the pushed stream.
3407 EXPECT_TRUE(response2.headers != NULL);
3408 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3411 TEST_P(SpdyNetworkTransactionSpdy3Test, ServerPushMultipleDataFrame) {
3412 static const unsigned char kPushBodyFrame1[] = {
3413 0x00, 0x00, 0x00, 0x02, // header, ID
3414 0x01, 0x00, 0x00, 0x1F, // FIN, length
3415 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3417 static const char kPushBodyFrame2[] = " my darling";
3418 static const char kPushBodyFrame3[] = " hello";
3419 static const char kPushBodyFrame4[] = " my baby";
3421 scoped_ptr<SpdyFrame>
3422 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3423 scoped_ptr<SpdyFrame>
3424 stream1_body(ConstructSpdyBodyFrame(1, true));
3425 MockWrite writes[] = {
3426 CreateMockWrite(*stream1_syn, 1),
3429 scoped_ptr<SpdyFrame>
3430 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3431 scoped_ptr<SpdyFrame>
3432 stream2_syn(ConstructSpdyPush(NULL,
3436 "http://www.google.com/foo.dat"));
3437 MockRead reads[] = {
3438 CreateMockRead(*stream1_reply, 2),
3439 CreateMockRead(*stream2_syn, 3),
3440 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame1),
3441 arraysize(kPushBodyFrame1), 4),
3442 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame2),
3443 arraysize(kPushBodyFrame2) - 1, 5),
3444 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame3),
3445 arraysize(kPushBodyFrame3) - 1, 6),
3446 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame4),
3447 arraysize(kPushBodyFrame4) - 1, 7),
3448 CreateMockRead(*stream1_body, 8, SYNCHRONOUS),
3449 MockRead(ASYNC, ERR_IO_PENDING, 9), // Force a pause
3452 HttpResponseInfo response;
3453 HttpResponseInfo response2;
3454 std::string expected_push_result("pushed my darling hello my baby");
3455 OrderedSocketData data(reads, arraysize(reads),
3456 writes, arraysize(writes));
3457 RunServerPushTest(&data,
3458 &response,
3459 &response2,
3460 expected_push_result);
3462 // Verify the SYN_REPLY.
3463 EXPECT_TRUE(response.headers != NULL);
3464 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3466 // Verify the pushed stream.
3467 EXPECT_TRUE(response2.headers != NULL);
3468 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3471 TEST_P(SpdyNetworkTransactionSpdy3Test,
3472 ServerPushMultipleDataFrameInterrupted) {
3473 static const unsigned char kPushBodyFrame1[] = {
3474 0x00, 0x00, 0x00, 0x02, // header, ID
3475 0x01, 0x00, 0x00, 0x1F, // FIN, length
3476 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3478 static const char kPushBodyFrame2[] = " my darling";
3479 static const char kPushBodyFrame3[] = " hello";
3480 static const char kPushBodyFrame4[] = " my baby";
3482 scoped_ptr<SpdyFrame>
3483 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3484 scoped_ptr<SpdyFrame>
3485 stream1_body(ConstructSpdyBodyFrame(1, true));
3486 MockWrite writes[] = {
3487 CreateMockWrite(*stream1_syn, 1),
3490 scoped_ptr<SpdyFrame>
3491 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3492 scoped_ptr<SpdyFrame>
3493 stream2_syn(ConstructSpdyPush(NULL,
3497 "http://www.google.com/foo.dat"));
3498 MockRead reads[] = {
3499 CreateMockRead(*stream1_reply, 2),
3500 CreateMockRead(*stream2_syn, 3),
3501 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame1),
3502 arraysize(kPushBodyFrame1), 4),
3503 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame2),
3504 arraysize(kPushBodyFrame2) - 1, 5),
3505 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
3506 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame3),
3507 arraysize(kPushBodyFrame3) - 1, 7),
3508 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame4),
3509 arraysize(kPushBodyFrame4) - 1, 8),
3510 CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS),
3511 MockRead(ASYNC, ERR_IO_PENDING, 10) // Force a pause.
3514 HttpResponseInfo response;
3515 HttpResponseInfo response2;
3516 std::string expected_push_result("pushed my darling hello my baby");
3517 OrderedSocketData data(reads, arraysize(reads),
3518 writes, arraysize(writes));
3519 RunServerPushTest(&data,
3520 &response,
3521 &response2,
3522 expected_push_result);
3524 // Verify the SYN_REPLY.
3525 EXPECT_TRUE(response.headers != NULL);
3526 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3528 // Verify the pushed stream.
3529 EXPECT_TRUE(response2.headers != NULL);
3530 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3533 TEST_P(SpdyNetworkTransactionSpdy3Test, ServerPushInvalidAssociatedStreamID0) {
3534 scoped_ptr<SpdyFrame>
3535 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3536 scoped_ptr<SpdyFrame>
3537 stream1_body(ConstructSpdyBodyFrame(1, true));
3538 scoped_ptr<SpdyFrame>
3539 stream2_rst(ConstructSpdyRstStream(2, REFUSED_STREAM));
3540 MockWrite writes[] = {
3541 CreateMockWrite(*stream1_syn, 1),
3542 CreateMockWrite(*stream2_rst, 4),
3545 scoped_ptr<SpdyFrame>
3546 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3547 scoped_ptr<SpdyFrame>
3548 stream2_syn(ConstructSpdyPush(NULL,
3552 "http://www.google.com/foo.dat"));
3553 MockRead reads[] = {
3554 CreateMockRead(*stream1_reply, 2),
3555 CreateMockRead(*stream2_syn, 3),
3556 CreateMockRead(*stream1_body, 4),
3557 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3560 OrderedSocketData data(reads, arraysize(reads),
3561 writes, arraysize(writes));
3562 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3563 BoundNetLog(), GetParam(), NULL);
3565 helper.RunPreTestSetup();
3566 helper.AddData(&data);
3568 HttpNetworkTransaction* trans = helper.trans();
3570 // Start the transaction with basic parameters.
3571 TestCompletionCallback callback;
3572 int rv = trans->Start(
3573 &CreateGetRequest(), callback.callback(), BoundNetLog());
3574 EXPECT_EQ(ERR_IO_PENDING, rv);
3575 rv = callback.WaitForResult();
3576 EXPECT_EQ(OK, rv);
3578 // Verify that we consumed all test data.
3579 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3580 << data.read_count()
3581 << " Read index: "
3582 << data.read_index();
3583 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3584 << data.write_count()
3585 << " Write index: "
3586 << data.write_index();
3588 // Verify the SYN_REPLY.
3589 HttpResponseInfo response = *trans->GetResponseInfo();
3590 EXPECT_TRUE(response.headers != NULL);
3591 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3594 TEST_P(SpdyNetworkTransactionSpdy3Test, ServerPushInvalidAssociatedStreamID9) {
3595 scoped_ptr<SpdyFrame>
3596 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3597 scoped_ptr<SpdyFrame>
3598 stream1_body(ConstructSpdyBodyFrame(1, true));
3599 scoped_ptr<SpdyFrame>
3600 stream2_rst(ConstructSpdyRstStream(2, INVALID_STREAM));
3601 MockWrite writes[] = {
3602 CreateMockWrite(*stream1_syn, 1),
3603 CreateMockWrite(*stream2_rst, 4),
3606 scoped_ptr<SpdyFrame>
3607 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3608 scoped_ptr<SpdyFrame>
3609 stream2_syn(ConstructSpdyPush(NULL,
3613 "http://www.google.com/foo.dat"));
3614 MockRead reads[] = {
3615 CreateMockRead(*stream1_reply, 2),
3616 CreateMockRead(*stream2_syn, 3),
3617 CreateMockRead(*stream1_body, 4),
3618 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
3621 OrderedSocketData data(reads, arraysize(reads),
3622 writes, arraysize(writes));
3623 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3624 BoundNetLog(), GetParam(), NULL);
3626 helper.RunPreTestSetup();
3627 helper.AddData(&data);
3629 HttpNetworkTransaction* trans = helper.trans();
3631 // Start the transaction with basic parameters.
3632 TestCompletionCallback callback;
3633 int rv = trans->Start(
3634 &CreateGetRequest(), callback.callback(), BoundNetLog());
3635 EXPECT_EQ(ERR_IO_PENDING, rv);
3636 rv = callback.WaitForResult();
3637 EXPECT_EQ(OK, rv);
3639 // Verify that we consumed all test data.
3640 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3641 << data.read_count()
3642 << " Read index: "
3643 << data.read_index();
3644 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3645 << data.write_count()
3646 << " Write index: "
3647 << data.write_index();
3649 // Verify the SYN_REPLY.
3650 HttpResponseInfo response = *trans->GetResponseInfo();
3651 EXPECT_TRUE(response.headers != NULL);
3652 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3655 TEST_P(SpdyNetworkTransactionSpdy3Test, ServerPushNoURL) {
3656 scoped_ptr<SpdyFrame>
3657 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3658 scoped_ptr<SpdyFrame>
3659 stream1_body(ConstructSpdyBodyFrame(1, true));
3660 scoped_ptr<SpdyFrame>
3661 stream2_rst(ConstructSpdyRstStream(2, PROTOCOL_ERROR));
3662 MockWrite writes[] = {
3663 CreateMockWrite(*stream1_syn, 1),
3664 CreateMockWrite(*stream2_rst, 4),
3667 scoped_ptr<SpdyFrame>
3668 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3669 scoped_ptr<SpdyFrame>
3670 stream2_syn(ConstructSpdyPush(NULL, 0, 2, 1));
3671 MockRead reads[] = {
3672 CreateMockRead(*stream1_reply, 2),
3673 CreateMockRead(*stream2_syn, 3),
3674 CreateMockRead(*stream1_body, 4),
3675 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3678 OrderedSocketData data(reads, arraysize(reads),
3679 writes, arraysize(writes));
3680 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3681 BoundNetLog(), GetParam(), NULL);
3683 helper.RunPreTestSetup();
3684 helper.AddData(&data);
3686 HttpNetworkTransaction* trans = helper.trans();
3688 // Start the transaction with basic parameters.
3689 TestCompletionCallback callback;
3690 int rv = trans->Start(
3691 &CreateGetRequest(), callback.callback(), BoundNetLog());
3692 EXPECT_EQ(ERR_IO_PENDING, rv);
3693 rv = callback.WaitForResult();
3694 EXPECT_EQ(OK, rv);
3695 // Verify that we consumed all test data.
3696 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3697 << data.read_count()
3698 << " Read index: "
3699 << data.read_index();
3700 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3701 << data.write_count()
3702 << " Write index: "
3703 << data.write_index();
3705 // Verify the SYN_REPLY.
3706 HttpResponseInfo response = *trans->GetResponseInfo();
3707 EXPECT_TRUE(response.headers != NULL);
3708 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3711 // Verify that various SynReply headers parse correctly through the
3712 // HTTP layer.
3713 TEST_P(SpdyNetworkTransactionSpdy3Test, SynReplyHeaders) {
3714 struct SynReplyHeadersTests {
3715 int num_headers;
3716 const char* extra_headers[5];
3717 const char* expected_headers;
3718 } test_cases[] = {
3719 // This uses a multi-valued cookie header.
3720 { 2,
3721 { "cookie", "val1",
3722 "cookie", "val2", // will get appended separated by NULL
3723 NULL
3725 "status: 200\n"
3726 "version: HTTP/1.1\n"
3727 "cookie: val1\n"
3728 "cookie: val2\n"
3729 "hello: bye\n"
3731 // This is the minimalist set of headers.
3732 { 0,
3733 { NULL },
3734 "status: 200\n"
3735 "version: HTTP/1.1\n"
3736 "hello: bye\n"
3738 // Headers with a comma separated list.
3739 { 1,
3740 { "cookie", "val1,val2",
3741 NULL
3743 "status: 200\n"
3744 "version: HTTP/1.1\n"
3745 "cookie: val1,val2\n"
3746 "hello: bye\n"
3750 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3751 scoped_ptr<SpdyFrame> req(
3752 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3753 MockWrite writes[] = { CreateMockWrite(*req) };
3755 scoped_ptr<SpdyFrame> resp(
3756 ConstructSpdyGetSynReply(test_cases[i].extra_headers,
3757 test_cases[i].num_headers,
3758 1));
3759 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3760 MockRead reads[] = {
3761 CreateMockRead(*resp),
3762 CreateMockRead(*body),
3763 MockRead(ASYNC, 0, 0) // EOF
3766 DelayedSocketData data(1, reads, arraysize(reads),
3767 writes, arraysize(writes));
3768 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3769 BoundNetLog(), GetParam(), NULL);
3770 helper.RunToCompletion(&data);
3771 TransactionHelperResult out = helper.output();
3773 EXPECT_EQ(OK, out.rv);
3774 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3775 EXPECT_EQ("hello!", out.response_data);
3777 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3778 EXPECT_TRUE(headers.get() != NULL);
3779 void* iter = NULL;
3780 std::string name, value, lines;
3781 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3782 lines.append(name);
3783 lines.append(": ");
3784 lines.append(value);
3785 lines.append("\n");
3787 EXPECT_EQ(std::string(test_cases[i].expected_headers), lines);
3791 // Verify that various SynReply headers parse vary fields correctly
3792 // through the HTTP layer, and the response matches the request.
3793 TEST_P(SpdyNetworkTransactionSpdy3Test, SynReplyHeadersVary) {
3794 static const SpdyHeaderInfo syn_reply_info = {
3795 SYN_REPLY, // Syn Reply
3796 1, // Stream ID
3797 0, // Associated Stream ID
3798 ConvertRequestPriorityToSpdyPriority(LOWEST, 3), // Priority
3799 0, // Credential Slot
3800 CONTROL_FLAG_NONE, // Control Flags
3801 false, // Compressed
3802 INVALID, // Status
3803 NULL, // Data
3804 0, // Data Length
3805 DATA_FLAG_NONE // Data Flags
3807 // Modify the following data to change/add test cases:
3808 struct SynReplyTests {
3809 const SpdyHeaderInfo* syn_reply;
3810 bool vary_matches;
3811 int num_headers[2];
3812 const char* extra_headers[2][16];
3813 } test_cases[] = {
3814 // Test the case of a multi-valued cookie. When the value is delimited
3815 // with NUL characters, it needs to be unfolded into multiple headers.
3817 &syn_reply_info,
3818 true,
3819 { 1, 4 },
3820 { { "cookie", "val1,val2",
3821 NULL
3823 { ":status", "200",
3824 ":version", "HTTP/1.1",
3825 "vary", "cookie",
3826 "url", "/index.php",
3827 NULL
3830 }, { // Multiple vary fields.
3831 &syn_reply_info,
3832 true,
3833 { 2, 5 },
3834 { { "friend", "barney",
3835 "enemy", "snaggletooth",
3836 NULL
3838 { ":status", "200",
3839 ":version", "HTTP/1.1",
3840 "vary", "friend",
3841 "vary", "enemy",
3842 "url", "/index.php",
3843 NULL
3846 }, { // Test a '*' vary field.
3847 &syn_reply_info,
3848 false,
3849 { 1, 4 },
3850 { { "cookie", "val1,val2",
3851 NULL
3853 { ":status", "200",
3854 ":version", "HTTP/1.1",
3855 "vary", "*",
3856 "url", "/index.php",
3857 NULL
3860 }, { // Multiple comma-separated vary fields.
3861 &syn_reply_info,
3862 true,
3863 { 2, 4 },
3864 { { "friend", "barney",
3865 "enemy", "snaggletooth",
3866 NULL
3868 { ":status", "200",
3869 ":version", "HTTP/1.1",
3870 "vary", "friend,enemy",
3871 "url", "/index.php",
3872 NULL
3878 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3879 // Construct the request.
3880 scoped_ptr<SpdyFrame> frame_req(
3881 ConstructSpdyGet(test_cases[i].extra_headers[0],
3882 test_cases[i].num_headers[0],
3883 false, 1, LOWEST));
3885 MockWrite writes[] = {
3886 CreateMockWrite(*frame_req),
3889 // Construct the reply.
3890 scoped_ptr<SpdyFrame> frame_reply(
3891 ConstructSpdyPacket(*test_cases[i].syn_reply,
3892 test_cases[i].extra_headers[1],
3893 test_cases[i].num_headers[1],
3894 NULL,
3895 0));
3897 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3898 MockRead reads[] = {
3899 CreateMockRead(*frame_reply),
3900 CreateMockRead(*body),
3901 MockRead(ASYNC, 0, 0) // EOF
3904 // Attach the headers to the request.
3905 int header_count = test_cases[i].num_headers[0];
3907 HttpRequestInfo request = CreateGetRequest();
3908 for (int ct = 0; ct < header_count; ct++) {
3909 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3910 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3911 request.extra_headers.SetHeader(header_key, header_value);
3914 DelayedSocketData data(1, reads, arraysize(reads),
3915 writes, arraysize(writes));
3916 NormalSpdyTransactionHelper helper(request,
3917 BoundNetLog(), GetParam(), NULL);
3918 helper.RunToCompletion(&data);
3919 TransactionHelperResult out = helper.output();
3921 EXPECT_EQ(OK, out.rv) << i;
3922 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
3923 EXPECT_EQ("hello!", out.response_data) << i;
3925 // Test the response information.
3926 EXPECT_TRUE(out.response_info.response_time >
3927 out.response_info.request_time) << i;
3928 base::TimeDelta test_delay = out.response_info.response_time -
3929 out.response_info.request_time;
3930 base::TimeDelta min_expected_delay;
3931 min_expected_delay.FromMilliseconds(10);
3932 EXPECT_GT(test_delay.InMillisecondsF(),
3933 min_expected_delay.InMillisecondsF()) << i;
3934 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3935 test_cases[i].vary_matches) << i;
3937 // Check the headers.
3938 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3939 ASSERT_TRUE(headers.get() != NULL) << i;
3940 void* iter = NULL;
3941 std::string name, value, lines;
3942 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3943 lines.append(name);
3944 lines.append(": ");
3945 lines.append(value);
3946 lines.append("\n");
3949 // Construct the expected header reply string.
3950 char reply_buffer[256] = "";
3951 ConstructSpdyReplyString(test_cases[i].extra_headers[1],
3952 test_cases[i].num_headers[1],
3953 reply_buffer,
3954 256);
3956 EXPECT_EQ(std::string(reply_buffer), lines) << i;
3960 // Verify that we don't crash on invalid SynReply responses.
3961 TEST_P(SpdyNetworkTransactionSpdy3Test, InvalidSynReply) {
3962 const SpdyHeaderInfo kSynStartHeader = {
3963 SYN_REPLY, // Kind = SynReply
3964 1, // Stream ID
3965 0, // Associated stream ID
3966 ConvertRequestPriorityToSpdyPriority(LOWEST, 3), // Priority
3967 0, // Credential Slot
3968 CONTROL_FLAG_NONE, // Control Flags
3969 false, // Compressed
3970 INVALID, // Status
3971 NULL, // Data
3972 0, // Length
3973 DATA_FLAG_NONE // Data Flags
3976 struct InvalidSynReplyTests {
3977 int num_headers;
3978 const char* headers[10];
3979 } test_cases[] = {
3980 // SYN_REPLY missing status header
3981 { 4,
3982 { "cookie", "val1",
3983 "cookie", "val2",
3984 "url", "/index.php",
3985 "version", "HTTP/1.1",
3986 NULL
3989 // SYN_REPLY missing version header
3990 { 2,
3991 { ":status", "200",
3992 "url", "/index.php",
3993 NULL
3996 // SYN_REPLY with no headers
3997 { 0, { NULL }, },
4000 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
4001 scoped_ptr<SpdyFrame> req(
4002 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4003 MockWrite writes[] = {
4004 CreateMockWrite(*req),
4007 scoped_ptr<SpdyFrame> resp(
4008 ConstructSpdyPacket(kSynStartHeader,
4009 NULL, 0,
4010 test_cases[i].headers,
4011 test_cases[i].num_headers));
4012 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4013 MockRead reads[] = {
4014 CreateMockRead(*resp),
4015 CreateMockRead(*body),
4016 MockRead(ASYNC, 0, 0) // EOF
4019 DelayedSocketData data(1, reads, arraysize(reads),
4020 writes, arraysize(writes));
4021 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4022 BoundNetLog(), GetParam(), NULL);
4023 helper.RunToCompletion(&data);
4024 TransactionHelperResult out = helper.output();
4025 EXPECT_EQ(ERR_INCOMPLETE_SPDY_HEADERS, out.rv);
4029 // Verify that we don't crash on some corrupt frames.
4030 TEST_P(SpdyNetworkTransactionSpdy3Test, CorruptFrameSessionError) {
4031 // This is the length field that's too short.
4032 scoped_ptr<SpdyFrame> syn_reply_wrong_length(
4033 ConstructSpdyGetSynReply(NULL, 0, 1));
4034 syn_reply_wrong_length->set_length(syn_reply_wrong_length->length() - 4);
4036 struct SynReplyTests {
4037 const SpdyFrame* syn_reply;
4038 } test_cases[] = {
4039 { syn_reply_wrong_length.get(), },
4042 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
4043 scoped_ptr<SpdyFrame> req(
4044 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4045 MockWrite writes[] = {
4046 CreateMockWrite(*req),
4047 MockWrite(ASYNC, 0, 0) // EOF
4050 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4051 MockRead reads[] = {
4052 CreateMockRead(*test_cases[i].syn_reply),
4053 CreateMockRead(*body),
4054 MockRead(ASYNC, 0, 0) // EOF
4057 DelayedSocketData data(1, reads, arraysize(reads),
4058 writes, arraysize(writes));
4059 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4060 BoundNetLog(), GetParam(), NULL);
4061 helper.RunToCompletion(&data);
4062 TransactionHelperResult out = helper.output();
4063 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
4067 // Test that we shutdown correctly on write errors.
4068 TEST_P(SpdyNetworkTransactionSpdy3Test, WriteError) {
4069 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4070 MockWrite writes[] = {
4071 // We'll write 10 bytes successfully
4072 MockWrite(ASYNC, req->data(), 10),
4073 // Followed by ERROR!
4074 MockWrite(ASYNC, ERR_FAILED),
4077 DelayedSocketData data(2, NULL, 0,
4078 writes, arraysize(writes));
4079 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4080 BoundNetLog(), GetParam(), NULL);
4081 helper.RunToCompletion(&data);
4082 TransactionHelperResult out = helper.output();
4083 EXPECT_EQ(ERR_FAILED, out.rv);
4084 data.Reset();
4087 // Test that partial writes work.
4088 TEST_P(SpdyNetworkTransactionSpdy3Test, PartialWrite) {
4089 // Chop the SYN_STREAM frame into 5 chunks.
4090 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4091 const int kChunks = 5;
4092 scoped_array<MockWrite> writes(ChopWriteFrame(*req.get(), kChunks));
4094 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4095 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4096 MockRead reads[] = {
4097 CreateMockRead(*resp),
4098 CreateMockRead(*body),
4099 MockRead(ASYNC, 0, 0) // EOF
4102 DelayedSocketData data(kChunks, reads, arraysize(reads),
4103 writes.get(), kChunks);
4104 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4105 BoundNetLog(), GetParam(), NULL);
4106 helper.RunToCompletion(&data);
4107 TransactionHelperResult out = helper.output();
4108 EXPECT_EQ(OK, out.rv);
4109 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4110 EXPECT_EQ("hello!", out.response_data);
4113 // In this test, we enable compression, but get a uncompressed SynReply from
4114 // the server. Verify that teardown is all clean.
4115 TEST_P(SpdyNetworkTransactionSpdy3Test, DecompressFailureOnSynReply) {
4116 scoped_ptr<SpdyFrame> compressed(
4117 ConstructSpdyGet(NULL, 0, true, 1, LOWEST));
4118 scoped_ptr<SpdyFrame> rst(
4119 ConstructSpdyRstStream(1, PROTOCOL_ERROR));
4120 MockWrite writes[] = {
4121 CreateMockWrite(*compressed),
4124 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4125 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4126 MockRead reads[] = {
4127 CreateMockRead(*resp),
4130 DelayedSocketData data(1, reads, arraysize(reads),
4131 writes, arraysize(writes));
4132 SpdySessionDependencies* session_deps = new SpdySessionDependencies();
4133 session_deps->enable_compression = true;
4134 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4135 BoundNetLog(), GetParam(), session_deps);
4136 helper.RunToCompletion(&data);
4137 TransactionHelperResult out = helper.output();
4138 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
4139 data.Reset();
4142 // Test that the NetLog contains good data for a simple GET request.
4143 TEST_P(SpdyNetworkTransactionSpdy3Test, NetLog) {
4144 static const char* const kExtraHeaders[] = {
4145 "user-agent", "Chrome",
4147 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(kExtraHeaders, 1, false, 1,
4148 LOWEST));
4149 MockWrite writes[] = { CreateMockWrite(*req) };
4151 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4152 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4153 MockRead reads[] = {
4154 CreateMockRead(*resp),
4155 CreateMockRead(*body),
4156 MockRead(ASYNC, 0, 0) // EOF
4159 CapturingBoundNetLog log;
4161 DelayedSocketData data(1, reads, arraysize(reads),
4162 writes, arraysize(writes));
4163 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
4164 log.bound(), GetParam(), NULL);
4165 helper.RunToCompletion(&data);
4166 TransactionHelperResult out = helper.output();
4167 EXPECT_EQ(OK, out.rv);
4168 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4169 EXPECT_EQ("hello!", out.response_data);
4171 // Check that the NetLog was filled reasonably.
4172 // This test is intentionally non-specific about the exact ordering of the
4173 // log; instead we just check to make sure that certain events exist, and that
4174 // they are in the right order.
4175 net::CapturingNetLog::CapturedEntryList entries;
4176 log.GetEntries(&entries);
4178 EXPECT_LT(0u, entries.size());
4179 int pos = 0;
4180 pos = net::ExpectLogContainsSomewhere(entries, 0,
4181 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
4182 net::NetLog::PHASE_BEGIN);
4183 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
4184 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
4185 net::NetLog::PHASE_END);
4186 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
4187 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
4188 net::NetLog::PHASE_BEGIN);
4189 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
4190 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
4191 net::NetLog::PHASE_END);
4192 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
4193 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
4194 net::NetLog::PHASE_BEGIN);
4195 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
4196 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
4197 net::NetLog::PHASE_END);
4199 // Check that we logged all the headers correctly
4200 pos = net::ExpectLogContainsSomewhere(
4201 entries, 0,
4202 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
4203 net::NetLog::PHASE_NONE);
4205 ListValue* header_list;
4206 ASSERT_TRUE(entries[pos].params.get());
4207 ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
4209 std::vector<std::string> expected;
4210 expected.push_back(":host: www.google.com");
4211 expected.push_back(":path: /");
4212 expected.push_back(":scheme: http");
4213 expected.push_back(":version: HTTP/1.1");
4214 expected.push_back(":method: GET");
4215 expected.push_back("user-agent: Chrome");
4216 EXPECT_EQ(expected.size(), header_list->GetSize());
4217 for (std::vector<std::string>::const_iterator it = expected.begin();
4218 it != expected.end();
4219 ++it) {
4220 base::StringValue header(*it);
4221 EXPECT_NE(header_list->end(), header_list->Find(header)) <<
4222 "Header not found: " << *it;
4226 // Since we buffer the IO from the stream to the renderer, this test verifies
4227 // that when we read out the maximum amount of data (e.g. we received 50 bytes
4228 // on the network, but issued a Read for only 5 of those bytes) that the data
4229 // flow still works correctly.
4230 TEST_P(SpdyNetworkTransactionSpdy3Test, BufferFull) {
4231 BufferedSpdyFramer framer(3, false);
4233 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4234 MockWrite writes[] = { CreateMockWrite(*req) };
4236 // 2 data frames in a single read.
4237 scoped_ptr<SpdyFrame> data_frame_1(
4238 framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
4239 scoped_ptr<SpdyFrame> data_frame_2(
4240 framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
4241 const SpdyFrame* data_frames[2] = {
4242 data_frame_1.get(),
4243 data_frame_2.get(),
4245 char combined_data_frames[100];
4246 int combined_data_frames_len =
4247 CombineFrames(data_frames, arraysize(data_frames),
4248 combined_data_frames, arraysize(combined_data_frames));
4249 scoped_ptr<SpdyFrame> last_frame(
4250 framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
4252 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4253 MockRead reads[] = {
4254 CreateMockRead(*resp),
4255 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
4256 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4257 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
4258 CreateMockRead(*last_frame),
4259 MockRead(ASYNC, 0, 0) // EOF
4262 DelayedSocketData data(1, reads, arraysize(reads),
4263 writes, arraysize(writes));
4265 TestCompletionCallback callback;
4267 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4268 BoundNetLog(), GetParam(), NULL);
4269 helper.RunPreTestSetup();
4270 helper.AddData(&data);
4271 HttpNetworkTransaction* trans = helper.trans();
4272 int rv = trans->Start(
4273 &CreateGetRequest(), callback.callback(), BoundNetLog());
4274 EXPECT_EQ(ERR_IO_PENDING, rv);
4276 TransactionHelperResult out = helper.output();
4277 out.rv = callback.WaitForResult();
4278 EXPECT_EQ(out.rv, OK);
4280 const HttpResponseInfo* response = trans->GetResponseInfo();
4281 EXPECT_TRUE(response->headers != NULL);
4282 EXPECT_TRUE(response->was_fetched_via_spdy);
4283 out.status_line = response->headers->GetStatusLine();
4284 out.response_info = *response; // Make a copy so we can verify.
4286 // Read Data
4287 TestCompletionCallback read_callback;
4289 std::string content;
4290 do {
4291 // Read small chunks at a time.
4292 const int kSmallReadSize = 3;
4293 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4294 rv = trans->Read(buf, kSmallReadSize, read_callback.callback());
4295 if (rv == net::ERR_IO_PENDING) {
4296 data.CompleteRead();
4297 rv = read_callback.WaitForResult();
4299 if (rv > 0) {
4300 content.append(buf->data(), rv);
4301 } else if (rv < 0) {
4302 NOTREACHED();
4304 } while (rv > 0);
4306 out.response_data.swap(content);
4308 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4309 // MockClientSocketFactory) are still alive.
4310 MessageLoop::current()->RunUntilIdle();
4312 // Verify that we consumed all test data.
4313 helper.VerifyDataConsumed();
4315 EXPECT_EQ(OK, out.rv);
4316 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4317 EXPECT_EQ("goodbye world", out.response_data);
4320 // Verify that basic buffering works; when multiple data frames arrive
4321 // at the same time, ensure that we don't notify a read completion for
4322 // each data frame individually.
4323 TEST_P(SpdyNetworkTransactionSpdy3Test, Buffering) {
4324 BufferedSpdyFramer framer(3, false);
4326 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4327 MockWrite writes[] = { CreateMockWrite(*req) };
4329 // 4 data frames in a single read.
4330 scoped_ptr<SpdyFrame> data_frame(
4331 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4332 scoped_ptr<SpdyFrame> data_frame_fin(
4333 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
4334 const SpdyFrame* data_frames[4] = {
4335 data_frame.get(),
4336 data_frame.get(),
4337 data_frame.get(),
4338 data_frame_fin.get()
4340 char combined_data_frames[100];
4341 int combined_data_frames_len =
4342 CombineFrames(data_frames, arraysize(data_frames),
4343 combined_data_frames, arraysize(combined_data_frames));
4345 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4346 MockRead reads[] = {
4347 CreateMockRead(*resp),
4348 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
4349 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4350 MockRead(ASYNC, 0, 0) // EOF
4353 DelayedSocketData data(1, reads, arraysize(reads),
4354 writes, arraysize(writes));
4356 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4357 BoundNetLog(), GetParam(), NULL);
4358 helper.RunPreTestSetup();
4359 helper.AddData(&data);
4360 HttpNetworkTransaction* trans = helper.trans();
4362 TestCompletionCallback callback;
4363 int rv = trans->Start(
4364 &CreateGetRequest(), callback.callback(), BoundNetLog());
4365 EXPECT_EQ(ERR_IO_PENDING, rv);
4367 TransactionHelperResult out = helper.output();
4368 out.rv = callback.WaitForResult();
4369 EXPECT_EQ(out.rv, OK);
4371 const HttpResponseInfo* response = trans->GetResponseInfo();
4372 EXPECT_TRUE(response->headers != NULL);
4373 EXPECT_TRUE(response->was_fetched_via_spdy);
4374 out.status_line = response->headers->GetStatusLine();
4375 out.response_info = *response; // Make a copy so we can verify.
4377 // Read Data
4378 TestCompletionCallback read_callback;
4380 std::string content;
4381 int reads_completed = 0;
4382 do {
4383 // Read small chunks at a time.
4384 const int kSmallReadSize = 14;
4385 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4386 rv = trans->Read(buf, kSmallReadSize, read_callback.callback());
4387 if (rv == net::ERR_IO_PENDING) {
4388 data.CompleteRead();
4389 rv = read_callback.WaitForResult();
4391 if (rv > 0) {
4392 EXPECT_EQ(kSmallReadSize, rv);
4393 content.append(buf->data(), rv);
4394 } else if (rv < 0) {
4395 FAIL() << "Unexpected read error: " << rv;
4397 reads_completed++;
4398 } while (rv > 0);
4400 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
4402 out.response_data.swap(content);
4404 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4405 // MockClientSocketFactory) are still alive.
4406 MessageLoop::current()->RunUntilIdle();
4408 // Verify that we consumed all test data.
4409 helper.VerifyDataConsumed();
4411 EXPECT_EQ(OK, out.rv);
4412 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4413 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4416 // Verify the case where we buffer data but read it after it has been buffered.
4417 TEST_P(SpdyNetworkTransactionSpdy3Test, BufferedAll) {
4418 BufferedSpdyFramer framer(3, false);
4420 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4421 MockWrite writes[] = { CreateMockWrite(*req) };
4423 // 5 data frames in a single read.
4424 scoped_ptr<SpdyFrame> syn_reply(
4425 ConstructSpdyGetSynReply(NULL, 0, 1));
4426 syn_reply->set_flags(CONTROL_FLAG_NONE); // turn off FIN bit
4427 scoped_ptr<SpdyFrame> data_frame(
4428 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4429 scoped_ptr<SpdyFrame> data_frame_fin(
4430 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
4431 const SpdyFrame* frames[5] = {
4432 syn_reply.get(),
4433 data_frame.get(),
4434 data_frame.get(),
4435 data_frame.get(),
4436 data_frame_fin.get()
4438 char combined_frames[200];
4439 int combined_frames_len =
4440 CombineFrames(frames, arraysize(frames),
4441 combined_frames, arraysize(combined_frames));
4443 MockRead reads[] = {
4444 MockRead(ASYNC, combined_frames, combined_frames_len),
4445 MockRead(ASYNC, 0, 0) // EOF
4448 DelayedSocketData data(1, reads, arraysize(reads),
4449 writes, arraysize(writes));
4451 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4452 BoundNetLog(), GetParam(), NULL);
4453 helper.RunPreTestSetup();
4454 helper.AddData(&data);
4455 HttpNetworkTransaction* trans = helper.trans();
4457 TestCompletionCallback callback;
4458 int rv = trans->Start(
4459 &CreateGetRequest(), callback.callback(), BoundNetLog());
4460 EXPECT_EQ(ERR_IO_PENDING, rv);
4462 TransactionHelperResult out = helper.output();
4463 out.rv = callback.WaitForResult();
4464 EXPECT_EQ(out.rv, OK);
4466 const HttpResponseInfo* response = trans->GetResponseInfo();
4467 EXPECT_TRUE(response->headers != NULL);
4468 EXPECT_TRUE(response->was_fetched_via_spdy);
4469 out.status_line = response->headers->GetStatusLine();
4470 out.response_info = *response; // Make a copy so we can verify.
4472 // Read Data
4473 TestCompletionCallback read_callback;
4475 std::string content;
4476 int reads_completed = 0;
4477 do {
4478 // Read small chunks at a time.
4479 const int kSmallReadSize = 14;
4480 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4481 rv = trans->Read(buf, kSmallReadSize, read_callback.callback());
4482 if (rv > 0) {
4483 EXPECT_EQ(kSmallReadSize, rv);
4484 content.append(buf->data(), rv);
4485 } else if (rv < 0) {
4486 FAIL() << "Unexpected read error: " << rv;
4488 reads_completed++;
4489 } while (rv > 0);
4491 EXPECT_EQ(3, reads_completed);
4493 out.response_data.swap(content);
4495 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4496 // MockClientSocketFactory) are still alive.
4497 MessageLoop::current()->RunUntilIdle();
4499 // Verify that we consumed all test data.
4500 helper.VerifyDataConsumed();
4502 EXPECT_EQ(OK, out.rv);
4503 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4504 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4507 // Verify the case where we buffer data and close the connection.
4508 TEST_P(SpdyNetworkTransactionSpdy3Test, BufferedClosed) {
4509 BufferedSpdyFramer framer(3, false);
4511 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4512 MockWrite writes[] = { CreateMockWrite(*req) };
4514 // All data frames in a single read.
4515 // NOTE: We don't FIN the stream.
4516 scoped_ptr<SpdyFrame> data_frame(
4517 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4518 const SpdyFrame* data_frames[4] = {
4519 data_frame.get(),
4520 data_frame.get(),
4521 data_frame.get(),
4522 data_frame.get()
4524 char combined_data_frames[100];
4525 int combined_data_frames_len =
4526 CombineFrames(data_frames, arraysize(data_frames),
4527 combined_data_frames, arraysize(combined_data_frames));
4528 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4529 MockRead reads[] = {
4530 CreateMockRead(*resp),
4531 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4532 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4533 MockRead(ASYNC, 0, 0) // EOF
4536 DelayedSocketData data(1, reads, arraysize(reads),
4537 writes, arraysize(writes));
4539 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4540 BoundNetLog(), GetParam(), NULL);
4541 helper.RunPreTestSetup();
4542 helper.AddData(&data);
4543 HttpNetworkTransaction* trans = helper.trans();
4545 TestCompletionCallback callback;
4547 int rv = trans->Start(
4548 &CreateGetRequest(), callback.callback(), BoundNetLog());
4549 EXPECT_EQ(ERR_IO_PENDING, rv);
4551 TransactionHelperResult out = helper.output();
4552 out.rv = callback.WaitForResult();
4553 EXPECT_EQ(out.rv, OK);
4555 const HttpResponseInfo* response = trans->GetResponseInfo();
4556 EXPECT_TRUE(response->headers != NULL);
4557 EXPECT_TRUE(response->was_fetched_via_spdy);
4558 out.status_line = response->headers->GetStatusLine();
4559 out.response_info = *response; // Make a copy so we can verify.
4561 // Read Data
4562 TestCompletionCallback read_callback;
4564 std::string content;
4565 int reads_completed = 0;
4566 do {
4567 // Read small chunks at a time.
4568 const int kSmallReadSize = 14;
4569 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4570 rv = trans->Read(buf, kSmallReadSize, read_callback.callback());
4571 if (rv == net::ERR_IO_PENDING) {
4572 data.CompleteRead();
4573 rv = read_callback.WaitForResult();
4575 if (rv > 0) {
4576 content.append(buf->data(), rv);
4577 } else if (rv < 0) {
4578 // This test intentionally closes the connection, and will get an error.
4579 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
4580 break;
4582 reads_completed++;
4583 } while (rv > 0);
4585 EXPECT_EQ(0, reads_completed);
4587 out.response_data.swap(content);
4589 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4590 // MockClientSocketFactory) are still alive.
4591 MessageLoop::current()->RunUntilIdle();
4593 // Verify that we consumed all test data.
4594 helper.VerifyDataConsumed();
4597 // Verify the case where we buffer data and cancel the transaction.
4598 TEST_P(SpdyNetworkTransactionSpdy3Test, BufferedCancelled) {
4599 BufferedSpdyFramer framer(3, false);
4601 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4602 MockWrite writes[] = { CreateMockWrite(*req) };
4604 // NOTE: We don't FIN the stream.
4605 scoped_ptr<SpdyFrame> data_frame(
4606 framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
4608 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4609 MockRead reads[] = {
4610 CreateMockRead(*resp),
4611 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4612 CreateMockRead(*data_frame),
4613 MockRead(ASYNC, 0, 0) // EOF
4616 DelayedSocketData data(1, reads, arraysize(reads),
4617 writes, arraysize(writes));
4619 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4620 BoundNetLog(), GetParam(), NULL);
4621 helper.RunPreTestSetup();
4622 helper.AddData(&data);
4623 HttpNetworkTransaction* trans = helper.trans();
4624 TestCompletionCallback callback;
4626 int rv = trans->Start(
4627 &CreateGetRequest(), callback.callback(), BoundNetLog());
4628 EXPECT_EQ(ERR_IO_PENDING, rv);
4630 TransactionHelperResult out = helper.output();
4631 out.rv = callback.WaitForResult();
4632 EXPECT_EQ(out.rv, OK);
4634 const HttpResponseInfo* response = trans->GetResponseInfo();
4635 EXPECT_TRUE(response->headers != NULL);
4636 EXPECT_TRUE(response->was_fetched_via_spdy);
4637 out.status_line = response->headers->GetStatusLine();
4638 out.response_info = *response; // Make a copy so we can verify.
4640 // Read Data
4641 TestCompletionCallback read_callback;
4643 do {
4644 const int kReadSize = 256;
4645 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
4646 rv = trans->Read(buf, kReadSize, read_callback.callback());
4647 if (rv == net::ERR_IO_PENDING) {
4648 // Complete the read now, which causes buffering to start.
4649 data.CompleteRead();
4650 // Destroy the transaction, causing the stream to get cancelled
4651 // and orphaning the buffered IO task.
4652 helper.ResetTrans();
4653 break;
4655 // We shouldn't get here in this test.
4656 FAIL() << "Unexpected read: " << rv;
4657 } while (rv > 0);
4659 // Flush the MessageLoop; this will cause the buffered IO task
4660 // to run for the final time.
4661 MessageLoop::current()->RunUntilIdle();
4663 // Verify that we consumed all test data.
4664 helper.VerifyDataConsumed();
4667 // Test that if the server requests persistence of settings, that we save
4668 // the settings in the HttpServerProperties.
4669 TEST_P(SpdyNetworkTransactionSpdy3Test, SettingsSaved) {
4670 static const SpdyHeaderInfo kSynReplyInfo = {
4671 SYN_REPLY, // Syn Reply
4672 1, // Stream ID
4673 0, // Associated Stream ID
4674 ConvertRequestPriorityToSpdyPriority(LOWEST, 3), // Priority
4675 0, // Credential Slot
4676 CONTROL_FLAG_NONE, // Control Flags
4677 false, // Compressed
4678 INVALID, // Status
4679 NULL, // Data
4680 0, // Data Length
4681 DATA_FLAG_NONE // Data Flags
4683 static const char* const kExtraHeaders[] = {
4684 ":status", "200",
4685 ":version", "HTTP/1.1"
4688 BoundNetLog net_log;
4689 NormalSpdyTransactionHelper helper(CreateGetRequest(), net_log,
4690 GetParam(), NULL);
4691 helper.RunPreTestSetup();
4693 // Verify that no settings exist initially.
4694 HostPortPair host_port_pair("www.google.com", helper.port());
4695 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4696 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4697 host_port_pair).empty());
4699 // Construct the request.
4700 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4701 MockWrite writes[] = { CreateMockWrite(*req) };
4703 // Construct the reply.
4704 scoped_ptr<SpdyFrame> reply(
4705 ConstructSpdyPacket(kSynReplyInfo,
4706 kExtraHeaders,
4707 arraysize(kExtraHeaders) / 2,
4708 NULL,
4709 0));
4711 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
4712 unsigned int kSampleValue1 = 0x0a0a0a0a;
4713 const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
4714 unsigned int kSampleValue2 = 0x0b0b0b0b;
4715 const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
4716 unsigned int kSampleValue3 = 0x0c0c0c0c;
4717 scoped_ptr<SpdyFrame> settings_frame;
4719 // Construct the SETTINGS frame.
4720 SettingsMap settings;
4721 // First add a persisted setting.
4722 settings[kSampleId1] =
4723 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
4724 // Next add a non-persisted setting.
4725 settings[kSampleId2] =
4726 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
4727 // Next add another persisted setting.
4728 settings[kSampleId3] =
4729 SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
4730 settings_frame.reset(ConstructSpdySettings(settings));
4733 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4734 MockRead reads[] = {
4735 CreateMockRead(*reply),
4736 CreateMockRead(*body),
4737 CreateMockRead(*settings_frame),
4738 MockRead(ASYNC, 0, 0) // EOF
4741 DelayedSocketData data(1, reads, arraysize(reads),
4742 writes, arraysize(writes));
4743 helper.AddData(&data);
4744 helper.RunDefaultTest();
4745 helper.VerifyDataConsumed();
4746 TransactionHelperResult out = helper.output();
4747 EXPECT_EQ(OK, out.rv);
4748 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4749 EXPECT_EQ("hello!", out.response_data);
4752 // Verify we had two persisted settings.
4753 const SettingsMap& settings_map =
4754 spdy_session_pool->http_server_properties()->GetSpdySettings(
4755 host_port_pair);
4756 ASSERT_EQ(2u, settings_map.size());
4758 // Verify the first persisted setting.
4759 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4760 EXPECT_TRUE(it1 != settings_map.end());
4761 SettingsFlagsAndValue flags_and_value1 = it1->second;
4762 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4763 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4765 // Verify the second persisted setting.
4766 SettingsMap::const_iterator it3 = settings_map.find(kSampleId3);
4767 EXPECT_TRUE(it3 != settings_map.end());
4768 SettingsFlagsAndValue flags_and_value3 = it3->second;
4769 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first);
4770 EXPECT_EQ(kSampleValue3, flags_and_value3.second);
4774 // Test that when there are settings saved that they are sent back to the
4775 // server upon session establishment.
4776 TEST_P(SpdyNetworkTransactionSpdy3Test, SettingsPlayback) {
4777 static const SpdyHeaderInfo kSynReplyInfo = {
4778 SYN_REPLY, // Syn Reply
4779 1, // Stream ID
4780 0, // Associated Stream ID
4781 ConvertRequestPriorityToSpdyPriority(LOWEST, 3), // Priority
4782 0, // Credential Slot
4783 CONTROL_FLAG_NONE, // Control Flags
4784 false, // Compressed
4785 INVALID, // Status
4786 NULL, // Data
4787 0, // Data Length
4788 DATA_FLAG_NONE // Data Flags
4790 static const char* kExtraHeaders[] = {
4791 ":status", "200",
4792 ":version", "HTTP/1.1"
4795 BoundNetLog net_log;
4796 NormalSpdyTransactionHelper helper(CreateGetRequest(), net_log,
4797 GetParam(), NULL);
4798 helper.RunPreTestSetup();
4800 // Verify that no settings exist initially.
4801 HostPortPair host_port_pair("www.google.com", helper.port());
4802 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4803 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4804 host_port_pair).empty());
4806 const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
4807 unsigned int kSampleValue1 = 0x0a0a0a0a;
4808 const SpdySettingsIds kSampleId2 = SETTINGS_ROUND_TRIP_TIME;
4809 unsigned int kSampleValue2 = 0x0c0c0c0c;
4811 // First add a persisted setting.
4812 spdy_session_pool->http_server_properties()->SetSpdySetting(
4813 host_port_pair,
4814 kSampleId1,
4815 SETTINGS_FLAG_PLEASE_PERSIST,
4816 kSampleValue1);
4818 // Next add another persisted setting.
4819 spdy_session_pool->http_server_properties()->SetSpdySetting(
4820 host_port_pair,
4821 kSampleId2,
4822 SETTINGS_FLAG_PLEASE_PERSIST,
4823 kSampleValue2);
4825 EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4826 host_port_pair).size());
4828 // Construct the SETTINGS frame.
4829 const SettingsMap& settings =
4830 spdy_session_pool->http_server_properties()->GetSpdySettings(
4831 host_port_pair);
4832 scoped_ptr<SpdyFrame> settings_frame(ConstructSpdySettings(settings));
4834 // Construct the request.
4835 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4837 MockWrite writes[] = {
4838 CreateMockWrite(*settings_frame),
4839 CreateMockWrite(*req),
4842 // Construct the reply.
4843 scoped_ptr<SpdyFrame> reply(
4844 ConstructSpdyPacket(kSynReplyInfo,
4845 kExtraHeaders,
4846 arraysize(kExtraHeaders) / 2,
4847 NULL,
4848 0));
4850 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4851 MockRead reads[] = {
4852 CreateMockRead(*reply),
4853 CreateMockRead(*body),
4854 MockRead(ASYNC, 0, 0) // EOF
4857 DelayedSocketData data(2, reads, arraysize(reads),
4858 writes, arraysize(writes));
4859 helper.AddData(&data);
4860 helper.RunDefaultTest();
4861 helper.VerifyDataConsumed();
4862 TransactionHelperResult out = helper.output();
4863 EXPECT_EQ(OK, out.rv);
4864 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4865 EXPECT_EQ("hello!", out.response_data);
4868 // Verify we had two persisted settings.
4869 const SettingsMap& settings_map =
4870 spdy_session_pool->http_server_properties()->GetSpdySettings(
4871 host_port_pair);
4872 ASSERT_EQ(2u, settings_map.size());
4874 // Verify the first persisted setting.
4875 SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4876 EXPECT_TRUE(it1 != settings_map.end());
4877 SettingsFlagsAndValue flags_and_value1 = it1->second;
4878 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4879 EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4881 // Verify the second persisted setting.
4882 SettingsMap::const_iterator it2 = settings_map.find(kSampleId2);
4883 EXPECT_TRUE(it2 != settings_map.end());
4884 SettingsFlagsAndValue flags_and_value2 = it2->second;
4885 EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first);
4886 EXPECT_EQ(kSampleValue2, flags_and_value2.second);
4890 TEST_P(SpdyNetworkTransactionSpdy3Test, GoAwayWithActiveStream) {
4891 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4892 MockWrite writes[] = { CreateMockWrite(*req) };
4894 scoped_ptr<SpdyFrame> go_away(ConstructSpdyGoAway());
4895 MockRead reads[] = {
4896 CreateMockRead(*go_away),
4897 MockRead(ASYNC, 0, 0), // EOF
4900 DelayedSocketData data(1, reads, arraysize(reads),
4901 writes, arraysize(writes));
4902 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4903 BoundNetLog(), GetParam(), NULL);
4904 helper.AddData(&data);
4905 helper.RunToCompletion(&data);
4906 TransactionHelperResult out = helper.output();
4907 EXPECT_EQ(ERR_ABORTED, out.rv);
4910 TEST_P(SpdyNetworkTransactionSpdy3Test, CloseWithActiveStream) {
4911 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4912 MockWrite writes[] = { CreateMockWrite(*req) };
4914 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4915 MockRead reads[] = {
4916 CreateMockRead(*resp),
4917 MockRead(SYNCHRONOUS, 0, 0) // EOF
4920 DelayedSocketData data(1, reads, arraysize(reads),
4921 writes, arraysize(writes));
4922 BoundNetLog log;
4923 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4924 log, GetParam(), NULL);
4925 helper.RunPreTestSetup();
4926 helper.AddData(&data);
4927 HttpNetworkTransaction* trans = helper.trans();
4929 TestCompletionCallback callback;
4930 TransactionHelperResult out;
4931 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
4933 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4934 out.rv = callback.WaitForResult();
4935 EXPECT_EQ(out.rv, OK);
4937 const HttpResponseInfo* response = trans->GetResponseInfo();
4938 EXPECT_TRUE(response->headers != NULL);
4939 EXPECT_TRUE(response->was_fetched_via_spdy);
4940 out.rv = ReadTransaction(trans, &out.response_data);
4941 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4943 // Verify that we consumed all test data.
4944 helper.VerifyDataConsumed();
4947 // Test to make sure we can correctly connect through a proxy.
4948 TEST_P(SpdyNetworkTransactionSpdy3Test, ProxyConnect) {
4949 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4950 BoundNetLog(), GetParam(), NULL);
4951 helper.session_deps().reset(new SpdySessionDependencies(
4952 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4953 helper.SetSession(make_scoped_refptr(
4954 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4955 helper.RunPreTestSetup();
4956 HttpNetworkTransaction* trans = helper.trans();
4958 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4959 "Host: www.google.com\r\n"
4960 "Proxy-Connection: keep-alive\r\n\r\n"};
4961 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4962 "Host: www.google.com\r\n"
4963 "Proxy-Connection: keep-alive\r\n\r\n"};
4964 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4965 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4966 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4967 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4969 MockWrite writes_SPDYNPN[] = {
4970 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4971 CreateMockWrite(*req, 2),
4973 MockRead reads_SPDYNPN[] = {
4974 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4975 CreateMockRead(*resp, 3),
4976 CreateMockRead(*body.get(), 4),
4977 MockRead(ASYNC, 0, 0, 5),
4980 MockWrite writes_SPDYSSL[] = {
4981 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4982 CreateMockWrite(*req, 2),
4984 MockRead reads_SPDYSSL[] = {
4985 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4986 CreateMockRead(*resp, 3),
4987 CreateMockRead(*body.get(), 4),
4988 MockRead(ASYNC, 0, 0, 5),
4991 MockWrite writes_SPDYNOSSL[] = {
4992 CreateMockWrite(*req, 0),
4995 MockRead reads_SPDYNOSSL[] = {
4996 CreateMockRead(*resp, 1),
4997 CreateMockRead(*body.get(), 2),
4998 MockRead(ASYNC, 0, 0, 3),
5001 scoped_ptr<OrderedSocketData> data;
5002 switch(GetParam()) {
5003 case SPDYNOSSL:
5004 data.reset(new OrderedSocketData(reads_SPDYNOSSL,
5005 arraysize(reads_SPDYNOSSL),
5006 writes_SPDYNOSSL,
5007 arraysize(writes_SPDYNOSSL)));
5008 break;
5009 case SPDYSSL:
5010 data.reset(new OrderedSocketData(reads_SPDYSSL,
5011 arraysize(reads_SPDYSSL),
5012 writes_SPDYSSL,
5013 arraysize(writes_SPDYSSL)));
5014 break;
5015 case SPDYNPN:
5016 data.reset(new OrderedSocketData(reads_SPDYNPN,
5017 arraysize(reads_SPDYNPN),
5018 writes_SPDYNPN,
5019 arraysize(writes_SPDYNPN)));
5020 break;
5021 default:
5022 NOTREACHED();
5025 helper.AddData(data.get());
5026 TestCompletionCallback callback;
5028 int rv = trans->Start(
5029 &CreateGetRequest(), callback.callback(), BoundNetLog());
5030 EXPECT_EQ(ERR_IO_PENDING, rv);
5032 rv = callback.WaitForResult();
5033 EXPECT_EQ(0, rv);
5035 // Verify the SYN_REPLY.
5036 HttpResponseInfo response = *trans->GetResponseInfo();
5037 EXPECT_TRUE(response.headers != NULL);
5038 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5040 std::string response_data;
5041 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
5042 EXPECT_EQ("hello!", response_data);
5043 helper.VerifyDataConsumed();
5046 // Test to make sure we can correctly connect through a proxy to www.google.com,
5047 // if there already exists a direct spdy connection to www.google.com. See
5048 // http://crbug.com/49874
5049 TEST_P(SpdyNetworkTransactionSpdy3Test, DirectConnectProxyReconnect) {
5050 // When setting up the first transaction, we store the SpdySessionPool so that
5051 // we can use the same pool in the second transaction.
5052 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5053 BoundNetLog(), GetParam(), NULL);
5055 // Use a proxy service which returns a proxy fallback list from DIRECT to
5056 // myproxy:70. For this test there will be no fallback, so it is equivalent
5057 // to simply DIRECT. The reason for appending the second proxy is to verify
5058 // that the session pool key used does is just "DIRECT".
5059 helper.session_deps().reset(new SpdySessionDependencies(
5060 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
5061 helper.SetSession(make_scoped_refptr(
5062 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
5064 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
5065 helper.RunPreTestSetup();
5067 // Construct and send a simple GET request.
5068 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5069 MockWrite writes[] = {
5070 CreateMockWrite(*req, 1),
5073 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5074 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
5075 MockRead reads[] = {
5076 CreateMockRead(*resp, 2),
5077 CreateMockRead(*body, 3),
5078 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
5079 MockRead(ASYNC, 0, 5) // EOF
5081 OrderedSocketData data(reads, arraysize(reads),
5082 writes, arraysize(writes));
5083 helper.AddData(&data);
5084 HttpNetworkTransaction* trans = helper.trans();
5086 TestCompletionCallback callback;
5087 TransactionHelperResult out;
5088 out.rv = trans->Start(
5089 &CreateGetRequest(), callback.callback(), BoundNetLog());
5091 EXPECT_EQ(out.rv, ERR_IO_PENDING);
5092 out.rv = callback.WaitForResult();
5093 EXPECT_EQ(out.rv, OK);
5095 const HttpResponseInfo* response = trans->GetResponseInfo();
5096 EXPECT_TRUE(response->headers != NULL);
5097 EXPECT_TRUE(response->was_fetched_via_spdy);
5098 out.rv = ReadTransaction(trans, &out.response_data);
5099 EXPECT_EQ(OK, out.rv);
5100 out.status_line = response->headers->GetStatusLine();
5101 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5102 EXPECT_EQ("hello!", out.response_data);
5104 // Check that the SpdySession is still in the SpdySessionPool.
5105 HostPortPair host_port_pair("www.google.com", helper.port());
5106 HostPortProxyPair session_pool_key_direct(
5107 host_port_pair, ProxyServer::Direct());
5108 EXPECT_TRUE(spdy_session_pool->HasSession(session_pool_key_direct));
5109 HostPortProxyPair session_pool_key_proxy(
5110 host_port_pair,
5111 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP));
5112 EXPECT_FALSE(spdy_session_pool->HasSession(session_pool_key_proxy));
5114 // Set up data for the proxy connection.
5115 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
5116 "Host: www.google.com\r\n"
5117 "Proxy-Connection: keep-alive\r\n\r\n"};
5118 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
5119 "Host: www.google.com\r\n"
5120 "Proxy-Connection: keep-alive\r\n\r\n"};
5121 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
5122 scoped_ptr<SpdyFrame> req2(ConstructSpdyGet(
5123 "http://www.google.com/foo.dat", false, 1, LOWEST));
5124 scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
5125 scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
5127 MockWrite writes_SPDYNPN[] = {
5128 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
5129 CreateMockWrite(*req2, 2),
5131 MockRead reads_SPDYNPN[] = {
5132 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
5133 CreateMockRead(*resp2, 3),
5134 CreateMockRead(*body2, 4),
5135 MockRead(ASYNC, 0, 5) // EOF
5138 MockWrite writes_SPDYNOSSL[] = {
5139 CreateMockWrite(*req2, 0),
5141 MockRead reads_SPDYNOSSL[] = {
5142 CreateMockRead(*resp2, 1),
5143 CreateMockRead(*body2, 2),
5144 MockRead(ASYNC, 0, 3) // EOF
5147 MockWrite writes_SPDYSSL[] = {
5148 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
5149 CreateMockWrite(*req2, 2),
5151 MockRead reads_SPDYSSL[] = {
5152 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
5153 CreateMockRead(*resp2, 3),
5154 CreateMockRead(*body2, 4),
5155 MockRead(ASYNC, 0, 0, 5),
5158 scoped_ptr<OrderedSocketData> data_proxy;
5159 switch(GetParam()) {
5160 case SPDYNPN:
5161 data_proxy.reset(new OrderedSocketData(reads_SPDYNPN,
5162 arraysize(reads_SPDYNPN),
5163 writes_SPDYNPN,
5164 arraysize(writes_SPDYNPN)));
5165 break;
5166 case SPDYNOSSL:
5167 data_proxy.reset(new OrderedSocketData(reads_SPDYNOSSL,
5168 arraysize(reads_SPDYNOSSL),
5169 writes_SPDYNOSSL,
5170 arraysize(writes_SPDYNOSSL)));
5171 break;
5172 case SPDYSSL:
5173 data_proxy.reset(new OrderedSocketData(reads_SPDYSSL,
5174 arraysize(reads_SPDYSSL),
5175 writes_SPDYSSL,
5176 arraysize(writes_SPDYSSL)));
5177 break;
5178 default:
5179 NOTREACHED();
5182 // Create another request to www.google.com, but this time through a proxy.
5183 HttpRequestInfo request_proxy;
5184 request_proxy.method = "GET";
5185 request_proxy.url = GURL("http://www.google.com/foo.dat");
5186 request_proxy.load_flags = 0;
5187 scoped_ptr<SpdySessionDependencies> ssd_proxy(new SpdySessionDependencies());
5188 // Ensure that this transaction uses the same SpdySessionPool.
5189 scoped_refptr<HttpNetworkSession> session_proxy(
5190 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
5191 NormalSpdyTransactionHelper helper_proxy(request_proxy,
5192 BoundNetLog(), GetParam(), NULL);
5193 HttpNetworkSessionPeer session_peer(session_proxy);
5194 scoped_ptr<net::ProxyService> proxy_service(
5195 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
5196 session_peer.SetProxyService(proxy_service.get());
5197 helper_proxy.session_deps().swap(ssd_proxy);
5198 helper_proxy.SetSession(session_proxy);
5199 helper_proxy.RunPreTestSetup();
5200 helper_proxy.AddData(data_proxy.get());
5202 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
5203 TestCompletionCallback callback_proxy;
5204 int rv = trans_proxy->Start(
5205 &request_proxy, callback_proxy.callback(), BoundNetLog());
5206 EXPECT_EQ(ERR_IO_PENDING, rv);
5207 rv = callback_proxy.WaitForResult();
5208 EXPECT_EQ(0, rv);
5210 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
5211 EXPECT_TRUE(response_proxy.headers != NULL);
5212 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
5214 std::string response_data;
5215 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
5216 EXPECT_EQ("hello!", response_data);
5218 data.CompleteRead();
5219 helper_proxy.VerifyDataConsumed();
5222 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
5223 // on a new connection, if the connection was previously known to be good.
5224 // This can happen when a server reboots without saying goodbye, or when
5225 // we're behind a NAT that masked the RST.
5226 TEST_P(SpdyNetworkTransactionSpdy3Test, VerifyRetryOnConnectionReset) {
5227 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5228 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
5229 MockRead reads[] = {
5230 CreateMockRead(*resp),
5231 CreateMockRead(*body),
5232 MockRead(ASYNC, ERR_IO_PENDING),
5233 MockRead(ASYNC, ERR_CONNECTION_RESET),
5236 MockRead reads2[] = {
5237 CreateMockRead(*resp),
5238 CreateMockRead(*body),
5239 MockRead(ASYNC, 0, 0) // EOF
5242 // This test has a couple of variants.
5243 enum {
5244 // Induce the RST while waiting for our transaction to send.
5245 VARIANT_RST_DURING_SEND_COMPLETION,
5246 // Induce the RST while waiting for our transaction to read.
5247 // In this case, the send completed - everything copied into the SNDBUF.
5248 VARIANT_RST_DURING_READ_COMPLETION
5251 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
5252 variant <= VARIANT_RST_DURING_READ_COMPLETION;
5253 ++variant) {
5254 DelayedSocketData data1(1, reads, arraysize(reads), NULL, 0);
5256 DelayedSocketData data2(1, reads2, arraysize(reads2), NULL, 0);
5258 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5259 BoundNetLog(), GetParam(), NULL);
5260 helper.AddData(&data1);
5261 helper.AddData(&data2);
5262 helper.RunPreTestSetup();
5264 for (int i = 0; i < 2; ++i) {
5265 scoped_ptr<HttpNetworkTransaction> trans(
5266 new HttpNetworkTransaction(helper.session()));
5268 TestCompletionCallback callback;
5269 int rv = trans->Start(
5270 &helper.request(), callback.callback(), BoundNetLog());
5271 EXPECT_EQ(ERR_IO_PENDING, rv);
5272 // On the second transaction, we trigger the RST.
5273 if (i == 1) {
5274 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
5275 // Writes to the socket complete asynchronously on SPDY by running
5276 // through the message loop. Complete the write here.
5277 MessageLoop::current()->RunUntilIdle();
5280 // Now schedule the ERR_CONNECTION_RESET.
5281 EXPECT_EQ(3u, data1.read_index());
5282 data1.CompleteRead();
5283 EXPECT_EQ(4u, data1.read_index());
5285 rv = callback.WaitForResult();
5286 EXPECT_EQ(OK, rv);
5288 const HttpResponseInfo* response = trans->GetResponseInfo();
5289 ASSERT_TRUE(response != NULL);
5290 EXPECT_TRUE(response->headers != NULL);
5291 EXPECT_TRUE(response->was_fetched_via_spdy);
5292 std::string response_data;
5293 rv = ReadTransaction(trans.get(), &response_data);
5294 EXPECT_EQ(OK, rv);
5295 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5296 EXPECT_EQ("hello!", response_data);
5299 helper.VerifyDataConsumed();
5303 // Test that turning SPDY on and off works properly.
5304 TEST_P(SpdyNetworkTransactionSpdy3Test, SpdyOnOffToggle) {
5305 net::HttpStreamFactory::set_spdy_enabled(true);
5306 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5307 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
5309 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5310 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
5311 MockRead spdy_reads[] = {
5312 CreateMockRead(*resp),
5313 CreateMockRead(*body),
5314 MockRead(ASYNC, 0, 0) // EOF
5317 DelayedSocketData data(1, spdy_reads, arraysize(spdy_reads),
5318 spdy_writes, arraysize(spdy_writes));
5319 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5320 BoundNetLog(), GetParam(), NULL);
5321 helper.RunToCompletion(&data);
5322 TransactionHelperResult out = helper.output();
5323 EXPECT_EQ(OK, out.rv);
5324 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5325 EXPECT_EQ("hello!", out.response_data);
5327 net::HttpStreamFactory::set_spdy_enabled(false);
5328 MockRead http_reads[] = {
5329 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5330 MockRead("hello from http"),
5331 MockRead(SYNCHRONOUS, OK),
5333 DelayedSocketData data2(1, http_reads, arraysize(http_reads), NULL, 0);
5334 NormalSpdyTransactionHelper helper2(CreateGetRequest(),
5335 BoundNetLog(), GetParam(), NULL);
5336 helper2.SetSpdyDisabled();
5337 helper2.RunToCompletion(&data2);
5338 TransactionHelperResult out2 = helper2.output();
5339 EXPECT_EQ(OK, out2.rv);
5340 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
5341 EXPECT_EQ("hello from http", out2.response_data);
5343 net::HttpStreamFactory::set_spdy_enabled(true);
5346 // Tests that Basic authentication works over SPDY
5347 TEST_P(SpdyNetworkTransactionSpdy3Test, SpdyBasicAuth) {
5348 net::HttpStreamFactory::set_spdy_enabled(true);
5350 // The first request will be a bare GET, the second request will be a
5351 // GET with an Authorization header.
5352 scoped_ptr<SpdyFrame> req_get(
5353 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5354 const char* const kExtraAuthorizationHeaders[] = {
5355 "authorization",
5356 "Basic Zm9vOmJhcg==",
5358 scoped_ptr<SpdyFrame> req_get_authorization(
5359 ConstructSpdyGet(
5360 kExtraAuthorizationHeaders,
5361 arraysize(kExtraAuthorizationHeaders) / 2,
5362 false, 3, LOWEST));
5363 MockWrite spdy_writes[] = {
5364 CreateMockWrite(*req_get, 1),
5365 CreateMockWrite(*req_get_authorization, 4),
5368 // The first response is a 401 authentication challenge, and the second
5369 // response will be a 200 response since the second request includes a valid
5370 // Authorization header.
5371 const char* const kExtraAuthenticationHeaders[] = {
5372 "www-authenticate",
5373 "Basic realm=\"MyRealm\""
5375 scoped_ptr<SpdyFrame> resp_authentication(
5376 ConstructSpdySynReplyError(
5377 "401 Authentication Required",
5378 kExtraAuthenticationHeaders,
5379 arraysize(kExtraAuthenticationHeaders) / 2,
5380 1));
5381 scoped_ptr<SpdyFrame> body_authentication(
5382 ConstructSpdyBodyFrame(1, true));
5383 scoped_ptr<SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
5384 scoped_ptr<SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
5385 MockRead spdy_reads[] = {
5386 CreateMockRead(*resp_authentication, 2),
5387 CreateMockRead(*body_authentication, 3),
5388 CreateMockRead(*resp_data, 5),
5389 CreateMockRead(*body_data, 6),
5390 MockRead(ASYNC, 0, 7),
5393 OrderedSocketData data(spdy_reads, arraysize(spdy_reads),
5394 spdy_writes, arraysize(spdy_writes));
5395 HttpRequestInfo request(CreateGetRequest());
5396 BoundNetLog net_log;
5397 NormalSpdyTransactionHelper helper(request, net_log, GetParam(), NULL);
5399 helper.RunPreTestSetup();
5400 helper.AddData(&data);
5401 HttpNetworkTransaction* trans = helper.trans();
5402 TestCompletionCallback callback;
5403 const int rv_start = trans->Start(&request, callback.callback(), net_log);
5404 EXPECT_EQ(ERR_IO_PENDING, rv_start);
5405 const int rv_start_complete = callback.WaitForResult();
5406 EXPECT_EQ(OK, rv_start_complete);
5408 // Make sure the response has an auth challenge.
5409 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
5410 ASSERT_TRUE(response_start != NULL);
5411 ASSERT_TRUE(response_start->headers != NULL);
5412 EXPECT_EQ(401, response_start->headers->response_code());
5413 EXPECT_TRUE(response_start->was_fetched_via_spdy);
5414 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
5415 ASSERT_TRUE(auth_challenge != NULL);
5416 EXPECT_FALSE(auth_challenge->is_proxy);
5417 EXPECT_EQ("basic", auth_challenge->scheme);
5418 EXPECT_EQ("MyRealm", auth_challenge->realm);
5420 // Restart with a username/password.
5421 AuthCredentials credentials(ASCIIToUTF16("foo"), ASCIIToUTF16("bar"));
5422 TestCompletionCallback callback_restart;
5423 const int rv_restart = trans->RestartWithAuth(
5424 credentials, callback_restart.callback());
5425 EXPECT_EQ(ERR_IO_PENDING, rv_restart);
5426 const int rv_restart_complete = callback_restart.WaitForResult();
5427 EXPECT_EQ(OK, rv_restart_complete);
5428 // TODO(cbentzel): This is actually the same response object as before, but
5429 // data has changed.
5430 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
5431 ASSERT_TRUE(response_restart != NULL);
5432 ASSERT_TRUE(response_restart->headers != NULL);
5433 EXPECT_EQ(200, response_restart->headers->response_code());
5434 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
5437 TEST_P(SpdyNetworkTransactionSpdy3Test, ServerPushWithHeaders) {
5438 static const unsigned char kPushBodyFrame[] = {
5439 0x00, 0x00, 0x00, 0x02, // header, ID
5440 0x01, 0x00, 0x00, 0x06, // FIN, length
5441 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5443 scoped_ptr<SpdyFrame>
5444 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5445 scoped_ptr<SpdyFrame>
5446 stream1_body(ConstructSpdyBodyFrame(1, true));
5447 MockWrite writes[] = {
5448 CreateMockWrite(*stream1_syn, 1),
5451 static const char* const kInitialHeaders[] = {
5452 ":scheme", "http",
5453 ":host", "www.google.com",
5454 ":path", "/foo.dat",
5456 static const char* const kLateHeaders[] = {
5457 "hello",
5458 "bye",
5459 ":status",
5460 "200",
5461 ":version",
5462 "HTTP/1.1"
5464 scoped_ptr<SpdyFrame>
5465 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
5466 arraysize(kInitialHeaders) / 2,
5467 false,
5469 LOWEST,
5470 SYN_STREAM,
5471 CONTROL_FLAG_NONE,
5472 NULL,
5474 1));
5475 scoped_ptr<SpdyFrame>
5476 stream2_headers(ConstructSpdyControlFrame(kLateHeaders,
5477 arraysize(kLateHeaders) / 2,
5478 false,
5480 LOWEST,
5481 HEADERS,
5482 CONTROL_FLAG_NONE,
5483 NULL,
5485 0));
5487 scoped_ptr<SpdyFrame>
5488 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5489 MockRead reads[] = {
5490 CreateMockRead(*stream1_reply, 2),
5491 CreateMockRead(*stream2_syn, 3),
5492 CreateMockRead(*stream2_headers, 4),
5493 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5494 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
5495 arraysize(kPushBodyFrame), 6),
5496 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5499 HttpResponseInfo response;
5500 HttpResponseInfo response2;
5501 std::string expected_push_result("pushed");
5502 OrderedSocketData data(reads, arraysize(reads),
5503 writes, arraysize(writes));
5504 RunServerPushTest(&data,
5505 &response,
5506 &response2,
5507 expected_push_result);
5509 // Verify the SYN_REPLY.
5510 EXPECT_TRUE(response.headers != NULL);
5511 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5513 // Verify the pushed stream.
5514 EXPECT_TRUE(response2.headers != NULL);
5515 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5518 TEST_P(SpdyNetworkTransactionSpdy3Test, ServerPushClaimBeforeHeaders) {
5519 // We push a stream and attempt to claim it before the headers come down.
5520 static const unsigned char kPushBodyFrame[] = {
5521 0x00, 0x00, 0x00, 0x02, // header, ID
5522 0x01, 0x00, 0x00, 0x06, // FIN, length
5523 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5525 scoped_ptr<SpdyFrame>
5526 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5527 scoped_ptr<SpdyFrame>
5528 stream1_body(ConstructSpdyBodyFrame(1, true));
5529 MockWrite writes[] = {
5530 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5533 static const char* const kInitialHeaders[] = {
5534 ":scheme", "http",
5535 ":host", "www.google.com",
5536 ":path", "/foo.dat"
5538 static const char* const kLateHeaders[] = {
5539 "hello",
5540 "bye",
5541 ":status",
5542 "200",
5543 ":version",
5544 "HTTP/1.1"
5546 scoped_ptr<SpdyFrame>
5547 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
5548 arraysize(kInitialHeaders) / 2,
5549 false,
5551 LOWEST,
5552 SYN_STREAM,
5553 CONTROL_FLAG_NONE,
5554 NULL,
5556 1));
5557 scoped_ptr<SpdyFrame>
5558 stream2_headers(ConstructSpdyControlFrame(kLateHeaders,
5559 arraysize(kLateHeaders) / 2,
5560 false,
5562 LOWEST,
5563 HEADERS,
5564 CONTROL_FLAG_NONE,
5565 NULL,
5567 0));
5569 scoped_ptr<SpdyFrame>
5570 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5571 MockRead reads[] = {
5572 CreateMockRead(*stream1_reply, 1),
5573 CreateMockRead(*stream2_syn, 2),
5574 CreateMockRead(*stream1_body, 3),
5575 CreateMockRead(*stream2_headers, 4),
5576 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
5577 arraysize(kPushBodyFrame), 5),
5578 MockRead(ASYNC, 0, 6), // EOF
5581 HttpResponseInfo response;
5582 HttpResponseInfo response2;
5583 std::string expected_push_result("pushed");
5584 DeterministicSocketData data(reads, arraysize(reads),
5585 writes, arraysize(writes));
5587 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5588 BoundNetLog(), GetParam(), NULL);
5589 helper.SetDeterministic();
5590 helper.AddDeterministicData(&data);
5591 helper.RunPreTestSetup();
5593 HttpNetworkTransaction* trans = helper.trans();
5595 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5596 // and the body of the primary stream, but before we've received the HEADERS
5597 // for the pushed stream.
5598 data.SetStop(3);
5600 // Start the transaction.
5601 TestCompletionCallback callback;
5602 int rv = trans->Start(
5603 &CreateGetRequest(), callback.callback(), BoundNetLog());
5604 EXPECT_EQ(ERR_IO_PENDING, rv);
5605 data.Run();
5606 rv = callback.WaitForResult();
5607 EXPECT_EQ(0, rv);
5609 // Request the pushed path. At this point, we've received the push, but the
5610 // headers are not yet complete.
5611 scoped_ptr<HttpNetworkTransaction> trans2(
5612 new HttpNetworkTransaction(helper.session()));
5613 rv = trans2->Start(
5614 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5615 EXPECT_EQ(ERR_IO_PENDING, rv);
5616 data.RunFor(3);
5617 MessageLoop::current()->RunUntilIdle();
5619 // Read the server push body.
5620 std::string result2;
5621 ReadResult(trans2.get(), &data, &result2);
5622 // Read the response body.
5623 std::string result;
5624 ReadResult(trans, &data, &result);
5626 // Verify that the received push data is same as the expected push data.
5627 EXPECT_EQ(result2.compare(expected_push_result), 0)
5628 << "Received data: "
5629 << result2
5630 << "||||| Expected data: "
5631 << expected_push_result;
5633 // Verify the SYN_REPLY.
5634 // Copy the response info, because trans goes away.
5635 response = *trans->GetResponseInfo();
5636 response2 = *trans2->GetResponseInfo();
5638 VerifyStreamsClosed(helper);
5640 // Verify the SYN_REPLY.
5641 EXPECT_TRUE(response.headers != NULL);
5642 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5644 // Verify the pushed stream.
5645 EXPECT_TRUE(response2.headers != NULL);
5646 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5648 // Read the final EOF (which will close the session)
5649 data.RunFor(1);
5651 // Verify that we consumed all test data.
5652 EXPECT_TRUE(data.at_read_eof());
5653 EXPECT_TRUE(data.at_write_eof());
5656 TEST_P(SpdyNetworkTransactionSpdy3Test, ServerPushWithTwoHeaderFrames) {
5657 // We push a stream and attempt to claim it before the headers come down.
5658 static const unsigned char kPushBodyFrame[] = {
5659 0x00, 0x00, 0x00, 0x02, // header, ID
5660 0x01, 0x00, 0x00, 0x06, // FIN, length
5661 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5663 scoped_ptr<SpdyFrame>
5664 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5665 scoped_ptr<SpdyFrame>
5666 stream1_body(ConstructSpdyBodyFrame(1, true));
5667 MockWrite writes[] = {
5668 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5671 static const char* const kInitialHeaders[] = {
5672 ":scheme", "http",
5673 ":host", "www.google.com",
5674 ":path", "/foo.dat"
5676 static const char* const kMiddleHeaders[] = {
5677 "hello",
5678 "bye",
5680 static const char* const kLateHeaders[] = {
5681 ":status",
5682 "200",
5683 ":version",
5684 "HTTP/1.1"
5686 scoped_ptr<SpdyFrame>
5687 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
5688 arraysize(kInitialHeaders) / 2,
5689 false,
5691 LOWEST,
5692 SYN_STREAM,
5693 CONTROL_FLAG_NONE,
5694 NULL,
5696 1));
5697 scoped_ptr<SpdyFrame>
5698 stream2_headers1(ConstructSpdyControlFrame(kMiddleHeaders,
5699 arraysize(kMiddleHeaders) / 2,
5700 false,
5702 LOWEST,
5703 HEADERS,
5704 CONTROL_FLAG_NONE,
5705 NULL,
5707 0));
5708 scoped_ptr<SpdyFrame>
5709 stream2_headers2(ConstructSpdyControlFrame(kLateHeaders,
5710 arraysize(kLateHeaders) / 2,
5711 false,
5713 LOWEST,
5714 HEADERS,
5715 CONTROL_FLAG_NONE,
5716 NULL,
5718 0));
5720 scoped_ptr<SpdyFrame>
5721 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5722 MockRead reads[] = {
5723 CreateMockRead(*stream1_reply, 1),
5724 CreateMockRead(*stream2_syn, 2),
5725 CreateMockRead(*stream1_body, 3),
5726 CreateMockRead(*stream2_headers1, 4),
5727 CreateMockRead(*stream2_headers2, 5),
5728 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
5729 arraysize(kPushBodyFrame), 6),
5730 MockRead(ASYNC, 0, 7), // EOF
5733 HttpResponseInfo response;
5734 HttpResponseInfo response2;
5735 std::string expected_push_result("pushed");
5736 DeterministicSocketData data(reads, arraysize(reads),
5737 writes, arraysize(writes));
5739 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5740 BoundNetLog(), GetParam(), NULL);
5741 helper.SetDeterministic();
5742 helper.AddDeterministicData(&data);
5743 helper.RunPreTestSetup();
5745 HttpNetworkTransaction* trans = helper.trans();
5747 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5748 // the first HEADERS frame, and the body of the primary stream, but before
5749 // we've received the final HEADERS for the pushed stream.
5750 data.SetStop(4);
5752 // Start the transaction.
5753 TestCompletionCallback callback;
5754 int rv = trans->Start(
5755 &CreateGetRequest(), callback.callback(), BoundNetLog());
5756 EXPECT_EQ(ERR_IO_PENDING, rv);
5757 data.Run();
5758 rv = callback.WaitForResult();
5759 EXPECT_EQ(0, rv);
5761 // Request the pushed path. At this point, we've received the push, but the
5762 // headers are not yet complete.
5763 scoped_ptr<HttpNetworkTransaction> trans2(
5764 new HttpNetworkTransaction(helper.session()));
5765 rv = trans2->Start(
5766 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5767 EXPECT_EQ(ERR_IO_PENDING, rv);
5768 data.RunFor(3);
5769 MessageLoop::current()->RunUntilIdle();
5771 // Read the server push body.
5772 std::string result2;
5773 ReadResult(trans2.get(), &data, &result2);
5774 // Read the response body.
5775 std::string result;
5776 ReadResult(trans, &data, &result);
5778 // Verify that the received push data is same as the expected push data.
5779 EXPECT_EQ(result2.compare(expected_push_result), 0)
5780 << "Received data: "
5781 << result2
5782 << "||||| Expected data: "
5783 << expected_push_result;
5785 // Verify the SYN_REPLY.
5786 // Copy the response info, because trans goes away.
5787 response = *trans->GetResponseInfo();
5788 response2 = *trans2->GetResponseInfo();
5790 VerifyStreamsClosed(helper);
5792 // Verify the SYN_REPLY.
5793 EXPECT_TRUE(response.headers != NULL);
5794 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5796 // Verify the pushed stream.
5797 EXPECT_TRUE(response2.headers != NULL);
5798 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5800 // Verify we got all the headers
5801 EXPECT_TRUE(response2.headers->HasHeaderValue(
5802 "scheme", "http"));
5803 EXPECT_TRUE(response2.headers->HasHeaderValue(
5804 "host", "www.google.com"));
5805 EXPECT_TRUE(response2.headers->HasHeaderValue(
5806 "path", "/foo.dat"));
5807 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5808 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
5809 EXPECT_TRUE(response2.headers->HasHeaderValue("version", "HTTP/1.1"));
5811 // Read the final EOF (which will close the session)
5812 data.RunFor(1);
5814 // Verify that we consumed all test data.
5815 EXPECT_TRUE(data.at_read_eof());
5816 EXPECT_TRUE(data.at_write_eof());
5819 TEST_P(SpdyNetworkTransactionSpdy3Test, ServerPushWithNoStatusHeaderFrames) {
5820 // We push a stream and attempt to claim it before the headers come down.
5821 static const unsigned char kPushBodyFrame[] = {
5822 0x00, 0x00, 0x00, 0x02, // header, ID
5823 0x01, 0x00, 0x00, 0x06, // FIN, length
5824 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5826 scoped_ptr<SpdyFrame>
5827 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5828 scoped_ptr<SpdyFrame>
5829 stream1_body(ConstructSpdyBodyFrame(1, true));
5830 MockWrite writes[] = {
5831 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5834 static const char* const kInitialHeaders[] = {
5835 ":scheme", "http",
5836 ":host", "www.google.com",
5837 ":path", "/foo.dat"
5839 static const char* const kMiddleHeaders[] = {
5840 "hello",
5841 "bye",
5843 scoped_ptr<SpdyFrame>
5844 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
5845 arraysize(kInitialHeaders) / 2,
5846 false,
5848 LOWEST,
5849 SYN_STREAM,
5850 CONTROL_FLAG_NONE,
5851 NULL,
5853 1));
5854 scoped_ptr<SpdyFrame>
5855 stream2_headers1(ConstructSpdyControlFrame(kMiddleHeaders,
5856 arraysize(kMiddleHeaders) / 2,
5857 false,
5859 LOWEST,
5860 HEADERS,
5861 CONTROL_FLAG_NONE,
5862 NULL,
5864 0));
5866 scoped_ptr<SpdyFrame>
5867 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5868 MockRead reads[] = {
5869 CreateMockRead(*stream1_reply, 1),
5870 CreateMockRead(*stream2_syn, 2),
5871 CreateMockRead(*stream1_body, 3),
5872 CreateMockRead(*stream2_headers1, 4),
5873 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
5874 arraysize(kPushBodyFrame), 5),
5875 MockRead(ASYNC, 0, 6), // EOF
5878 DeterministicSocketData data(reads, arraysize(reads),
5879 writes, arraysize(writes));
5881 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5882 BoundNetLog(), GetParam(), NULL);
5883 helper.SetDeterministic();
5884 helper.AddDeterministicData(&data);
5885 helper.RunPreTestSetup();
5887 HttpNetworkTransaction* trans = helper.trans();
5889 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5890 // the first HEADERS frame, and the body of the primary stream, but before
5891 // we've received the final HEADERS for the pushed stream.
5892 data.SetStop(4);
5894 // Start the transaction.
5895 TestCompletionCallback callback;
5896 int rv = trans->Start(
5897 &CreateGetRequest(), callback.callback(), BoundNetLog());
5898 EXPECT_EQ(ERR_IO_PENDING, rv);
5899 data.Run();
5900 rv = callback.WaitForResult();
5901 EXPECT_EQ(0, rv);
5903 // Request the pushed path. At this point, we've received the push, but the
5904 // headers are not yet complete.
5905 scoped_ptr<HttpNetworkTransaction> trans2(
5906 new HttpNetworkTransaction(helper.session()));
5907 rv = trans2->Start(
5908 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5909 EXPECT_EQ(ERR_IO_PENDING, rv);
5910 data.RunFor(2);
5911 MessageLoop::current()->RunUntilIdle();
5913 // Read the server push body.
5914 std::string result2;
5915 ReadResult(trans2.get(), &data, &result2);
5916 // Read the response body.
5917 std::string result;
5918 ReadResult(trans, &data, &result);
5919 EXPECT_EQ("hello!", result);
5921 // Verify that we haven't received any push data.
5922 EXPECT_EQ("", result2);
5924 // Verify the SYN_REPLY.
5925 // Copy the response info, because trans goes away.
5926 HttpResponseInfo response = *trans->GetResponseInfo();
5927 ASSERT_TRUE(trans2->GetResponseInfo() == NULL);
5929 VerifyStreamsClosed(helper);
5931 // Verify the SYN_REPLY.
5932 EXPECT_TRUE(response.headers != NULL);
5933 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5935 // Read the final EOF (which will close the session).
5936 data.RunFor(1);
5938 // Verify that we consumed all test data.
5939 EXPECT_TRUE(data.at_read_eof());
5940 EXPECT_TRUE(data.at_write_eof());
5943 TEST_P(SpdyNetworkTransactionSpdy3Test, SynReplyWithHeaders) {
5944 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5945 MockWrite writes[] = { CreateMockWrite(*req) };
5947 static const char* const kInitialHeaders[] = {
5948 ":status",
5949 "200 OK",
5950 ":version",
5951 "HTTP/1.1"
5953 static const char* const kLateHeaders[] = {
5954 "hello",
5955 "bye",
5957 scoped_ptr<SpdyFrame>
5958 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
5959 arraysize(kInitialHeaders) / 2,
5960 false,
5962 LOWEST,
5963 SYN_REPLY,
5964 CONTROL_FLAG_NONE,
5965 NULL,
5967 0));
5968 scoped_ptr<SpdyFrame>
5969 stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
5970 arraysize(kLateHeaders) / 2,
5971 false,
5973 LOWEST,
5974 HEADERS,
5975 CONTROL_FLAG_NONE,
5976 NULL,
5978 0));
5979 scoped_ptr<SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, true));
5980 MockRead reads[] = {
5981 CreateMockRead(*stream1_reply),
5982 CreateMockRead(*stream1_headers),
5983 CreateMockRead(*stream1_body),
5984 MockRead(ASYNC, 0, 0) // EOF
5987 DelayedSocketData data(1, reads, arraysize(reads),
5988 writes, arraysize(writes));
5989 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5990 BoundNetLog(), GetParam(), NULL);
5991 helper.RunToCompletion(&data);
5992 TransactionHelperResult out = helper.output();
5993 EXPECT_EQ(OK, out.rv);
5994 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5995 EXPECT_EQ("hello!", out.response_data);
5998 TEST_P(SpdyNetworkTransactionSpdy3Test, SynReplyWithLateHeaders) {
5999 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6000 MockWrite writes[] = { CreateMockWrite(*req) };
6002 static const char* const kInitialHeaders[] = {
6003 ":status",
6004 "200 OK",
6005 ":version",
6006 "HTTP/1.1"
6008 static const char* const kLateHeaders[] = {
6009 "hello",
6010 "bye",
6012 scoped_ptr<SpdyFrame>
6013 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
6014 arraysize(kInitialHeaders) / 2,
6015 false,
6017 LOWEST,
6018 SYN_REPLY,
6019 CONTROL_FLAG_NONE,
6020 NULL,
6022 0));
6023 scoped_ptr<SpdyFrame>
6024 stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
6025 arraysize(kLateHeaders) / 2,
6026 false,
6028 LOWEST,
6029 HEADERS,
6030 CONTROL_FLAG_NONE,
6031 NULL,
6033 0));
6034 scoped_ptr<SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, false));
6035 scoped_ptr<SpdyFrame> stream1_body2(ConstructSpdyBodyFrame(1, true));
6036 MockRead reads[] = {
6037 CreateMockRead(*stream1_reply),
6038 CreateMockRead(*stream1_body),
6039 CreateMockRead(*stream1_headers),
6040 CreateMockRead(*stream1_body2),
6041 MockRead(ASYNC, 0, 0) // EOF
6044 DelayedSocketData data(1, reads, arraysize(reads),
6045 writes, arraysize(writes));
6046 NormalSpdyTransactionHelper helper(CreateGetRequest(),
6047 BoundNetLog(), GetParam(), NULL);
6048 helper.RunToCompletion(&data);
6049 TransactionHelperResult out = helper.output();
6050 EXPECT_EQ(OK, out.rv);
6051 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
6052 EXPECT_EQ("hello!hello!", out.response_data);
6055 TEST_P(SpdyNetworkTransactionSpdy3Test, SynReplyWithDuplicateLateHeaders) {
6056 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6057 MockWrite writes[] = { CreateMockWrite(*req) };
6059 static const char* const kInitialHeaders[] = {
6060 ":status",
6061 "200 OK",
6062 ":version",
6063 "HTTP/1.1"
6065 static const char* const kLateHeaders[] = {
6066 ":status",
6067 "500 Server Error",
6069 scoped_ptr<SpdyFrame>
6070 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
6071 arraysize(kInitialHeaders) / 2,
6072 false,
6074 LOWEST,
6075 SYN_REPLY,
6076 CONTROL_FLAG_NONE,
6077 NULL,
6079 0));
6080 scoped_ptr<SpdyFrame>
6081 stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
6082 arraysize(kLateHeaders) / 2,
6083 false,
6085 LOWEST,
6086 HEADERS,
6087 CONTROL_FLAG_NONE,
6088 NULL,
6090 0));
6091 scoped_ptr<SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, false));
6092 scoped_ptr<SpdyFrame> stream1_body2(ConstructSpdyBodyFrame(1, true));
6093 MockRead reads[] = {
6094 CreateMockRead(*stream1_reply),
6095 CreateMockRead(*stream1_body),
6096 CreateMockRead(*stream1_headers),
6097 CreateMockRead(*stream1_body2),
6098 MockRead(ASYNC, 0, 0) // EOF
6101 DelayedSocketData data(1, reads, arraysize(reads),
6102 writes, arraysize(writes));
6103 NormalSpdyTransactionHelper helper(CreateGetRequest(),
6104 BoundNetLog(), GetParam(), NULL);
6105 helper.RunToCompletion(&data);
6106 TransactionHelperResult out = helper.output();
6107 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
6110 TEST_P(SpdyNetworkTransactionSpdy3Test, ServerPushCrossOriginCorrectness) {
6111 // In this test we want to verify that we can't accidentally push content
6112 // which can't be pushed by this content server.
6113 // This test assumes that:
6114 // - if we're requesting http://www.foo.com/barbaz
6115 // - the browser has made a connection to "www.foo.com".
6117 // A list of the URL to fetch, followed by the URL being pushed.
6118 static const char* const kTestCases[] = {
6119 "http://www.google.com/foo.html",
6120 "http://www.google.com:81/foo.js", // Bad port
6122 "http://www.google.com/foo.html",
6123 "https://www.google.com/foo.js", // Bad protocol
6125 "http://www.google.com/foo.html",
6126 "ftp://www.google.com/foo.js", // Invalid Protocol
6128 "http://www.google.com/foo.html",
6129 "http://blat.www.google.com/foo.js", // Cross subdomain
6131 "http://www.google.com/foo.html",
6132 "http://www.foo.com/foo.js", // Cross domain
6136 static const unsigned char kPushBodyFrame[] = {
6137 0x00, 0x00, 0x00, 0x02, // header, ID
6138 0x01, 0x00, 0x00, 0x06, // FIN, length
6139 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
6142 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
6143 const char* url_to_fetch = kTestCases[index];
6144 const char* url_to_push = kTestCases[index + 1];
6146 scoped_ptr<SpdyFrame>
6147 stream1_syn(ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
6148 scoped_ptr<SpdyFrame>
6149 stream1_body(ConstructSpdyBodyFrame(1, true));
6150 scoped_ptr<SpdyFrame> push_rst(
6151 ConstructSpdyRstStream(2, REFUSED_STREAM));
6152 MockWrite writes[] = {
6153 CreateMockWrite(*stream1_syn, 1),
6154 CreateMockWrite(*push_rst, 4),
6157 scoped_ptr<SpdyFrame>
6158 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
6159 scoped_ptr<SpdyFrame>
6160 stream2_syn(ConstructSpdyPush(NULL,
6164 url_to_push));
6165 scoped_ptr<SpdyFrame> rst(
6166 ConstructSpdyRstStream(2, CANCEL));
6168 MockRead reads[] = {
6169 CreateMockRead(*stream1_reply, 2),
6170 CreateMockRead(*stream2_syn, 3),
6171 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
6172 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
6173 arraysize(kPushBodyFrame), 6),
6174 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
6177 HttpResponseInfo response;
6178 OrderedSocketData data(reads, arraysize(reads),
6179 writes, arraysize(writes));
6181 HttpRequestInfo request;
6182 request.method = "GET";
6183 request.url = GURL(url_to_fetch);
6184 request.load_flags = 0;
6186 // Enable cross-origin push. Since we are not using a proxy, this should
6187 // not actually enable cross-origin SPDY push.
6188 scoped_ptr<SpdySessionDependencies> session_deps(
6189 new SpdySessionDependencies());
6190 session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
6191 NormalSpdyTransactionHelper helper(request,
6192 BoundNetLog(), GetParam(),
6193 session_deps.release());
6194 helper.RunPreTestSetup();
6195 helper.AddData(&data);
6197 HttpNetworkTransaction* trans = helper.trans();
6199 // Start the transaction with basic parameters.
6200 TestCompletionCallback callback;
6202 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6203 EXPECT_EQ(ERR_IO_PENDING, rv);
6204 rv = callback.WaitForResult();
6206 // Read the response body.
6207 std::string result;
6208 ReadResult(trans, &data, &result);
6210 // Verify that we consumed all test data.
6211 EXPECT_TRUE(data.at_read_eof());
6212 EXPECT_TRUE(data.at_write_eof());
6214 // Verify the SYN_REPLY.
6215 // Copy the response info, because trans goes away.
6216 response = *trans->GetResponseInfo();
6218 VerifyStreamsClosed(helper);
6220 // Verify the SYN_REPLY.
6221 EXPECT_TRUE(response.headers != NULL);
6222 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
6226 TEST_P(SpdyNetworkTransactionSpdy3Test, RetryAfterRefused) {
6227 // Construct the request.
6228 scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6229 scoped_ptr<SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
6230 MockWrite writes[] = {
6231 CreateMockWrite(*req, 1),
6232 CreateMockWrite(*req2, 3),
6235 scoped_ptr<SpdyFrame> refused(
6236 ConstructSpdyRstStream(1, REFUSED_STREAM));
6237 scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 3));
6238 scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(3, true));
6239 MockRead reads[] = {
6240 CreateMockRead(*refused, 2),
6241 CreateMockRead(*resp, 4),
6242 CreateMockRead(*body, 5),
6243 MockRead(ASYNC, 0, 6) // EOF
6246 OrderedSocketData data(reads, arraysize(reads),
6247 writes, arraysize(writes));
6248 NormalSpdyTransactionHelper helper(CreateGetRequest(),
6249 BoundNetLog(), GetParam(), NULL);
6251 helper.RunPreTestSetup();
6252 helper.AddData(&data);
6254 HttpNetworkTransaction* trans = helper.trans();
6256 // Start the transaction with basic parameters.
6257 TestCompletionCallback callback;
6258 int rv = trans->Start(
6259 &CreateGetRequest(), callback.callback(), BoundNetLog());
6260 EXPECT_EQ(ERR_IO_PENDING, rv);
6261 rv = callback.WaitForResult();
6262 EXPECT_EQ(OK, rv);
6264 // Verify that we consumed all test data.
6265 EXPECT_TRUE(data.at_read_eof()) << "Read count: "
6266 << data.read_count()
6267 << " Read index: "
6268 << data.read_index();
6269 EXPECT_TRUE(data.at_write_eof()) << "Write count: "
6270 << data.write_count()
6271 << " Write index: "
6272 << data.write_index();
6274 // Verify the SYN_REPLY.
6275 HttpResponseInfo response = *trans->GetResponseInfo();
6276 EXPECT_TRUE(response.headers != NULL);
6277 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
6280 TEST_P(SpdyNetworkTransactionSpdy3Test, OutOfOrderSynStream) {
6281 // This first request will start to establish the SpdySession.
6282 // Then we will start the second (MEDIUM priority) and then third
6283 // (HIGHEST priority) request in such a way that the third will actually
6284 // start before the second, causing the second to be numbered differently
6285 // than they order they were created.
6286 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6287 scoped_ptr<SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, HIGHEST));
6288 scoped_ptr<SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, MEDIUM));
6289 MockWrite writes[] = {
6290 CreateMockWrite(*req1, 0),
6291 CreateMockWrite(*req2, 3),
6292 CreateMockWrite(*req3, 4),
6295 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
6296 scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, true));
6297 scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
6298 scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(3, true));
6299 scoped_ptr<SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
6300 scoped_ptr<SpdyFrame> body3(ConstructSpdyBodyFrame(5, true));
6301 MockRead reads[] = {
6302 CreateMockRead(*resp1, 1),
6303 CreateMockRead(*body1, 2),
6304 CreateMockRead(*resp2, 5),
6305 CreateMockRead(*body2, 6),
6306 CreateMockRead(*resp3, 7),
6307 CreateMockRead(*body3, 8),
6308 MockRead(ASYNC, 0, 9) // EOF
6311 DeterministicSocketData data(reads, arraysize(reads),
6312 writes, arraysize(writes));
6313 NormalSpdyTransactionHelper helper(CreateGetRequest(),
6314 BoundNetLog(), GetParam(), NULL);
6315 helper.SetDeterministic();
6316 helper.RunPreTestSetup();
6317 helper.AddDeterministicData(&data);
6319 // Start the first transaction to set up the SpdySession
6320 HttpNetworkTransaction* trans = helper.trans();
6321 TestCompletionCallback callback;
6322 HttpRequestInfo info1 = CreateGetRequest();
6323 info1.priority = LOWEST;
6324 int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
6325 EXPECT_EQ(ERR_IO_PENDING, rv);
6327 // Run the message loop, but do not allow the write to complete.
6328 // This leaves the SpdySession with a write pending, which prevents
6329 // SpdySession from attempting subsequent writes until this write completes.
6330 MessageLoop::current()->RunUntilIdle();
6332 // Now, start both new transactions
6333 HttpRequestInfo info2 = CreateGetRequest();
6334 info2.priority = MEDIUM;
6335 TestCompletionCallback callback2;
6336 scoped_ptr<HttpNetworkTransaction> trans2(
6337 new HttpNetworkTransaction(helper.session()));
6338 rv = trans2->Start(&info2, callback2.callback(), BoundNetLog());
6339 EXPECT_EQ(ERR_IO_PENDING, rv);
6340 MessageLoop::current()->RunUntilIdle();
6342 HttpRequestInfo info3 = CreateGetRequest();
6343 info3.priority = HIGHEST;
6344 TestCompletionCallback callback3;
6345 scoped_ptr<HttpNetworkTransaction> trans3(
6346 new HttpNetworkTransaction(helper.session()));
6347 rv = trans3->Start(&info3, callback3.callback(), BoundNetLog());
6348 EXPECT_EQ(ERR_IO_PENDING, rv);
6349 MessageLoop::current()->RunUntilIdle();
6351 // We now have two SYN_STREAM frames queued up which will be
6352 // dequeued only once the first write completes, which we
6353 // now allow to happen.
6354 data.RunFor(2);
6355 EXPECT_EQ(OK, callback.WaitForResult());
6357 // And now we can allow everything else to run to completion.
6358 data.SetStop(10);
6359 data.Run();
6360 EXPECT_EQ(OK, callback2.WaitForResult());
6361 EXPECT_EQ(OK, callback3.WaitForResult());
6363 helper.VerifyDataConsumed();
6366 } // namespace net