chromeos: bluetooth: add BluetoothInputClient
[chromium-blink-merge.git] / net / spdy / spdy_network_transaction_unittest.cc
blob10b0ceba66c08aa387886f87293dd460cf7d9979
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 "net/base/auth.h"
13 #include "net/base/net_log_unittest.h"
14 #include "net/http/http_network_session_peer.h"
15 #include "net/http/http_transaction_unittest.h"
16 #include "net/socket/client_socket_pool_base.h"
17 #include "net/spdy/spdy_http_stream.h"
18 #include "net/spdy/spdy_http_utils.h"
19 #include "net/spdy/spdy_session.h"
20 #include "net/spdy/spdy_session_pool.h"
21 #include "net/spdy/spdy_test_util.h"
22 #include "net/url_request/url_request_test_util.h"
23 #include "testing/platform_test.h"
25 //-----------------------------------------------------------------------------
27 namespace net {
29 enum SpdyNetworkTransactionTestTypes {
30 SPDYNPN,
31 SPDYNOSSL,
32 SPDYSSL,
34 class SpdyNetworkTransactionTest
35 : public ::testing::TestWithParam<SpdyNetworkTransactionTestTypes> {
36 protected:
38 virtual void SetUp() {
39 // By default, all tests turn off compression.
40 EnableCompression(false);
41 google_get_request_initialized_ = false;
42 google_post_request_initialized_ = false;
43 google_chunked_post_request_initialized_ = false;
46 virtual void TearDown() {
47 // Empty the current queue.
48 MessageLoop::current()->RunAllPending();
51 struct TransactionHelperResult {
52 int rv;
53 std::string status_line;
54 std::string response_data;
55 HttpResponseInfo response_info;
58 void EnableCompression(bool enabled) {
59 spdy::SpdyFramer::set_enable_compression_default(enabled);
62 // A helper class that handles all the initial npn/ssl setup.
63 class NormalSpdyTransactionHelper {
64 public:
65 NormalSpdyTransactionHelper(const HttpRequestInfo& request,
66 const BoundNetLog& log,
67 SpdyNetworkTransactionTestTypes test_type)
68 : request_(request),
69 session_deps_(new SpdySessionDependencies()),
70 session_(SpdySessionDependencies::SpdyCreateSession(
71 session_deps_.get())),
72 log_(log),
73 test_type_(test_type),
74 deterministic_(false),
75 spdy_enabled_(true) {
76 switch (test_type_) {
77 case SPDYNOSSL:
78 case SPDYSSL:
79 port_ = 80;
80 break;
81 case SPDYNPN:
82 port_ = 443;
83 break;
84 default:
85 NOTREACHED();
89 ~NormalSpdyTransactionHelper() {
90 // Any test which doesn't close the socket by sending it an EOF will
91 // have a valid session left open, which leaks the entire session pool.
92 // This is just fine - in fact, some of our tests intentionally do this
93 // so that we can check consistency of the SpdySessionPool as the test
94 // finishes. If we had put an EOF on the socket, the SpdySession would
95 // have closed and we wouldn't be able to check the consistency.
97 // Forcefully close existing sessions here.
98 session()->spdy_session_pool()->CloseAllSessions();
101 void SetDeterministic() {
102 session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
103 session_deps_.get());
104 deterministic_ = true;
107 void SetSpdyDisabled() {
108 spdy_enabled_ = false;
111 void RunPreTestSetup() {
112 if (!session_deps_.get())
113 session_deps_.reset(new SpdySessionDependencies());
114 if (!session_.get())
115 session_ = SpdySessionDependencies::SpdyCreateSession(
116 session_deps_.get());
117 HttpStreamFactory::set_use_alternate_protocols(false);
118 HttpStreamFactory::set_force_spdy_over_ssl(false);
119 HttpStreamFactory::set_force_spdy_always(false);
121 std::vector<std::string> next_protos;
122 next_protos.push_back("http/1.1");
123 next_protos.push_back("spdy/2");
124 next_protos.push_back("spdy/2.1");
126 switch (test_type_) {
127 case SPDYNPN:
128 session_->http_server_properties()->SetAlternateProtocol(
129 HostPortPair("www.google.com", 80), 443,
130 NPN_SPDY_21);
131 HttpStreamFactory::set_use_alternate_protocols(true);
132 HttpStreamFactory::set_next_protos(next_protos);
133 break;
134 case SPDYNOSSL:
135 HttpStreamFactory::set_force_spdy_over_ssl(false);
136 HttpStreamFactory::set_force_spdy_always(true);
137 break;
138 case SPDYSSL:
139 HttpStreamFactory::set_force_spdy_over_ssl(true);
140 HttpStreamFactory::set_force_spdy_always(true);
141 break;
142 default:
143 NOTREACHED();
146 // We're now ready to use SSL-npn SPDY.
147 trans_.reset(new HttpNetworkTransaction(session_));
150 // Start the transaction, read some data, finish.
151 void RunDefaultTest() {
152 output_.rv = trans_->Start(&request_, callback.callback(), log_);
154 // We expect an IO Pending or some sort of error.
155 EXPECT_LT(output_.rv, 0);
156 if (output_.rv != ERR_IO_PENDING)
157 return;
159 output_.rv = callback.WaitForResult();
160 if (output_.rv != OK) {
161 session_->spdy_session_pool()->CloseCurrentSessions();
162 return;
165 // Verify responses.
166 const HttpResponseInfo* response = trans_->GetResponseInfo();
167 ASSERT_TRUE(response != NULL);
168 ASSERT_TRUE(response->headers != NULL);
169 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
170 EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
171 if (test_type_ == SPDYNPN && spdy_enabled_) {
172 EXPECT_TRUE(response->was_npn_negotiated);
173 } else {
174 EXPECT_TRUE(!response->was_npn_negotiated);
176 // If SPDY is not enabled, a HTTP request should not be diverted
177 // over a SSL session.
178 if (!spdy_enabled_) {
179 EXPECT_EQ(request_.url.SchemeIs("https"),
180 response->was_npn_negotiated);
182 EXPECT_EQ("192.0.2.33", response->socket_address.host());
183 EXPECT_EQ(0, response->socket_address.port());
184 output_.status_line = response->headers->GetStatusLine();
185 output_.response_info = *response; // Make a copy so we can verify.
186 output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
189 // Most tests will want to call this function. In particular, the MockReads
190 // should end with an empty read, and that read needs to be processed to
191 // ensure proper deletion of the spdy_session_pool.
192 void VerifyDataConsumed() {
193 for (DataVector::iterator it = data_vector_.begin();
194 it != data_vector_.end(); ++it) {
195 EXPECT_TRUE((*it)->at_read_eof()) << "Read count: "
196 << (*it)->read_count()
197 << " Read index: "
198 << (*it)->read_index();
199 EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
200 << (*it)->write_count()
201 << " Write index: "
202 << (*it)->write_index();
206 // Occasionally a test will expect to error out before certain reads are
207 // processed. In that case we want to explicitly ensure that the reads were
208 // not processed.
209 void VerifyDataNotConsumed() {
210 for (DataVector::iterator it = data_vector_.begin();
211 it != data_vector_.end(); ++it) {
212 EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: "
213 << (*it)->read_count()
214 << " Read index: "
215 << (*it)->read_index();
216 EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
217 << (*it)->write_count()
218 << " Write index: "
219 << (*it)->write_index();
223 void RunToCompletion(StaticSocketDataProvider* data) {
224 RunPreTestSetup();
225 AddData(data);
226 RunDefaultTest();
227 VerifyDataConsumed();
230 void AddData(StaticSocketDataProvider* data) {
231 DCHECK(!deterministic_);
232 data_vector_.push_back(data);
233 linked_ptr<SSLSocketDataProvider> ssl_(
234 new SSLSocketDataProvider(ASYNC, OK));
235 if (test_type_ == SPDYNPN) {
236 ssl_->SetNextProto(SSLClientSocket::kProtoSPDY21);
238 ssl_vector_.push_back(ssl_);
239 if (test_type_ == SPDYNPN || test_type_ == SPDYSSL)
240 session_deps_->socket_factory->AddSSLSocketDataProvider(ssl_.get());
241 session_deps_->socket_factory->AddSocketDataProvider(data);
242 if (test_type_ == SPDYNPN) {
243 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
244 linked_ptr<StaticSocketDataProvider>
245 hanging_non_alternate_protocol_socket(
246 new StaticSocketDataProvider(NULL, 0, NULL, 0));
247 hanging_non_alternate_protocol_socket->set_connect_data(
248 never_finishing_connect);
249 session_deps_->socket_factory->AddSocketDataProvider(
250 hanging_non_alternate_protocol_socket.get());
251 alternate_vector_.push_back(hanging_non_alternate_protocol_socket);
255 void AddDeterministicData(DeterministicSocketData* data) {
256 DCHECK(deterministic_);
257 data_vector_.push_back(data);
258 linked_ptr<SSLSocketDataProvider> ssl_(
259 new SSLSocketDataProvider(ASYNC, OK));
260 if (test_type_ == SPDYNPN) {
261 ssl_->SetNextProto(SSLClientSocket::kProtoSPDY21);
263 ssl_vector_.push_back(ssl_);
264 if (test_type_ == SPDYNPN || test_type_ == SPDYSSL) {
265 session_deps_->deterministic_socket_factory->
266 AddSSLSocketDataProvider(ssl_.get());
268 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
269 if (test_type_ == SPDYNPN) {
270 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
271 scoped_refptr<DeterministicSocketData>
272 hanging_non_alternate_protocol_socket(
273 new DeterministicSocketData(NULL, 0, NULL, 0));
274 hanging_non_alternate_protocol_socket->set_connect_data(
275 never_finishing_connect);
276 session_deps_->deterministic_socket_factory->AddSocketDataProvider(
277 hanging_non_alternate_protocol_socket);
278 alternate_deterministic_vector_.push_back(
279 hanging_non_alternate_protocol_socket);
283 // This can only be called after RunPreTestSetup. It adds a Data Provider,
284 // but not a corresponding SSL data provider
285 void AddDataNoSSL(StaticSocketDataProvider* data) {
286 DCHECK(!deterministic_);
287 session_deps_->socket_factory->AddSocketDataProvider(data);
289 void AddDataNoSSL(DeterministicSocketData* data) {
290 DCHECK(deterministic_);
291 session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
294 void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
295 session_ = session;
297 HttpNetworkTransaction* trans() { return trans_.get(); }
298 void ResetTrans() { trans_.reset(); }
299 TransactionHelperResult& output() { return output_; }
300 const HttpRequestInfo& request() const { return request_; }
301 const scoped_refptr<HttpNetworkSession>& session() const {
302 return session_;
304 scoped_ptr<SpdySessionDependencies>& session_deps() {
305 return session_deps_;
307 int port() const { return port_; }
308 SpdyNetworkTransactionTestTypes test_type() const { return test_type_; }
310 private:
311 typedef std::vector<StaticSocketDataProvider*> DataVector;
312 typedef std::vector<linked_ptr<SSLSocketDataProvider> > SSLVector;
313 typedef std::vector<linked_ptr<StaticSocketDataProvider> > AlternateVector;
314 typedef std::vector<scoped_refptr<DeterministicSocketData> >
315 AlternateDeterministicVector;
316 HttpRequestInfo request_;
317 scoped_ptr<SpdySessionDependencies> session_deps_;
318 scoped_refptr<HttpNetworkSession> session_;
319 TransactionHelperResult output_;
320 scoped_ptr<StaticSocketDataProvider> first_transaction_;
321 SSLVector ssl_vector_;
322 TestCompletionCallback callback;
323 scoped_ptr<HttpNetworkTransaction> trans_;
324 scoped_ptr<HttpNetworkTransaction> trans_http_;
325 DataVector data_vector_;
326 AlternateVector alternate_vector_;
327 AlternateDeterministicVector alternate_deterministic_vector_;
328 const BoundNetLog& log_;
329 SpdyNetworkTransactionTestTypes test_type_;
330 int port_;
331 bool deterministic_;
332 bool spdy_enabled_;
335 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
336 int expected_status);
338 void ConnectStatusHelper(const MockRead& status);
340 const HttpRequestInfo& CreateGetPushRequest() {
341 google_get_push_request_.method = "GET";
342 google_get_push_request_.url = GURL("http://www.google.com/foo.dat");
343 google_get_push_request_.load_flags = 0;
344 return google_get_push_request_;
347 const HttpRequestInfo& CreateGetRequest() {
348 if (!google_get_request_initialized_) {
349 google_get_request_.method = "GET";
350 google_get_request_.url = GURL(kDefaultURL);
351 google_get_request_.load_flags = 0;
352 google_get_request_initialized_ = true;
354 return google_get_request_;
357 const HttpRequestInfo& CreateGetRequestWithUserAgent() {
358 if (!google_get_request_initialized_) {
359 google_get_request_.method = "GET";
360 google_get_request_.url = GURL(kDefaultURL);
361 google_get_request_.load_flags = 0;
362 google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
363 google_get_request_initialized_ = true;
365 return google_get_request_;
368 const HttpRequestInfo& CreatePostRequest() {
369 if (!google_post_request_initialized_) {
370 google_post_request_.method = "POST";
371 google_post_request_.url = GURL(kDefaultURL);
372 google_post_request_.upload_data = new UploadData();
373 google_post_request_.upload_data->AppendBytes(kUploadData,
374 kUploadDataSize);
375 google_post_request_initialized_ = true;
377 return google_post_request_;
380 const HttpRequestInfo& CreateChunkedPostRequest() {
381 if (!google_chunked_post_request_initialized_) {
382 google_chunked_post_request_.method = "POST";
383 google_chunked_post_request_.url = GURL(kDefaultURL);
384 google_chunked_post_request_.upload_data = new UploadData();
385 google_chunked_post_request_.upload_data->set_is_chunked(true);
386 google_chunked_post_request_.upload_data->AppendChunk(
387 kUploadData, kUploadDataSize, false);
388 google_chunked_post_request_.upload_data->AppendChunk(
389 kUploadData, kUploadDataSize, true);
390 google_chunked_post_request_initialized_ = true;
392 return google_chunked_post_request_;
395 // Read the result of a particular transaction, knowing that we've got
396 // multiple transactions in the read pipeline; so as we read, we may have
397 // to skip over data destined for other transactions while we consume
398 // the data for |trans|.
399 int ReadResult(HttpNetworkTransaction* trans,
400 StaticSocketDataProvider* data,
401 std::string* result) {
402 const int kSize = 3000;
404 int bytes_read = 0;
405 scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
406 TestCompletionCallback callback;
407 while (true) {
408 int rv = trans->Read(buf, kSize, callback.callback());
409 if (rv == ERR_IO_PENDING) {
410 // Multiple transactions may be in the data set. Keep pulling off
411 // reads until we complete our callback.
412 while (!callback.have_result()) {
413 data->CompleteRead();
414 MessageLoop::current()->RunAllPending();
416 rv = callback.WaitForResult();
417 } else if (rv <= 0) {
418 break;
420 result->append(buf->data(), rv);
421 bytes_read += rv;
423 return bytes_read;
426 void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
427 // This lengthy block is reaching into the pool to dig out the active
428 // session. Once we have the session, we verify that the streams are
429 // all closed and not leaked at this point.
430 const GURL& url = helper.request().url;
431 int port = helper.test_type() == SPDYNPN ? 443 : 80;
432 HostPortPair host_port_pair(url.host(), port);
433 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
434 BoundNetLog log;
435 const scoped_refptr<HttpNetworkSession>& session = helper.session();
436 SpdySessionPool* pool(session->spdy_session_pool());
437 EXPECT_TRUE(pool->HasSession(pair));
438 scoped_refptr<SpdySession> spdy_session(pool->Get(pair, log));
439 ASSERT_TRUE(spdy_session.get() != NULL);
440 EXPECT_EQ(0u, spdy_session->num_active_streams());
441 EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
444 void RunServerPushTest(OrderedSocketData* data,
445 HttpResponseInfo* response,
446 HttpResponseInfo* push_response,
447 std::string& expected) {
448 NormalSpdyTransactionHelper helper(CreateGetRequest(),
449 BoundNetLog(), GetParam());
450 helper.RunPreTestSetup();
451 helper.AddData(data);
453 HttpNetworkTransaction* trans = helper.trans();
455 // Start the transaction with basic parameters.
456 TestCompletionCallback callback;
457 int rv = trans->Start(
458 &CreateGetRequest(), callback.callback(), BoundNetLog());
459 EXPECT_EQ(ERR_IO_PENDING, rv);
460 rv = callback.WaitForResult();
462 // Request the pushed path.
463 scoped_ptr<HttpNetworkTransaction> trans2(
464 new HttpNetworkTransaction(helper.session()));
465 rv = trans2->Start(
466 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
467 EXPECT_EQ(ERR_IO_PENDING, rv);
468 MessageLoop::current()->RunAllPending();
470 // The data for the pushed path may be coming in more than 1 packet. Compile
471 // the results into a single string.
473 // Read the server push body.
474 std::string result2;
475 ReadResult(trans2.get(), data, &result2);
476 // Read the response body.
477 std::string result;
478 ReadResult(trans, data, &result);
480 // Verify that we consumed all test data.
481 EXPECT_TRUE(data->at_read_eof());
482 EXPECT_TRUE(data->at_write_eof());
484 // Verify that the received push data is same as the expected push data.
485 EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
486 << result2
487 << "||||| Expected data: "
488 << expected;
490 // Verify the SYN_REPLY.
491 // Copy the response info, because trans goes away.
492 *response = *trans->GetResponseInfo();
493 *push_response = *trans2->GetResponseInfo();
495 VerifyStreamsClosed(helper);
498 static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
499 int result) {
500 helper->ResetTrans();
503 static void StartTransactionCallback(
504 const scoped_refptr<HttpNetworkSession>& session,
505 int result) {
506 scoped_ptr<HttpNetworkTransaction> trans(
507 new HttpNetworkTransaction(session));
508 TestCompletionCallback callback;
509 HttpRequestInfo request;
510 request.method = "GET";
511 request.url = GURL("http://www.google.com/");
512 request.load_flags = 0;
513 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
514 EXPECT_EQ(ERR_IO_PENDING, rv);
515 callback.WaitForResult();
518 private:
519 bool google_get_request_initialized_;
520 bool google_post_request_initialized_;
521 bool google_chunked_post_request_initialized_;
522 HttpRequestInfo google_get_request_;
523 HttpRequestInfo google_post_request_;
524 HttpRequestInfo google_chunked_post_request_;
525 HttpRequestInfo google_get_push_request_;
528 //-----------------------------------------------------------------------------
529 // All tests are run with three different connection types: SPDY after NPN
530 // negotiation, SPDY without SSL, and SPDY with SSL.
531 INSTANTIATE_TEST_CASE_P(Spdy,
532 SpdyNetworkTransactionTest,
533 ::testing::Values(SPDYNOSSL, SPDYSSL, SPDYNPN));
536 // Verify HttpNetworkTransaction constructor.
537 TEST_P(SpdyNetworkTransactionTest, Constructor) {
538 SpdySessionDependencies session_deps;
539 scoped_refptr<HttpNetworkSession> session(
540 SpdySessionDependencies::SpdyCreateSession(&session_deps));
541 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
544 TEST_P(SpdyNetworkTransactionTest, Get) {
545 // Construct the request.
546 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
547 MockWrite writes[] = { CreateMockWrite(*req) };
549 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
550 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
551 MockRead reads[] = {
552 CreateMockRead(*resp),
553 CreateMockRead(*body),
554 MockRead(ASYNC, 0, 0) // EOF
557 scoped_ptr<DelayedSocketData> data(
558 new DelayedSocketData(1, reads, arraysize(reads),
559 writes, arraysize(writes)));
560 NormalSpdyTransactionHelper helper(CreateGetRequest(),
561 BoundNetLog(), GetParam());
562 helper.RunToCompletion(data.get());
563 TransactionHelperResult out = helper.output();
564 EXPECT_EQ(OK, out.rv);
565 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
566 EXPECT_EQ("hello!", out.response_data);
569 TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
570 for (RequestPriority p = HIGHEST; p < NUM_PRIORITIES;
571 p = RequestPriority(p+1)) {
572 // Construct the request.
573 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, p));
574 MockWrite writes[] = { CreateMockWrite(*req) };
576 const int spdy_prio = reinterpret_cast<spdy::SpdySynStreamControlFrame*>(
577 req.get())->priority();
578 // this repeats the RequestPriority-->SpdyPriority mapping from
579 // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
580 // sure it's being done right.
581 switch(p) {
582 case HIGHEST:
583 EXPECT_EQ(0, spdy_prio);
584 break;
585 case MEDIUM:
586 EXPECT_EQ(1, spdy_prio);
587 break;
588 case LOW:
589 case LOWEST:
590 EXPECT_EQ(2, spdy_prio);
591 break;
592 case IDLE:
593 EXPECT_EQ(3, spdy_prio);
594 break;
595 default:
596 FAIL();
599 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
600 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
601 MockRead reads[] = {
602 CreateMockRead(*resp),
603 CreateMockRead(*body),
604 MockRead(ASYNC, 0, 0) // EOF
607 scoped_ptr<DelayedSocketData> data(
608 new DelayedSocketData(1, reads, arraysize(reads),
609 writes, arraysize(writes)));
610 HttpRequestInfo http_req = CreateGetRequest();
611 http_req.priority = p;
613 NormalSpdyTransactionHelper helper(http_req, BoundNetLog(), GetParam());
614 helper.RunToCompletion(data.get());
615 TransactionHelperResult out = helper.output();
616 EXPECT_EQ(OK, out.rv);
617 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
618 EXPECT_EQ("hello!", out.response_data);
622 // Start three gets simultaniously; making sure that multiplexed
623 // streams work properly.
625 // This can't use the TransactionHelper method, since it only
626 // handles a single transaction, and finishes them as soon
627 // as it launches them.
629 // TODO(gavinp): create a working generalized TransactionHelper that
630 // can allow multiple streams in flight.
632 TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
633 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
634 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
635 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
636 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
638 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
639 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
640 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
641 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
643 scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
644 scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
645 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(5, false));
646 scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(5, true));
648 MockWrite writes[] = {
649 CreateMockWrite(*req),
650 CreateMockWrite(*req2),
651 CreateMockWrite(*req3),
653 MockRead reads[] = {
654 CreateMockRead(*resp, 1),
655 CreateMockRead(*body),
656 CreateMockRead(*resp2, 4),
657 CreateMockRead(*body2),
658 CreateMockRead(*resp3, 7),
659 CreateMockRead(*body3),
661 CreateMockRead(*fbody),
662 CreateMockRead(*fbody2),
663 CreateMockRead(*fbody3),
665 MockRead(ASYNC, 0, 0), // EOF
667 scoped_ptr<OrderedSocketData> data(
668 new OrderedSocketData(reads, arraysize(reads),
669 writes, arraysize(writes)));
670 scoped_ptr<OrderedSocketData> data_placeholder(
671 new OrderedSocketData(NULL, 0, NULL, 0));
673 BoundNetLog log;
674 TransactionHelperResult out;
675 NormalSpdyTransactionHelper helper(CreateGetRequest(),
676 BoundNetLog(), GetParam());
677 helper.RunPreTestSetup();
678 helper.AddData(data.get());
679 // We require placeholder data because three get requests are sent out, so
680 // there needs to be three sets of SSL connection data.
681 helper.AddData(data_placeholder.get());
682 helper.AddData(data_placeholder.get());
683 scoped_ptr<HttpNetworkTransaction> trans1(
684 new HttpNetworkTransaction(helper.session()));
685 scoped_ptr<HttpNetworkTransaction> trans2(
686 new HttpNetworkTransaction(helper.session()));
687 scoped_ptr<HttpNetworkTransaction> trans3(
688 new HttpNetworkTransaction(helper.session()));
690 TestCompletionCallback callback1;
691 TestCompletionCallback callback2;
692 TestCompletionCallback callback3;
694 HttpRequestInfo httpreq1 = CreateGetRequest();
695 HttpRequestInfo httpreq2 = CreateGetRequest();
696 HttpRequestInfo httpreq3 = CreateGetRequest();
698 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
699 ASSERT_EQ(ERR_IO_PENDING, out.rv);
700 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
701 ASSERT_EQ(ERR_IO_PENDING, out.rv);
702 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
703 ASSERT_EQ(ERR_IO_PENDING, out.rv);
705 out.rv = callback1.WaitForResult();
706 ASSERT_EQ(OK, out.rv);
707 out.rv = callback3.WaitForResult();
708 ASSERT_EQ(OK, out.rv);
710 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
711 EXPECT_TRUE(response1->headers != NULL);
712 EXPECT_TRUE(response1->was_fetched_via_spdy);
713 out.status_line = response1->headers->GetStatusLine();
714 out.response_info = *response1;
716 trans2->GetResponseInfo();
718 out.rv = ReadTransaction(trans1.get(), &out.response_data);
719 helper.VerifyDataConsumed();
720 EXPECT_EQ(OK, out.rv);
722 EXPECT_EQ(OK, out.rv);
723 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
724 EXPECT_EQ("hello!hello!", out.response_data);
727 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
728 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
729 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
730 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
731 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
733 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
734 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
735 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
736 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
738 MockWrite writes[] = {
739 CreateMockWrite(*req),
740 CreateMockWrite(*req2),
742 MockRead reads[] = {
743 CreateMockRead(*resp, 1),
744 CreateMockRead(*body),
745 CreateMockRead(*resp2, 4),
746 CreateMockRead(*body2),
747 CreateMockRead(*fbody),
748 CreateMockRead(*fbody2),
749 MockRead(ASYNC, 0, 0), // EOF
751 scoped_ptr<OrderedSocketData> data(
752 new OrderedSocketData(reads, arraysize(reads),
753 writes, arraysize(writes)));
755 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
757 scoped_ptr<OrderedSocketData> data_placeholder(
758 new OrderedSocketData(NULL, 0, NULL, 0));
759 data_placeholder->set_connect_data(never_finishing_connect);
761 BoundNetLog log;
762 TransactionHelperResult out;
763 NormalSpdyTransactionHelper helper(CreateGetRequest(),
764 BoundNetLog(), GetParam());
765 helper.RunPreTestSetup();
766 helper.AddData(data.get());
767 // We require placeholder data because two get requests are sent out, so
768 // there needs to be two sets of SSL connection data.
769 helper.AddData(data_placeholder.get());
770 scoped_ptr<HttpNetworkTransaction> trans1(
771 new HttpNetworkTransaction(helper.session()));
772 scoped_ptr<HttpNetworkTransaction> trans2(
773 new HttpNetworkTransaction(helper.session()));
775 TestCompletionCallback callback1;
776 TestCompletionCallback callback2;
778 HttpRequestInfo httpreq1 = CreateGetRequest();
779 HttpRequestInfo httpreq2 = CreateGetRequest();
781 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
782 ASSERT_EQ(ERR_IO_PENDING, out.rv);
783 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
784 ASSERT_EQ(ERR_IO_PENDING, out.rv);
786 out.rv = callback1.WaitForResult();
787 ASSERT_EQ(OK, out.rv);
788 out.rv = callback2.WaitForResult();
789 ASSERT_EQ(OK, out.rv);
791 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
792 EXPECT_TRUE(response1->headers != NULL);
793 EXPECT_TRUE(response1->was_fetched_via_spdy);
794 out.status_line = response1->headers->GetStatusLine();
795 out.response_info = *response1;
796 out.rv = ReadTransaction(trans1.get(), &out.response_data);
797 EXPECT_EQ(OK, out.rv);
798 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
799 EXPECT_EQ("hello!hello!", out.response_data);
801 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
802 EXPECT_TRUE(response2->headers != NULL);
803 EXPECT_TRUE(response2->was_fetched_via_spdy);
804 out.status_line = response2->headers->GetStatusLine();
805 out.response_info = *response2;
806 out.rv = ReadTransaction(trans2.get(), &out.response_data);
807 EXPECT_EQ(OK, out.rv);
808 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
809 EXPECT_EQ("hello!hello!", out.response_data);
811 helper.VerifyDataConsumed();
814 TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
815 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
816 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
817 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
818 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
820 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
821 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
822 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
823 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
825 MockWrite writes[] = {
826 CreateMockWrite(*req),
827 CreateMockWrite(*req2),
829 MockRead reads[] = {
830 CreateMockRead(*resp, 1),
831 CreateMockRead(*body),
832 CreateMockRead(*resp2, 4),
833 CreateMockRead(*body2),
834 CreateMockRead(*fbody),
835 CreateMockRead(*fbody2),
836 MockRead(ASYNC, 0, 0), // EOF
838 scoped_ptr<OrderedSocketData> preconnect_data(
839 new OrderedSocketData(reads, arraysize(reads),
840 writes, arraysize(writes)));
842 MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
844 scoped_ptr<OrderedSocketData> data_placeholder(
845 new OrderedSocketData(NULL, 0, NULL, 0));
846 data_placeholder->set_connect_data(never_finishing_connect);
848 BoundNetLog log;
849 TransactionHelperResult out;
850 NormalSpdyTransactionHelper helper(CreateGetRequest(),
851 BoundNetLog(), GetParam());
852 helper.RunPreTestSetup();
853 helper.AddData(preconnect_data.get());
854 // We require placeholder data because 3 connections are attempted (first is
855 // the preconnect, 2nd and 3rd are the never finished connections.
856 helper.AddData(data_placeholder.get());
857 helper.AddData(data_placeholder.get());
859 scoped_ptr<HttpNetworkTransaction> trans1(
860 new HttpNetworkTransaction(helper.session()));
861 scoped_ptr<HttpNetworkTransaction> trans2(
862 new HttpNetworkTransaction(helper.session()));
864 TestCompletionCallback callback1;
865 TestCompletionCallback callback2;
867 HttpRequestInfo httpreq = CreateGetRequest();
869 // Preconnect the first.
870 SSLConfig preconnect_ssl_config;
871 helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
872 HttpStreamFactory* http_stream_factory =
873 helper.session()->http_stream_factory();
874 if (http_stream_factory->has_next_protos()) {
875 preconnect_ssl_config.next_protos = http_stream_factory->next_protos();
878 http_stream_factory->PreconnectStreams(
879 1, httpreq, preconnect_ssl_config, preconnect_ssl_config);
881 out.rv = trans1->Start(&httpreq, callback1.callback(), log);
882 ASSERT_EQ(ERR_IO_PENDING, out.rv);
883 out.rv = trans2->Start(&httpreq, callback2.callback(), log);
884 ASSERT_EQ(ERR_IO_PENDING, out.rv);
886 out.rv = callback1.WaitForResult();
887 ASSERT_EQ(OK, out.rv);
888 out.rv = callback2.WaitForResult();
889 ASSERT_EQ(OK, out.rv);
891 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
892 EXPECT_TRUE(response1->headers != NULL);
893 EXPECT_TRUE(response1->was_fetched_via_spdy);
894 out.status_line = response1->headers->GetStatusLine();
895 out.response_info = *response1;
896 out.rv = ReadTransaction(trans1.get(), &out.response_data);
897 EXPECT_EQ(OK, out.rv);
898 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
899 EXPECT_EQ("hello!hello!", out.response_data);
901 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
902 EXPECT_TRUE(response2->headers != NULL);
903 EXPECT_TRUE(response2->was_fetched_via_spdy);
904 out.status_line = response2->headers->GetStatusLine();
905 out.response_info = *response2;
906 out.rv = ReadTransaction(trans2.get(), &out.response_data);
907 EXPECT_EQ(OK, out.rv);
908 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
909 EXPECT_EQ("hello!hello!", out.response_data);
911 helper.VerifyDataConsumed();
914 // Similar to ThreeGets above, however this test adds a SETTINGS
915 // frame. The SETTINGS frame is read during the IO loop waiting on
916 // the first transaction completion, and sets a maximum concurrent
917 // stream limit of 1. This means that our IO loop exists after the
918 // second transaction completes, so we can assert on read_index().
919 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
920 // Construct the request.
921 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
922 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
923 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
924 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
926 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
927 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
928 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
929 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
931 scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 5, LOWEST));
932 scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5));
933 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(5, false));
934 scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(5, true));
936 spdy::SpdySettings settings;
937 spdy::SettingsFlagsAndId id(0);
938 id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
939 const size_t max_concurrent_streams = 1;
941 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
942 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
944 MockWrite writes[] = {
945 CreateMockWrite(*req),
946 CreateMockWrite(*req2),
947 CreateMockWrite(*req3),
950 MockRead reads[] = {
951 CreateMockRead(*settings_frame, 1),
952 CreateMockRead(*resp),
953 CreateMockRead(*body),
954 CreateMockRead(*fbody),
955 CreateMockRead(*resp2, 7),
956 CreateMockRead(*body2),
957 CreateMockRead(*fbody2),
958 CreateMockRead(*resp3, 12),
959 CreateMockRead(*body3),
960 CreateMockRead(*fbody3),
962 MockRead(ASYNC, 0, 0), // EOF
965 scoped_ptr<OrderedSocketData> data(
966 new OrderedSocketData(reads, arraysize(reads),
967 writes, arraysize(writes)));
968 scoped_ptr<OrderedSocketData> data_placeholder(
969 new OrderedSocketData(NULL, 0, NULL, 0));
971 BoundNetLog log;
972 TransactionHelperResult out;
974 NormalSpdyTransactionHelper helper(CreateGetRequest(),
975 BoundNetLog(), GetParam());
976 helper.RunPreTestSetup();
977 helper.AddData(data.get());
978 // We require placeholder data because three get requests are sent out, so
979 // there needs to be three sets of SSL connection data.
980 helper.AddData(data_placeholder.get());
981 helper.AddData(data_placeholder.get());
982 scoped_ptr<HttpNetworkTransaction> trans1(
983 new HttpNetworkTransaction(helper.session()));
984 scoped_ptr<HttpNetworkTransaction> trans2(
985 new HttpNetworkTransaction(helper.session()));
986 scoped_ptr<HttpNetworkTransaction> trans3(
987 new HttpNetworkTransaction(helper.session()));
989 TestCompletionCallback callback1;
990 TestCompletionCallback callback2;
991 TestCompletionCallback callback3;
993 HttpRequestInfo httpreq1 = CreateGetRequest();
994 HttpRequestInfo httpreq2 = CreateGetRequest();
995 HttpRequestInfo httpreq3 = CreateGetRequest();
997 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
998 ASSERT_EQ(out.rv, ERR_IO_PENDING);
999 // run transaction 1 through quickly to force a read of our SETTINGS
1000 // frame
1001 out.rv = callback1.WaitForResult();
1002 ASSERT_EQ(OK, out.rv);
1004 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1005 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1006 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1007 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1008 out.rv = callback2.WaitForResult();
1009 ASSERT_EQ(OK, out.rv);
1010 EXPECT_EQ(7U, data->read_index()); // i.e. the third trans was queued
1012 out.rv = callback3.WaitForResult();
1013 ASSERT_EQ(OK, out.rv);
1015 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1016 ASSERT_TRUE(response1 != NULL);
1017 EXPECT_TRUE(response1->headers != NULL);
1018 EXPECT_TRUE(response1->was_fetched_via_spdy);
1019 out.status_line = response1->headers->GetStatusLine();
1020 out.response_info = *response1;
1021 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1022 EXPECT_EQ(OK, out.rv);
1023 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1024 EXPECT_EQ("hello!hello!", out.response_data);
1026 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1027 out.status_line = response2->headers->GetStatusLine();
1028 out.response_info = *response2;
1029 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1030 EXPECT_EQ(OK, out.rv);
1031 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1032 EXPECT_EQ("hello!hello!", out.response_data);
1034 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1035 out.status_line = response3->headers->GetStatusLine();
1036 out.response_info = *response3;
1037 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1038 EXPECT_EQ(OK, out.rv);
1039 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1040 EXPECT_EQ("hello!hello!", out.response_data);
1042 helper.VerifyDataConsumed();
1044 EXPECT_EQ(OK, out.rv);
1047 // Similar to ThreeGetsWithMaxConcurrent above, however this test adds
1048 // a fourth transaction. The third and fourth transactions have
1049 // different data ("hello!" vs "hello!hello!") and because of the
1050 // user specified priority, we expect to see them inverted in
1051 // the response from the server.
1052 TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
1053 // Construct the request.
1054 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1055 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1056 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
1057 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
1059 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
1060 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
1061 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
1062 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
1064 scoped_ptr<spdy::SpdyFrame> req4(
1065 ConstructSpdyGet(NULL, 0, false, 5, HIGHEST));
1066 scoped_ptr<spdy::SpdyFrame> resp4(ConstructSpdyGetSynReply(NULL, 0, 5));
1067 scoped_ptr<spdy::SpdyFrame> fbody4(ConstructSpdyBodyFrame(5, true));
1069 scoped_ptr<spdy::SpdyFrame> req3(ConstructSpdyGet(NULL, 0, false, 7, LOWEST));
1070 scoped_ptr<spdy::SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 7));
1071 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(7, false));
1072 scoped_ptr<spdy::SpdyFrame> fbody3(ConstructSpdyBodyFrame(7, true));
1075 spdy::SpdySettings settings;
1076 spdy::SettingsFlagsAndId id(0);
1077 id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
1078 const size_t max_concurrent_streams = 1;
1080 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
1081 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
1083 MockWrite writes[] = { CreateMockWrite(*req),
1084 CreateMockWrite(*req2),
1085 CreateMockWrite(*req4),
1086 CreateMockWrite(*req3),
1088 MockRead reads[] = {
1089 CreateMockRead(*settings_frame, 1),
1090 CreateMockRead(*resp),
1091 CreateMockRead(*body),
1092 CreateMockRead(*fbody),
1093 CreateMockRead(*resp2, 7),
1094 CreateMockRead(*body2),
1095 CreateMockRead(*fbody2),
1096 CreateMockRead(*resp4, 13),
1097 CreateMockRead(*fbody4),
1098 CreateMockRead(*resp3, 16),
1099 CreateMockRead(*body3),
1100 CreateMockRead(*fbody3),
1102 MockRead(ASYNC, 0, 0), // EOF
1105 scoped_ptr<OrderedSocketData> data(
1106 new OrderedSocketData(reads, arraysize(reads),
1107 writes, arraysize(writes)));
1108 scoped_ptr<OrderedSocketData> data_placeholder(
1109 new OrderedSocketData(NULL, 0, NULL, 0));
1111 BoundNetLog log;
1112 TransactionHelperResult out;
1113 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1114 BoundNetLog(), GetParam());
1115 helper.RunPreTestSetup();
1116 helper.AddData(data.get());
1117 // We require placeholder data because four get requests are sent out, so
1118 // there needs to be four sets of SSL connection data.
1119 helper.AddData(data_placeholder.get());
1120 helper.AddData(data_placeholder.get());
1121 helper.AddData(data_placeholder.get());
1122 scoped_ptr<HttpNetworkTransaction> trans1(
1123 new HttpNetworkTransaction(helper.session()));
1124 scoped_ptr<HttpNetworkTransaction> trans2(
1125 new HttpNetworkTransaction(helper.session()));
1126 scoped_ptr<HttpNetworkTransaction> trans3(
1127 new HttpNetworkTransaction(helper.session()));
1128 scoped_ptr<HttpNetworkTransaction> trans4(
1129 new HttpNetworkTransaction(helper.session()));
1131 TestCompletionCallback callback1;
1132 TestCompletionCallback callback2;
1133 TestCompletionCallback callback3;
1134 TestCompletionCallback callback4;
1136 HttpRequestInfo httpreq1 = CreateGetRequest();
1137 HttpRequestInfo httpreq2 = CreateGetRequest();
1138 HttpRequestInfo httpreq3 = CreateGetRequest();
1139 HttpRequestInfo httpreq4 = CreateGetRequest();
1140 httpreq4.priority = HIGHEST;
1142 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1143 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1144 // run transaction 1 through quickly to force a read of our SETTINGS
1145 // frame
1146 out.rv = callback1.WaitForResult();
1147 ASSERT_EQ(OK, out.rv);
1149 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1150 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1151 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1152 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1153 out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
1154 ASSERT_EQ(ERR_IO_PENDING, out.rv);
1156 out.rv = callback2.WaitForResult();
1157 ASSERT_EQ(OK, out.rv);
1158 EXPECT_EQ(data->read_index(), 7U); // i.e. the third & fourth trans queued
1160 out.rv = callback3.WaitForResult();
1161 ASSERT_EQ(OK, out.rv);
1163 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1164 EXPECT_TRUE(response1->headers != NULL);
1165 EXPECT_TRUE(response1->was_fetched_via_spdy);
1166 out.status_line = response1->headers->GetStatusLine();
1167 out.response_info = *response1;
1168 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1169 EXPECT_EQ(OK, out.rv);
1170 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1171 EXPECT_EQ("hello!hello!", out.response_data);
1173 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1174 out.status_line = response2->headers->GetStatusLine();
1175 out.response_info = *response2;
1176 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1177 EXPECT_EQ(OK, out.rv);
1178 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1179 EXPECT_EQ("hello!hello!", out.response_data);
1181 // notice: response3 gets two hellos, response4 gets one
1182 // hello, so we know dequeuing priority was respected.
1183 const HttpResponseInfo* response3 = trans3->GetResponseInfo();
1184 out.status_line = response3->headers->GetStatusLine();
1185 out.response_info = *response3;
1186 out.rv = ReadTransaction(trans3.get(), &out.response_data);
1187 EXPECT_EQ(OK, out.rv);
1188 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1189 EXPECT_EQ("hello!hello!", out.response_data);
1191 out.rv = callback4.WaitForResult();
1192 EXPECT_EQ(OK, out.rv);
1193 const HttpResponseInfo* response4 = trans4->GetResponseInfo();
1194 out.status_line = response4->headers->GetStatusLine();
1195 out.response_info = *response4;
1196 out.rv = ReadTransaction(trans4.get(), &out.response_data);
1197 EXPECT_EQ(OK, out.rv);
1198 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1199 EXPECT_EQ("hello!", out.response_data);
1200 helper.VerifyDataConsumed();
1201 EXPECT_EQ(OK, out.rv);
1204 // Similar to ThreeGetsMaxConcurrrent above, however, this test
1205 // deletes a session in the middle of the transaction to insure
1206 // that we properly remove pendingcreatestream objects from
1207 // the spdy_session
1208 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
1209 // Construct the request.
1210 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1211 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1212 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
1213 scoped_ptr<spdy::SpdyFrame> fbody(ConstructSpdyBodyFrame(1, true));
1215 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
1216 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
1217 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(3, false));
1218 scoped_ptr<spdy::SpdyFrame> fbody2(ConstructSpdyBodyFrame(3, true));
1220 spdy::SpdySettings settings;
1221 spdy::SettingsFlagsAndId id(0);
1222 id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
1223 const size_t max_concurrent_streams = 1;
1225 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
1226 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
1228 MockWrite writes[] = { CreateMockWrite(*req),
1229 CreateMockWrite(*req2),
1231 MockRead reads[] = {
1232 CreateMockRead(*settings_frame, 1),
1233 CreateMockRead(*resp),
1234 CreateMockRead(*body),
1235 CreateMockRead(*fbody),
1236 CreateMockRead(*resp2, 7),
1237 CreateMockRead(*body2),
1238 CreateMockRead(*fbody2),
1239 MockRead(ASYNC, 0, 0), // EOF
1242 scoped_ptr<OrderedSocketData> data(
1243 new OrderedSocketData(reads, arraysize(reads),
1244 writes, arraysize(writes)));
1245 scoped_ptr<OrderedSocketData> data_placeholder(
1246 new OrderedSocketData(NULL, 0, NULL, 0));
1248 BoundNetLog log;
1249 TransactionHelperResult out;
1250 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1251 BoundNetLog(), GetParam());
1252 helper.RunPreTestSetup();
1253 helper.AddData(data.get());
1254 // We require placeholder data because three get requests are sent out, so
1255 // there needs to be three sets of SSL connection data.
1256 helper.AddData(data_placeholder.get());
1257 helper.AddData(data_placeholder.get());
1258 scoped_ptr<HttpNetworkTransaction> trans1(
1259 new HttpNetworkTransaction(helper.session()));
1260 scoped_ptr<HttpNetworkTransaction> trans2(
1261 new HttpNetworkTransaction(helper.session()));
1262 scoped_ptr<HttpNetworkTransaction> trans3(
1263 new HttpNetworkTransaction(helper.session()));
1265 TestCompletionCallback callback1;
1266 TestCompletionCallback callback2;
1267 TestCompletionCallback callback3;
1269 HttpRequestInfo httpreq1 = CreateGetRequest();
1270 HttpRequestInfo httpreq2 = CreateGetRequest();
1271 HttpRequestInfo httpreq3 = CreateGetRequest();
1273 out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
1274 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1275 // run transaction 1 through quickly to force a read of our SETTINGS
1276 // frame
1277 out.rv = callback1.WaitForResult();
1278 ASSERT_EQ(OK, out.rv);
1280 out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
1281 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1282 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1283 delete trans3.release();
1284 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1285 out.rv = callback2.WaitForResult();
1286 ASSERT_EQ(OK, out.rv);
1288 EXPECT_EQ(8U, data->read_index());
1290 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1291 ASSERT_TRUE(response1 != NULL);
1292 EXPECT_TRUE(response1->headers != NULL);
1293 EXPECT_TRUE(response1->was_fetched_via_spdy);
1294 out.status_line = response1->headers->GetStatusLine();
1295 out.response_info = *response1;
1296 out.rv = ReadTransaction(trans1.get(), &out.response_data);
1297 EXPECT_EQ(OK, out.rv);
1298 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1299 EXPECT_EQ("hello!hello!", out.response_data);
1301 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1302 ASSERT_TRUE(response2 != NULL);
1303 out.status_line = response2->headers->GetStatusLine();
1304 out.response_info = *response2;
1305 out.rv = ReadTransaction(trans2.get(), &out.response_data);
1306 EXPECT_EQ(OK, out.rv);
1307 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1308 EXPECT_EQ("hello!hello!", out.response_data);
1309 helper.VerifyDataConsumed();
1310 EXPECT_EQ(OK, out.rv);
1313 // The KillerCallback will delete the transaction on error as part of the
1314 // callback.
1315 class KillerCallback : public TestCompletionCallbackBase {
1316 public:
1317 explicit KillerCallback(HttpNetworkTransaction* transaction)
1318 : transaction_(transaction),
1319 ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
1320 base::Bind(&KillerCallback::OnComplete, base::Unretained(this)))) {
1323 virtual ~KillerCallback() {}
1325 const CompletionCallback& callback() const { return callback_; }
1327 private:
1328 void OnComplete(int result) {
1329 if (result < 0)
1330 delete transaction_;
1332 SetResult(result);
1335 HttpNetworkTransaction* transaction_;
1336 CompletionCallback callback_;
1339 // Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
1340 // closes the socket while we have a pending transaction waiting for
1341 // a pending stream creation. http://crbug.com/52901
1342 TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
1343 // Construct the request.
1344 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1345 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1346 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, false));
1347 scoped_ptr<spdy::SpdyFrame> fin_body(ConstructSpdyBodyFrame(1, true));
1349 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
1350 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
1352 spdy::SpdySettings settings;
1353 spdy::SettingsFlagsAndId id(0);
1354 id.set_id(spdy::SETTINGS_MAX_CONCURRENT_STREAMS);
1355 const size_t max_concurrent_streams = 1;
1357 settings.push_back(spdy::SpdySetting(id, max_concurrent_streams));
1358 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
1360 MockWrite writes[] = { CreateMockWrite(*req),
1361 CreateMockWrite(*req2),
1363 MockRead reads[] = {
1364 CreateMockRead(*settings_frame, 1),
1365 CreateMockRead(*resp),
1366 CreateMockRead(*body),
1367 CreateMockRead(*fin_body),
1368 CreateMockRead(*resp2, 7),
1369 MockRead(ASYNC, ERR_CONNECTION_RESET, 0), // Abort!
1372 scoped_ptr<OrderedSocketData> data(
1373 new OrderedSocketData(reads, arraysize(reads),
1374 writes, arraysize(writes)));
1375 scoped_ptr<OrderedSocketData> data_placeholder(
1376 new OrderedSocketData(NULL, 0, NULL, 0));
1378 BoundNetLog log;
1379 TransactionHelperResult out;
1380 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1381 BoundNetLog(), GetParam());
1382 helper.RunPreTestSetup();
1383 helper.AddData(data.get());
1384 // We require placeholder data because three get requests are sent out, so
1385 // there needs to be three sets of SSL connection data.
1386 helper.AddData(data_placeholder.get());
1387 helper.AddData(data_placeholder.get());
1388 HttpNetworkTransaction trans1(helper.session());
1389 HttpNetworkTransaction trans2(helper.session());
1390 HttpNetworkTransaction* trans3(new HttpNetworkTransaction(helper.session()));
1392 TestCompletionCallback callback1;
1393 TestCompletionCallback callback2;
1394 KillerCallback callback3(trans3);
1396 HttpRequestInfo httpreq1 = CreateGetRequest();
1397 HttpRequestInfo httpreq2 = CreateGetRequest();
1398 HttpRequestInfo httpreq3 = CreateGetRequest();
1400 out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
1401 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1402 // run transaction 1 through quickly to force a read of our SETTINGS
1403 // frame
1404 out.rv = callback1.WaitForResult();
1405 ASSERT_EQ(OK, out.rv);
1407 out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
1408 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1409 out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
1410 ASSERT_EQ(out.rv, ERR_IO_PENDING);
1411 out.rv = callback3.WaitForResult();
1412 ASSERT_EQ(ERR_ABORTED, out.rv);
1414 EXPECT_EQ(6U, data->read_index());
1416 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
1417 ASSERT_TRUE(response1 != NULL);
1418 EXPECT_TRUE(response1->headers != NULL);
1419 EXPECT_TRUE(response1->was_fetched_via_spdy);
1420 out.status_line = response1->headers->GetStatusLine();
1421 out.response_info = *response1;
1422 out.rv = ReadTransaction(&trans1, &out.response_data);
1423 EXPECT_EQ(OK, out.rv);
1425 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
1426 ASSERT_TRUE(response2 != NULL);
1427 out.status_line = response2->headers->GetStatusLine();
1428 out.response_info = *response2;
1429 out.rv = ReadTransaction(&trans2, &out.response_data);
1430 EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
1432 helper.VerifyDataConsumed();
1435 // Test that a simple PUT request works.
1436 TEST_P(SpdyNetworkTransactionTest, Put) {
1437 // Setup the request
1438 HttpRequestInfo request;
1439 request.method = "PUT";
1440 request.url = GURL("http://www.google.com/");
1442 const SpdyHeaderInfo kSynStartHeader = {
1443 spdy::SYN_STREAM, // Kind = Syn
1444 1, // Stream ID
1445 0, // Associated stream ID
1446 net::ConvertRequestPriorityToSpdyPriority(LOWEST), // Priority
1447 spdy::CONTROL_FLAG_FIN, // Control Flags
1448 false, // Compressed
1449 spdy::INVALID, // Status
1450 NULL, // Data
1451 0, // Length
1452 spdy::DATA_FLAG_NONE // Data Flags
1454 const char* const kPutHeaders[] = {
1455 "method", "PUT",
1456 "url", "/",
1457 "host", "www.google.com",
1458 "scheme", "http",
1459 "version", "HTTP/1.1",
1460 "content-length", "0"
1462 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0,
1463 kPutHeaders, arraysize(kPutHeaders) / 2));
1464 MockWrite writes[] = {
1465 CreateMockWrite(*req)
1468 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1469 const SpdyHeaderInfo kSynReplyHeader = {
1470 spdy::SYN_REPLY, // Kind = SynReply
1471 1, // Stream ID
1472 0, // Associated stream ID
1473 net::ConvertRequestPriorityToSpdyPriority(LOWEST), // Priority
1474 spdy::CONTROL_FLAG_NONE, // Control Flags
1475 false, // Compressed
1476 spdy::INVALID, // Status
1477 NULL, // Data
1478 0, // Length
1479 spdy::DATA_FLAG_NONE // Data Flags
1481 static const char* const kStandardGetHeaders[] = {
1482 "status", "200",
1483 "version", "HTTP/1.1"
1484 "content-length", "1234"
1486 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPacket(kSynReplyHeader,
1487 NULL, 0, kStandardGetHeaders, arraysize(kStandardGetHeaders) / 2));
1488 MockRead reads[] = {
1489 CreateMockRead(*resp),
1490 CreateMockRead(*body),
1491 MockRead(ASYNC, 0, 0) // EOF
1494 scoped_ptr<DelayedSocketData> data(
1495 new DelayedSocketData(1, reads, arraysize(reads),
1496 writes, arraysize(writes)));
1497 NormalSpdyTransactionHelper helper(request,
1498 BoundNetLog(), GetParam());
1499 helper.RunToCompletion(data.get());
1500 TransactionHelperResult out = helper.output();
1502 EXPECT_EQ(OK, out.rv);
1503 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1506 // Test that a simple HEAD request works.
1507 TEST_P(SpdyNetworkTransactionTest, Head) {
1508 // Setup the request
1509 HttpRequestInfo request;
1510 request.method = "HEAD";
1511 request.url = GURL("http://www.google.com/");
1513 const SpdyHeaderInfo kSynStartHeader = {
1514 spdy::SYN_STREAM, // Kind = Syn
1515 1, // Stream ID
1516 0, // Associated stream ID
1517 net::ConvertRequestPriorityToSpdyPriority(LOWEST), // Priority
1518 spdy::CONTROL_FLAG_FIN, // Control Flags
1519 false, // Compressed
1520 spdy::INVALID, // Status
1521 NULL, // Data
1522 0, // Length
1523 spdy::DATA_FLAG_NONE // Data Flags
1525 const char* const kHeadHeaders[] = {
1526 "method", "HEAD",
1527 "url", "/",
1528 "host", "www.google.com",
1529 "scheme", "http",
1530 "version", "HTTP/1.1",
1531 "content-length", "0"
1533 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0,
1534 kHeadHeaders, arraysize(kHeadHeaders) / 2));
1535 MockWrite writes[] = {
1536 CreateMockWrite(*req)
1539 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1540 const SpdyHeaderInfo kSynReplyHeader = {
1541 spdy::SYN_REPLY, // Kind = SynReply
1542 1, // Stream ID
1543 0, // Associated stream ID
1544 net::ConvertRequestPriorityToSpdyPriority(LOWEST), // Priority
1545 spdy::CONTROL_FLAG_NONE, // Control Flags
1546 false, // Compressed
1547 spdy::INVALID, // Status
1548 NULL, // Data
1549 0, // Length
1550 spdy::DATA_FLAG_NONE // Data Flags
1552 static const char* const kStandardGetHeaders[] = {
1553 "status", "200",
1554 "version", "HTTP/1.1"
1555 "content-length", "1234"
1557 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPacket(kSynReplyHeader,
1558 NULL, 0, kStandardGetHeaders, arraysize(kStandardGetHeaders) / 2));
1559 MockRead reads[] = {
1560 CreateMockRead(*resp),
1561 CreateMockRead(*body),
1562 MockRead(ASYNC, 0, 0) // EOF
1565 scoped_ptr<DelayedSocketData> data(
1566 new DelayedSocketData(1, reads, arraysize(reads),
1567 writes, arraysize(writes)));
1568 NormalSpdyTransactionHelper helper(request,
1569 BoundNetLog(), GetParam());
1570 helper.RunToCompletion(data.get());
1571 TransactionHelperResult out = helper.output();
1573 EXPECT_EQ(OK, out.rv);
1574 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1577 // Test that a simple POST works.
1578 TEST_P(SpdyNetworkTransactionTest, Post) {
1579 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(kUploadDataSize, NULL, 0));
1580 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1581 MockWrite writes[] = {
1582 CreateMockWrite(*req),
1583 CreateMockWrite(*body), // POST upload frame
1586 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1587 MockRead reads[] = {
1588 CreateMockRead(*resp),
1589 CreateMockRead(*body),
1590 MockRead(ASYNC, 0, 0) // EOF
1593 scoped_ptr<DelayedSocketData> data(
1594 new DelayedSocketData(2, reads, arraysize(reads),
1595 writes, arraysize(writes)));
1596 NormalSpdyTransactionHelper helper(CreatePostRequest(),
1597 BoundNetLog(), GetParam());
1598 helper.RunToCompletion(data.get());
1599 TransactionHelperResult out = helper.output();
1600 EXPECT_EQ(OK, out.rv);
1601 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1602 EXPECT_EQ("hello!", out.response_data);
1605 // Test that a chunked POST works.
1606 TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
1607 UploadDataStream::set_merge_chunks(false);
1608 scoped_ptr<spdy::SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
1609 scoped_ptr<spdy::SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
1610 scoped_ptr<spdy::SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true));
1611 MockWrite writes[] = {
1612 CreateMockWrite(*req),
1613 CreateMockWrite(*chunk1),
1614 CreateMockWrite(*chunk2),
1617 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1618 MockRead reads[] = {
1619 CreateMockRead(*resp),
1620 CreateMockRead(*chunk1),
1621 CreateMockRead(*chunk2),
1622 MockRead(ASYNC, 0, 0) // EOF
1625 scoped_ptr<DelayedSocketData> data(
1626 new DelayedSocketData(2, reads, arraysize(reads),
1627 writes, arraysize(writes)));
1628 NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
1629 BoundNetLog(), GetParam());
1630 helper.RunToCompletion(data.get());
1631 TransactionHelperResult out = helper.output();
1632 EXPECT_EQ(OK, out.rv);
1633 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1634 EXPECT_EQ("hello!hello!", out.response_data);
1637 // Test that a POST without any post data works.
1638 TEST_P(SpdyNetworkTransactionTest, NullPost) {
1639 // Setup the request
1640 HttpRequestInfo request;
1641 request.method = "POST";
1642 request.url = GURL("http://www.google.com/");
1643 // Create an empty UploadData.
1644 request.upload_data = NULL;
1646 // When request.upload_data is NULL for post, content-length is
1647 // expected to be 0.
1648 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(0, NULL, 0));
1649 // Set the FIN bit since there will be no body.
1650 req->set_flags(spdy::CONTROL_FLAG_FIN);
1651 MockWrite writes[] = {
1652 CreateMockWrite(*req),
1655 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1656 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1657 MockRead reads[] = {
1658 CreateMockRead(*resp),
1659 CreateMockRead(*body),
1660 MockRead(ASYNC, 0, 0) // EOF
1663 scoped_ptr<DelayedSocketData> data(
1664 new DelayedSocketData(1, reads, arraysize(reads),
1665 writes, arraysize(writes)));
1667 NormalSpdyTransactionHelper helper(request,
1668 BoundNetLog(), GetParam());
1669 helper.RunToCompletion(data.get());
1670 TransactionHelperResult out = helper.output();
1671 EXPECT_EQ(OK, out.rv);
1672 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1673 EXPECT_EQ("hello!", out.response_data);
1676 // Test that a simple POST works.
1677 TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
1678 // Setup the request
1679 HttpRequestInfo request;
1680 request.method = "POST";
1681 request.url = GURL("http://www.google.com/");
1682 // Create an empty UploadData.
1683 request.upload_data = new UploadData();
1685 // Http POST Content-Length is using UploadDataStream::size().
1686 // It is the same as request.upload_data->GetContentLengthSync().
1687 scoped_ptr<UploadDataStream> stream(
1688 new UploadDataStream(request.upload_data));
1689 ASSERT_EQ(OK, stream->Init());
1690 ASSERT_EQ(request.upload_data->GetContentLengthSync(),
1691 stream->size());
1693 scoped_ptr<spdy::SpdyFrame>
1694 req(ConstructSpdyPost(
1695 request.upload_data->GetContentLengthSync(), NULL, 0));
1696 // Set the FIN bit since there will be no body.
1697 req->set_flags(spdy::CONTROL_FLAG_FIN);
1698 MockWrite writes[] = {
1699 CreateMockWrite(*req),
1702 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1703 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1704 MockRead reads[] = {
1705 CreateMockRead(*resp),
1706 CreateMockRead(*body),
1707 MockRead(ASYNC, 0, 0) // EOF
1710 scoped_ptr<DelayedSocketData> data(
1711 new DelayedSocketData(1, reads, arraysize(reads),
1712 writes, arraysize(writes)));
1714 NormalSpdyTransactionHelper helper(request,
1715 BoundNetLog(), GetParam());
1716 helper.RunToCompletion(data.get());
1717 TransactionHelperResult out = helper.output();
1718 EXPECT_EQ(OK, out.rv);
1719 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1720 EXPECT_EQ("hello!", out.response_data);
1723 // While we're doing a post, the server sends back a SYN_REPLY.
1724 TEST_P(SpdyNetworkTransactionTest, PostWithEarlySynReply) {
1725 static const char upload[] = { "hello!" };
1727 // Setup the request
1728 HttpRequestInfo request;
1729 request.method = "POST";
1730 request.url = GURL("http://www.google.com/");
1731 request.upload_data = new UploadData();
1732 request.upload_data->AppendBytes(upload, sizeof(upload));
1734 // Http POST Content-Length is using UploadDataStream::size().
1735 // It is the same as request.upload_data->GetContentLengthSync().
1736 scoped_ptr<UploadDataStream> stream(
1737 new UploadDataStream(request.upload_data));
1738 ASSERT_EQ(OK, stream->Init());
1739 ASSERT_EQ(request.upload_data->GetContentLengthSync(),
1740 stream->size());
1741 scoped_ptr<spdy::SpdyFrame> stream_reply(ConstructSpdyPostSynReply(NULL, 0));
1742 scoped_ptr<spdy::SpdyFrame> stream_body(ConstructSpdyBodyFrame(1, true));
1743 MockRead reads[] = {
1744 CreateMockRead(*stream_reply, 2),
1745 CreateMockRead(*stream_body, 3),
1746 MockRead(SYNCHRONOUS, 0, 0) // EOF
1749 scoped_ptr<DelayedSocketData> data(
1750 new DelayedSocketData(0, reads, arraysize(reads), NULL, 0));
1751 NormalSpdyTransactionHelper helper(request,
1752 BoundNetLog(), GetParam());
1753 helper.RunPreTestSetup();
1754 helper.AddData(data.get());
1755 helper.RunDefaultTest();
1756 helper.VerifyDataConsumed();
1758 TransactionHelperResult out = helper.output();
1759 EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED, out.rv);
1762 // The client upon cancellation tries to send a RST_STREAM frame. The mock
1763 // socket causes the TCP write to return zero. This test checks that the client
1764 // tries to queue up the RST_STREAM frame again.
1765 TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
1766 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1767 scoped_ptr<spdy::SpdyFrame> rst(
1768 ConstructSpdyRstStream(1, spdy::CANCEL));
1769 MockWrite writes[] = {
1770 CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
1771 MockWrite(SYNCHRONOUS, 0, 0, 2),
1772 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
1775 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1776 MockRead reads[] = {
1777 CreateMockRead(*resp.get(), 1, ASYNC),
1778 MockRead(ASYNC, 0, 0, 4) // EOF
1781 scoped_refptr<DeterministicSocketData> data(
1782 new DeterministicSocketData(reads, arraysize(reads),
1783 writes, arraysize(writes)));
1784 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1785 BoundNetLog(), GetParam());
1786 helper.SetDeterministic();
1787 helper.RunPreTestSetup();
1788 helper.AddDeterministicData(data.get());
1789 HttpNetworkTransaction* trans = helper.trans();
1791 TestCompletionCallback callback;
1792 int rv = trans->Start(
1793 &CreateGetRequest(), callback.callback(), BoundNetLog());
1794 EXPECT_EQ(ERR_IO_PENDING, rv);
1796 data->SetStop(2);
1797 data->Run();
1798 helper.ResetTrans();
1799 data->SetStop(20);
1800 data->Run();
1802 helper.VerifyDataConsumed();
1805 // Test that the transaction doesn't crash when we don't have a reply.
1806 TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
1807 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1808 MockRead reads[] = {
1809 CreateMockRead(*body),
1810 MockRead(ASYNC, 0, 0) // EOF
1813 scoped_ptr<DelayedSocketData> data(
1814 new DelayedSocketData(1, reads, arraysize(reads), NULL, 0));
1815 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1816 BoundNetLog(), GetParam());
1817 helper.RunToCompletion(data.get());
1818 TransactionHelperResult out = helper.output();
1819 EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED, out.rv);
1822 // Test that the transaction doesn't crash when we get two replies on the same
1823 // stream ID. See http://crbug.com/45639.
1824 TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
1825 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1826 MockWrite writes[] = { CreateMockWrite(*req) };
1828 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1829 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
1830 MockRead reads[] = {
1831 CreateMockRead(*resp),
1832 CreateMockRead(*resp),
1833 CreateMockRead(*body),
1834 MockRead(ASYNC, 0, 0) // EOF
1837 scoped_ptr<DelayedSocketData> data(
1838 new DelayedSocketData(1, reads, arraysize(reads),
1839 writes, arraysize(writes)));
1841 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1842 BoundNetLog(), GetParam());
1843 helper.RunPreTestSetup();
1844 helper.AddData(data.get());
1846 HttpNetworkTransaction* trans = helper.trans();
1848 TestCompletionCallback callback;
1849 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
1850 EXPECT_EQ(ERR_IO_PENDING, rv);
1851 rv = callback.WaitForResult();
1852 EXPECT_EQ(OK, rv);
1854 const HttpResponseInfo* response = trans->GetResponseInfo();
1855 ASSERT_TRUE(response != NULL);
1856 EXPECT_TRUE(response->headers != NULL);
1857 EXPECT_TRUE(response->was_fetched_via_spdy);
1858 std::string response_data;
1859 rv = ReadTransaction(trans, &response_data);
1860 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
1862 helper.VerifyDataConsumed();
1865 // Test that sent data frames and received WINDOW_UPDATE frames change
1866 // the send_window_size_ correctly.
1868 // WINDOW_UPDATE is different than most other frames in that it can arrive
1869 // while the client is still sending the request body. In order to enforce
1870 // this scenario, we feed a couple of dummy frames and give a delay of 0 to
1871 // socket data provider, so that initial read that is done as soon as the
1872 // stream is created, succeeds and schedules another read. This way reads
1873 // and writes are interleaved; after doing a full frame write, SpdyStream
1874 // will break out of DoLoop and will read and process a WINDOW_UPDATE.
1875 // Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
1876 // since request has not been completely written, therefore we feed
1877 // enough number of WINDOW_UPDATEs to finish the first read and cause a
1878 // write, leading to a complete write of request body; after that we send
1879 // a reply with a body, to cause a graceful shutdown.
1881 // TODO(agayev): develop a socket data provider where both, reads and
1882 // writes are ordered so that writing tests like these are easy and rewrite
1883 // all these tests using it. Right now we are working around the
1884 // limitations as described above and it's not deterministic, tests may
1885 // fail under specific circumstances.
1886 TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
1887 SpdySession::set_use_flow_control(SpdySession::kEnableFlowControl);
1889 static int kFrameCount = 2;
1890 scoped_ptr<std::string> content(
1891 new std::string(kMaxSpdyFrameChunkSize, 'a'));
1892 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(
1893 kMaxSpdyFrameChunkSize * kFrameCount, NULL, 0));
1894 scoped_ptr<spdy::SpdyFrame> body(
1895 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
1896 scoped_ptr<spdy::SpdyFrame> body_end(
1897 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), true));
1899 MockWrite writes[] = {
1900 CreateMockWrite(*req),
1901 CreateMockWrite(*body),
1902 CreateMockWrite(*body_end),
1905 static const int32 kDeltaWindowSize = 0xff;
1906 static const int kDeltaCount = 4;
1907 scoped_ptr<spdy::SpdyFrame> window_update(
1908 ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
1909 scoped_ptr<spdy::SpdyFrame> window_update_dummy(
1910 ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
1911 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
1912 MockRead reads[] = {
1913 CreateMockRead(*window_update_dummy),
1914 CreateMockRead(*window_update_dummy),
1915 CreateMockRead(*window_update_dummy),
1916 CreateMockRead(*window_update), // Four updates, therefore window
1917 CreateMockRead(*window_update), // size should increase by
1918 CreateMockRead(*window_update), // kDeltaWindowSize * 4
1919 CreateMockRead(*window_update),
1920 CreateMockRead(*resp),
1921 CreateMockRead(*body_end),
1922 MockRead(ASYNC, 0, 0) // EOF
1925 scoped_ptr<DelayedSocketData> data(
1926 new DelayedSocketData(0, reads, arraysize(reads),
1927 writes, arraysize(writes)));
1929 // Setup the request
1930 HttpRequestInfo request;
1931 request.method = "POST";
1932 request.url = GURL(kDefaultURL);
1933 request.upload_data = new UploadData();
1934 for (int i = 0; i < kFrameCount; ++i)
1935 request.upload_data->AppendBytes(content->c_str(), content->size());
1937 NormalSpdyTransactionHelper helper(request, BoundNetLog(), GetParam());
1938 helper.AddData(data.get());
1939 helper.RunPreTestSetup();
1941 HttpNetworkTransaction* trans = helper.trans();
1943 TestCompletionCallback callback;
1944 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
1946 EXPECT_EQ(ERR_IO_PENDING, rv);
1947 rv = callback.WaitForResult();
1948 EXPECT_EQ(OK, rv);
1950 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
1951 ASSERT_TRUE(stream != NULL);
1952 ASSERT_TRUE(stream->stream() != NULL);
1953 EXPECT_EQ(static_cast<int>(spdy::kSpdyStreamInitialWindowSize) +
1954 kDeltaWindowSize * kDeltaCount -
1955 kMaxSpdyFrameChunkSize * kFrameCount,
1956 stream->stream()->send_window_size());
1957 helper.VerifyDataConsumed();
1959 SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN);
1962 // Test that received data frames and sent WINDOW_UPDATE frames change
1963 // the recv_window_size_ correctly.
1964 TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
1965 SpdySession::set_use_flow_control(SpdySession::kEnableFlowControl);
1967 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
1968 scoped_ptr<spdy::SpdyFrame> window_update(
1969 ConstructSpdyWindowUpdate(1, kUploadDataSize));
1971 MockWrite writes[] = {
1972 CreateMockWrite(*req),
1973 CreateMockWrite(*window_update),
1976 scoped_ptr<spdy::SpdyFrame> resp(
1977 ConstructSpdyGetSynReply(NULL, 0, 1));
1978 scoped_ptr<spdy::SpdyFrame> body_no_fin(
1979 ConstructSpdyBodyFrame(1, false));
1980 scoped_ptr<spdy::SpdyFrame> body_fin(
1981 ConstructSpdyBodyFrame(1, NULL, 0, true));
1982 MockRead reads[] = {
1983 CreateMockRead(*resp),
1984 CreateMockRead(*body_no_fin),
1985 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause
1986 CreateMockRead(*body_fin),
1987 MockRead(ASYNC, ERR_IO_PENDING, 0), // Force a pause
1988 MockRead(ASYNC, 0, 0) // EOF
1991 scoped_ptr<DelayedSocketData> data(
1992 new DelayedSocketData(1, reads, arraysize(reads),
1993 writes, arraysize(writes)));
1995 NormalSpdyTransactionHelper helper(CreateGetRequest(),
1996 BoundNetLog(), GetParam());
1997 helper.AddData(data.get());
1998 helper.RunPreTestSetup();
1999 HttpNetworkTransaction* trans = helper.trans();
2001 TestCompletionCallback callback;
2002 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2004 EXPECT_EQ(ERR_IO_PENDING, rv);
2005 rv = callback.WaitForResult();
2006 EXPECT_EQ(OK, rv);
2008 SpdyHttpStream* stream =
2009 static_cast<SpdyHttpStream*>(trans->stream_.get());
2010 ASSERT_TRUE(stream != NULL);
2011 ASSERT_TRUE(stream->stream() != NULL);
2013 EXPECT_EQ(
2014 static_cast<int>(spdy::kSpdyStreamInitialWindowSize) - kUploadDataSize,
2015 stream->stream()->recv_window_size());
2017 const HttpResponseInfo* response = trans->GetResponseInfo();
2018 ASSERT_TRUE(response != NULL);
2019 ASSERT_TRUE(response->headers != NULL);
2020 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2021 EXPECT_TRUE(response->was_fetched_via_spdy);
2023 // Issue a read which will cause a WINDOW_UPDATE to be sent and window
2024 // size increased to default.
2025 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kUploadDataSize));
2026 rv = trans->Read(buf, kUploadDataSize, CompletionCallback());
2027 EXPECT_EQ(kUploadDataSize, rv);
2028 std::string content(buf->data(), buf->data()+kUploadDataSize);
2029 EXPECT_STREQ(kUploadData, content.c_str());
2031 // Schedule the reading of empty data frame with FIN
2032 data->CompleteRead();
2034 // Force write of WINDOW_UPDATE which was scheduled during the above
2035 // read.
2036 MessageLoop::current()->RunAllPending();
2038 // Read EOF.
2039 data->CompleteRead();
2041 helper.VerifyDataConsumed();
2043 SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN);
2046 // Test that WINDOW_UPDATE frame causing overflow is handled correctly. We
2047 // use the same trick as in the above test to enforce our scenario.
2048 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
2049 SpdySession::set_use_flow_control(SpdySession::kEnableFlowControl);
2051 // number of full frames we hope to write (but will not, used to
2052 // set content-length header correctly)
2053 static int kFrameCount = 3;
2055 scoped_ptr<std::string> content(
2056 new std::string(kMaxSpdyFrameChunkSize, 'a'));
2057 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(
2058 kMaxSpdyFrameChunkSize * kFrameCount, NULL, 0));
2059 scoped_ptr<spdy::SpdyFrame> body(
2060 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
2061 scoped_ptr<spdy::SpdyFrame> rst(
2062 ConstructSpdyRstStream(1, spdy::FLOW_CONTROL_ERROR));
2064 // We're not going to write a data frame with FIN, we'll receive a bad
2065 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
2066 MockWrite writes[] = {
2067 CreateMockWrite(*req),
2068 CreateMockWrite(*body),
2069 CreateMockWrite(*rst),
2072 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow
2073 scoped_ptr<spdy::SpdyFrame> window_update(
2074 ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
2075 scoped_ptr<spdy::SpdyFrame> window_update2(
2076 ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
2077 scoped_ptr<spdy::SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
2079 MockRead reads[] = {
2080 CreateMockRead(*window_update2),
2081 CreateMockRead(*window_update2),
2082 CreateMockRead(*window_update),
2083 CreateMockRead(*window_update),
2084 CreateMockRead(*window_update),
2085 MockRead(ASYNC, ERR_IO_PENDING, 0), // Wait for the RST to be written.
2086 MockRead(ASYNC, 0, 0) // EOF
2089 scoped_ptr<DelayedSocketData> data(
2090 new DelayedSocketData(0, reads, arraysize(reads),
2091 writes, arraysize(writes)));
2093 // Setup the request
2094 HttpRequestInfo request;
2095 request.method = "POST";
2096 request.url = GURL("http://www.google.com/");
2097 request.upload_data = new UploadData();
2098 for (int i = 0; i < kFrameCount; ++i)
2099 request.upload_data->AppendBytes(content->c_str(), content->size());
2101 NormalSpdyTransactionHelper helper(request,
2102 BoundNetLog(), GetParam());
2103 helper.AddData(data.get());
2104 helper.RunPreTestSetup();
2106 HttpNetworkTransaction* trans = helper.trans();
2108 TestCompletionCallback callback;
2109 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2111 EXPECT_EQ(ERR_IO_PENDING, rv);
2112 rv = callback.WaitForResult();
2113 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
2115 data->CompleteRead();
2117 ASSERT_TRUE(helper.session() != NULL);
2118 ASSERT_TRUE(helper.session()->spdy_session_pool() != NULL);
2119 helper.session()->spdy_session_pool()->CloseAllSessions();
2120 helper.VerifyDataConsumed();
2122 SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN);
2125 // Test that after hitting a send window size of 0, the write process
2126 // stalls and upon receiving WINDOW_UPDATE frame write resumes.
2128 // This test constructs a POST request followed by enough data frames
2129 // containing 'a' that would make the window size 0, followed by another
2130 // data frame containing default content (which is "hello!") and this frame
2131 // also contains a FIN flag. DelayedSocketData is used to enforce all
2132 // writes go through before a read could happen. However, the last frame
2133 // ("hello!") is not supposed to go through since by the time its turn
2134 // arrives, window size is 0. At this point MessageLoop::Run() called via
2135 // callback would block. Therefore we call MessageLoop::RunAllPending()
2136 // which returns after performing all possible writes. We use DCHECKS to
2137 // ensure that last data frame is still there and stream has stalled.
2138 // After that, next read is artifically enforced, which causes a
2139 // WINDOW_UPDATE to be read and I/O process resumes.
2140 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
2141 SpdySession::set_use_flow_control(SpdySession::kEnableFlowControl);
2143 // Number of frames we need to send to zero out the window size: data
2144 // frames plus SYN_STREAM plus the last data frame; also we need another
2145 // data frame that we will send once the WINDOW_UPDATE is received,
2146 // therefore +3.
2147 size_t nwrites =
2148 spdy::kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
2150 // Calculate last frame's size; 0 size data frame is legal.
2151 size_t last_frame_size =
2152 spdy::kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
2154 // Construct content for a data frame of maximum size.
2155 scoped_ptr<std::string> content(
2156 new std::string(kMaxSpdyFrameChunkSize, 'a'));
2158 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost(
2159 spdy::kSpdyStreamInitialWindowSize + kUploadDataSize, NULL, 0));
2161 // Full frames.
2162 scoped_ptr<spdy::SpdyFrame> body1(
2163 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false));
2165 // Last frame to zero out the window size.
2166 scoped_ptr<spdy::SpdyFrame> body2(
2167 ConstructSpdyBodyFrame(1, content->c_str(), last_frame_size, false));
2169 // Data frame to be sent once WINDOW_UPDATE frame is received.
2170 scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(1, true));
2172 // Fill in mock writes.
2173 scoped_array<MockWrite> writes(new MockWrite[nwrites]);
2174 size_t i = 0;
2175 writes[i] = CreateMockWrite(*req);
2176 for (i = 1; i < nwrites-2; i++)
2177 writes[i] = CreateMockWrite(*body1);
2178 writes[i++] = CreateMockWrite(*body2);
2179 writes[i] = CreateMockWrite(*body3);
2181 // Construct read frame, give enough space to upload the rest of the
2182 // data.
2183 scoped_ptr<spdy::SpdyFrame> window_update(
2184 ConstructSpdyWindowUpdate(1, kUploadDataSize));
2185 scoped_ptr<spdy::SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
2186 MockRead reads[] = {
2187 CreateMockRead(*window_update),
2188 CreateMockRead(*window_update),
2189 CreateMockRead(*reply),
2190 CreateMockRead(*body2),
2191 CreateMockRead(*body3),
2192 MockRead(ASYNC, 0, 0) // EOF
2195 // Force all writes to happen before any read, last write will not
2196 // actually queue a frame, due to window size being 0.
2197 scoped_ptr<DelayedSocketData> data(
2198 new DelayedSocketData(nwrites, reads, arraysize(reads),
2199 writes.get(), nwrites));
2201 HttpRequestInfo request;
2202 request.method = "POST";
2203 request.url = GURL("http://www.google.com/");
2204 request.upload_data = new UploadData();
2205 scoped_ptr<std::string> upload_data(
2206 new std::string(spdy::kSpdyStreamInitialWindowSize, 'a'));
2207 upload_data->append(kUploadData, kUploadDataSize);
2208 request.upload_data->AppendBytes(upload_data->c_str(), upload_data->size());
2209 NormalSpdyTransactionHelper helper(request,
2210 BoundNetLog(), GetParam());
2211 helper.AddData(data.get());
2212 helper.RunPreTestSetup();
2214 HttpNetworkTransaction* trans = helper.trans();
2216 TestCompletionCallback callback;
2217 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2218 EXPECT_EQ(ERR_IO_PENDING, rv);
2220 MessageLoop::current()->RunAllPending(); // Write as much as we can.
2222 SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
2223 ASSERT_TRUE(stream != NULL);
2224 ASSERT_TRUE(stream->stream() != NULL);
2225 EXPECT_EQ(0, stream->stream()->send_window_size());
2226 // All the body data should have been read.
2227 // TODO(satorux): This is because of the weirdness in reading the request
2228 // body in OnSendBodyComplete(). See crbug.com/113107.
2229 EXPECT_TRUE(stream->request_body_stream_->IsEOF());
2230 // But the body is not yet fully sent ("hello!" is not yet sent).
2231 EXPECT_FALSE(stream->stream()->body_sent());
2233 data->ForceNextRead(); // Read in WINDOW_UPDATE frame.
2234 rv = callback.WaitForResult();
2235 helper.VerifyDataConsumed();
2237 SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN);
2240 TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
2241 // Construct the request.
2242 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2243 MockWrite writes[] = {
2244 CreateMockWrite(*req),
2247 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2248 MockRead reads[] = {
2249 CreateMockRead(*resp),
2250 // This following read isn't used by the test, except during the
2251 // RunAllPending() call at the end since the SpdySession survives the
2252 // HttpNetworkTransaction and still tries to continue Read()'ing. Any
2253 // MockRead will do here.
2254 MockRead(ASYNC, 0, 0) // EOF
2257 StaticSocketDataProvider data(reads, arraysize(reads),
2258 writes, arraysize(writes));
2260 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2261 BoundNetLog(), GetParam());
2262 helper.RunPreTestSetup();
2263 helper.AddData(&data);
2264 HttpNetworkTransaction* trans = helper.trans();
2266 TestCompletionCallback callback;
2267 int rv = trans->Start(
2268 &CreateGetRequest(), callback.callback(), BoundNetLog());
2269 EXPECT_EQ(ERR_IO_PENDING, rv);
2270 helper.ResetTrans(); // Cancel the transaction.
2272 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2273 // MockClientSocketFactory) are still alive.
2274 MessageLoop::current()->RunAllPending();
2275 helper.VerifyDataNotConsumed();
2278 // Verify that the client sends a Rst Frame upon cancelling the stream.
2279 TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
2280 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2281 scoped_ptr<spdy::SpdyFrame> rst(
2282 ConstructSpdyRstStream(1, spdy::CANCEL));
2283 MockWrite writes[] = {
2284 CreateMockWrite(*req, 0, SYNCHRONOUS),
2285 CreateMockWrite(*rst, 2, SYNCHRONOUS),
2288 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2289 MockRead reads[] = {
2290 CreateMockRead(*resp, 1, ASYNC),
2291 MockRead(ASYNC, 0, 0, 3) // EOF
2294 scoped_refptr<DeterministicSocketData> data(
2295 new DeterministicSocketData(reads, arraysize(reads),
2296 writes, arraysize(writes)));
2298 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2299 BoundNetLog(),
2300 GetParam());
2301 helper.SetDeterministic();
2302 helper.RunPreTestSetup();
2303 helper.AddDeterministicData(data.get());
2304 HttpNetworkTransaction* trans = helper.trans();
2306 TestCompletionCallback callback;
2308 int rv = trans->Start(
2309 &CreateGetRequest(), callback.callback(), BoundNetLog());
2310 EXPECT_EQ(ERR_IO_PENDING, rv);
2312 data->SetStop(2);
2313 data->Run();
2314 helper.ResetTrans();
2315 data->SetStop(20);
2316 data->Run();
2318 helper.VerifyDataConsumed();
2321 // Verify that the client can correctly deal with the user callback attempting
2322 // to start another transaction on a session that is closing down. See
2323 // http://crbug.com/47455
2324 TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
2325 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2326 MockWrite writes[] = { CreateMockWrite(*req) };
2327 MockWrite writes2[] = { CreateMockWrite(*req) };
2329 // The indicated length of this packet is longer than its actual length. When
2330 // the session receives an empty packet after this one, it shuts down the
2331 // session, and calls the read callback with the incomplete data.
2332 const uint8 kGetBodyFrame2[] = {
2333 0x00, 0x00, 0x00, 0x01,
2334 0x01, 0x00, 0x00, 0x07,
2335 'h', 'e', 'l', 'l', 'o', '!',
2338 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2339 MockRead reads[] = {
2340 CreateMockRead(*resp, 2),
2341 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2342 MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2343 arraysize(kGetBodyFrame2), 4),
2344 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2345 MockRead(ASYNC, 0, 0, 6), // EOF
2347 MockRead reads2[] = {
2348 CreateMockRead(*resp, 2),
2349 MockRead(ASYNC, 0, 0, 3), // EOF
2352 scoped_ptr<OrderedSocketData> data(
2353 new OrderedSocketData(reads, arraysize(reads),
2354 writes, arraysize(writes)));
2355 scoped_ptr<DelayedSocketData> data2(
2356 new DelayedSocketData(1, reads2, arraysize(reads2),
2357 writes2, arraysize(writes2)));
2359 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2360 BoundNetLog(), GetParam());
2361 helper.RunPreTestSetup();
2362 helper.AddData(data.get());
2363 helper.AddData(data2.get());
2364 HttpNetworkTransaction* trans = helper.trans();
2366 // Start the transaction with basic parameters.
2367 TestCompletionCallback callback;
2368 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2369 EXPECT_EQ(ERR_IO_PENDING, rv);
2370 rv = callback.WaitForResult();
2372 const int kSize = 3000;
2373 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2374 rv = trans->Read(
2375 buf, kSize,
2376 base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
2377 helper.session()));
2378 // This forces an err_IO_pending, which sets the callback.
2379 data->CompleteRead();
2380 // This finishes the read.
2381 data->CompleteRead();
2382 helper.VerifyDataConsumed();
2385 // Verify that the client can correctly deal with the user callback deleting the
2386 // transaction. Failures will usually be valgrind errors. See
2387 // http://crbug.com/46925
2388 TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
2389 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2390 MockWrite writes[] = { CreateMockWrite(*req) };
2392 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2393 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2394 MockRead reads[] = {
2395 CreateMockRead(*resp.get(), 2),
2396 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2397 CreateMockRead(*body.get(), 4),
2398 MockRead(ASYNC, 0, 0, 5), // EOF
2401 scoped_ptr<OrderedSocketData> data(
2402 new OrderedSocketData(reads, arraysize(reads),
2403 writes, arraysize(writes)));
2405 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2406 BoundNetLog(), GetParam());
2407 helper.RunPreTestSetup();
2408 helper.AddData(data.get());
2409 HttpNetworkTransaction* trans = helper.trans();
2411 // Start the transaction with basic parameters.
2412 TestCompletionCallback callback;
2413 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
2414 EXPECT_EQ(ERR_IO_PENDING, rv);
2415 rv = callback.WaitForResult();
2417 // Setup a user callback which will delete the session, and clear out the
2418 // memory holding the stream object. Note that the callback deletes trans.
2419 const int kSize = 3000;
2420 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2421 rv = trans->Read(
2422 buf, kSize,
2423 base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
2424 base::Unretained(&helper)));
2425 ASSERT_EQ(ERR_IO_PENDING, rv);
2426 data->CompleteRead();
2428 // Finish running rest of tasks.
2429 MessageLoop::current()->RunAllPending();
2430 helper.VerifyDataConsumed();
2433 // Send a spdy request to www.google.com that gets redirected to www.foo.com.
2434 TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
2435 // These are headers which the net::URLRequest tacks on.
2436 const char* const kExtraHeaders[] = {
2437 "accept-encoding",
2438 "gzip,deflate",
2440 const SpdyHeaderInfo kSynStartHeader = MakeSpdyHeader(spdy::SYN_STREAM);
2441 const char* const kStandardGetHeaders[] = {
2442 "host",
2443 "www.google.com",
2444 "method",
2445 "GET",
2446 "scheme",
2447 "http",
2448 "url",
2449 "/",
2450 "user-agent",
2452 "version",
2453 "HTTP/1.1"
2455 const char* const kStandardGetHeaders2[] = {
2456 "host",
2457 "www.foo.com",
2458 "method",
2459 "GET",
2460 "scheme",
2461 "http",
2462 "url",
2463 "/index.php",
2464 "user-agent",
2466 "version",
2467 "HTTP/1.1"
2470 // Setup writes/reads to www.google.com
2471 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(
2472 kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders) / 2,
2473 kStandardGetHeaders, arraysize(kStandardGetHeaders) / 2));
2474 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyPacket(
2475 kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders) / 2,
2476 kStandardGetHeaders2, arraysize(kStandardGetHeaders2) / 2));
2477 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReplyRedirect(1));
2478 MockWrite writes[] = {
2479 CreateMockWrite(*req, 1),
2481 MockRead reads[] = {
2482 CreateMockRead(*resp, 2),
2483 MockRead(ASYNC, 0, 0, 3) // EOF
2486 // Setup writes/reads to www.foo.com
2487 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
2488 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
2489 MockWrite writes2[] = {
2490 CreateMockWrite(*req2, 1),
2492 MockRead reads2[] = {
2493 CreateMockRead(*resp2, 2),
2494 CreateMockRead(*body2, 3),
2495 MockRead(ASYNC, 0, 0, 4) // EOF
2497 scoped_ptr<OrderedSocketData> data(
2498 new OrderedSocketData(reads, arraysize(reads),
2499 writes, arraysize(writes)));
2500 scoped_ptr<OrderedSocketData> data2(
2501 new OrderedSocketData(reads2, arraysize(reads2),
2502 writes2, arraysize(writes2)));
2504 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2505 HttpStreamFactory::set_force_spdy_over_ssl(false);
2506 HttpStreamFactory::set_force_spdy_always(true);
2507 TestDelegate d;
2509 net::URLRequest r(GURL("http://www.google.com/"), &d);
2510 SpdyURLRequestContext* spdy_url_request_context =
2511 new SpdyURLRequestContext();
2512 r.set_context(spdy_url_request_context);
2513 spdy_url_request_context->socket_factory().
2514 AddSocketDataProvider(data.get());
2515 spdy_url_request_context->socket_factory().
2516 AddSocketDataProvider(data2.get());
2518 d.set_quit_on_redirect(true);
2519 r.Start();
2520 MessageLoop::current()->Run();
2522 EXPECT_EQ(1, d.received_redirect_count());
2524 r.FollowDeferredRedirect();
2525 MessageLoop::current()->Run();
2526 EXPECT_EQ(1, d.response_started_count());
2527 EXPECT_FALSE(d.received_data_before_response());
2528 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r.status().status());
2529 std::string contents("hello!");
2530 EXPECT_EQ(contents, d.data_received());
2532 EXPECT_TRUE(data->at_read_eof());
2533 EXPECT_TRUE(data->at_write_eof());
2534 EXPECT_TRUE(data2->at_read_eof());
2535 EXPECT_TRUE(data2->at_write_eof());
2538 // Detect response with upper case headers and reset the stream.
2539 TEST_P(SpdyNetworkTransactionTest, UpperCaseHeaders) {
2540 scoped_ptr<spdy::SpdyFrame>
2541 syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2542 scoped_ptr<spdy::SpdyFrame>
2543 rst(ConstructSpdyRstStream(1, spdy::PROTOCOL_ERROR));
2544 MockWrite writes[] = {
2545 CreateMockWrite(*syn, 0),
2546 CreateMockWrite(*rst, 2),
2549 const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
2550 scoped_ptr<spdy::SpdyFrame>
2551 reply(ConstructSpdyGetSynReply(kExtraHeaders, 1, 1));
2552 MockRead reads[] = {
2553 CreateMockRead(*reply, 1),
2554 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2557 HttpResponseInfo response;
2558 HttpResponseInfo response2;
2559 scoped_ptr<OrderedSocketData> data(new OrderedSocketData(
2560 reads,
2561 arraysize(reads),
2562 writes,
2563 arraysize(writes)));
2564 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2565 BoundNetLog(), GetParam());
2566 helper.RunToCompletion(data.get());
2567 TransactionHelperResult out = helper.output();
2568 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2571 // Detect response with upper case headers in a HEADERS frame and reset the
2572 // stream.
2573 TEST_P(SpdyNetworkTransactionTest, UpperCaseHeadersInHeadersFrame) {
2574 scoped_ptr<spdy::SpdyFrame>
2575 syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2576 scoped_ptr<spdy::SpdyFrame>
2577 rst(ConstructSpdyRstStream(1, spdy::PROTOCOL_ERROR));
2578 MockWrite writes[] = {
2579 CreateMockWrite(*syn, 0),
2580 CreateMockWrite(*rst, 2),
2583 static const char* const kInitialHeaders[] = {
2584 "status", "200 OK",
2585 "version", "HTTP/1.1"
2587 static const char* const kLateHeaders[] = {
2588 "X-UpperCase", "yes",
2590 scoped_ptr<spdy::SpdyFrame>
2591 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
2592 arraysize(kInitialHeaders) / 2,
2593 false,
2595 LOWEST,
2596 spdy::SYN_REPLY,
2597 spdy::CONTROL_FLAG_NONE,
2598 NULL,
2600 0));
2601 scoped_ptr<spdy::SpdyFrame>
2602 stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
2603 arraysize(kLateHeaders) / 2,
2604 false,
2606 LOWEST,
2607 spdy::HEADERS,
2608 spdy::CONTROL_FLAG_NONE,
2609 NULL,
2611 0));
2612 scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, true));
2613 MockRead reads[] = {
2614 CreateMockRead(*stream1_reply),
2615 CreateMockRead(*stream1_headers),
2616 CreateMockRead(*stream1_body),
2617 MockRead(ASYNC, 0, 0) // EOF
2620 scoped_ptr<DelayedSocketData> data(
2621 new DelayedSocketData(1, reads, arraysize(reads),
2622 writes, arraysize(writes)));
2623 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2624 BoundNetLog(), GetParam());
2625 helper.RunToCompletion(data.get());
2626 TransactionHelperResult out = helper.output();
2627 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
2630 // Detect push stream with upper case headers and reset the stream.
2631 TEST_P(SpdyNetworkTransactionTest, UpperCaseHeadersOnPush) {
2632 scoped_ptr<spdy::SpdyFrame>
2633 syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2634 scoped_ptr<spdy::SpdyFrame>
2635 rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR));
2636 MockWrite writes[] = {
2637 CreateMockWrite(*syn, 0),
2638 CreateMockWrite(*rst, 2),
2641 scoped_ptr<spdy::SpdyFrame>
2642 reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2643 const char* const extra_headers[] = {"X-UpperCase", "yes"};
2644 scoped_ptr<spdy::SpdyFrame>
2645 push(ConstructSpdyPush(extra_headers, 1, 2, 1));
2646 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2647 MockRead reads[] = {
2648 CreateMockRead(*reply, 1),
2649 CreateMockRead(*push, 1),
2650 CreateMockRead(*body, 1),
2651 MockRead(ASYNC, ERR_IO_PENDING, 3), // Force a pause
2654 HttpResponseInfo response;
2655 HttpResponseInfo response2;
2656 scoped_ptr<OrderedSocketData> data(new OrderedSocketData(
2657 reads,
2658 arraysize(reads),
2659 writes,
2660 arraysize(writes)));
2661 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2662 BoundNetLog(), GetParam());
2663 helper.RunToCompletion(data.get());
2664 TransactionHelperResult out = helper.output();
2665 EXPECT_EQ(OK, out.rv);
2668 // Send a spdy request to www.google.com. Get a pushed stream that redirects to
2669 // www.foo.com.
2670 TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
2671 // These are headers which the net::URLRequest tacks on.
2672 const char* const kExtraHeaders[] = {
2673 "accept-encoding",
2674 "gzip,deflate",
2676 const SpdyHeaderInfo kSynStartHeader = MakeSpdyHeader(spdy::SYN_STREAM);
2677 const char* const kStandardGetHeaders[] = {
2678 "host",
2679 "www.google.com",
2680 "method",
2681 "GET",
2682 "scheme",
2683 "http",
2684 "url",
2685 "/",
2686 "user-agent",
2688 "version",
2689 "HTTP/1.1"
2692 // Setup writes/reads to www.google.com
2693 scoped_ptr<spdy::SpdyFrame> req(
2694 ConstructSpdyPacket(kSynStartHeader,
2695 kExtraHeaders,
2696 arraysize(kExtraHeaders) / 2,
2697 kStandardGetHeaders,
2698 arraysize(kStandardGetHeaders) / 2));
2699 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2700 scoped_ptr<spdy::SpdyFrame> rep(
2701 ConstructSpdyPush(NULL,
2705 "http://www.google.com/foo.dat",
2706 "301 Moved Permanently",
2707 "http://www.foo.com/index.php"));
2708 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2709 scoped_ptr<spdy::SpdyFrame> rst(ConstructSpdyRstStream(2, spdy::CANCEL));
2710 MockWrite writes[] = {
2711 CreateMockWrite(*req, 1),
2712 CreateMockWrite(*rst, 6),
2714 MockRead reads[] = {
2715 CreateMockRead(*resp, 2),
2716 CreateMockRead(*rep, 3),
2717 CreateMockRead(*body, 4),
2718 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
2719 MockRead(ASYNC, 0, 0, 7) // EOF
2722 // Setup writes/reads to www.foo.com
2723 const char* const kStandardGetHeaders2[] = {
2724 "host",
2725 "www.foo.com",
2726 "method",
2727 "GET",
2728 "scheme",
2729 "http",
2730 "url",
2731 "/index.php",
2732 "user-agent",
2734 "version",
2735 "HTTP/1.1"
2737 scoped_ptr<spdy::SpdyFrame> req2(
2738 ConstructSpdyPacket(kSynStartHeader,
2739 kExtraHeaders,
2740 arraysize(kExtraHeaders) / 2,
2741 kStandardGetHeaders2,
2742 arraysize(kStandardGetHeaders2) / 2));
2743 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
2744 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
2745 MockWrite writes2[] = {
2746 CreateMockWrite(*req2, 1),
2748 MockRead reads2[] = {
2749 CreateMockRead(*resp2, 2),
2750 CreateMockRead(*body2, 3),
2751 MockRead(ASYNC, 0, 0, 5) // EOF
2753 scoped_ptr<OrderedSocketData> data(
2754 new OrderedSocketData(reads, arraysize(reads),
2755 writes, arraysize(writes)));
2756 scoped_ptr<OrderedSocketData> data2(
2757 new OrderedSocketData(reads2, arraysize(reads2),
2758 writes2, arraysize(writes2)));
2760 // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2761 HttpStreamFactory::set_force_spdy_over_ssl(false);
2762 HttpStreamFactory::set_force_spdy_always(true);
2763 TestDelegate d;
2764 TestDelegate d2;
2765 scoped_refptr<SpdyURLRequestContext> spdy_url_request_context(
2766 new SpdyURLRequestContext());
2768 net::URLRequest r(GURL("http://www.google.com/"), &d);
2769 r.set_context(spdy_url_request_context);
2770 spdy_url_request_context->socket_factory().
2771 AddSocketDataProvider(data.get());
2773 r.Start();
2774 MessageLoop::current()->Run();
2776 EXPECT_EQ(0, d.received_redirect_count());
2777 std::string contents("hello!");
2778 EXPECT_EQ(contents, d.data_received());
2780 net::URLRequest r2(GURL("http://www.google.com/foo.dat"), &d2);
2781 r2.set_context(spdy_url_request_context);
2782 spdy_url_request_context->socket_factory().
2783 AddSocketDataProvider(data2.get());
2785 d2.set_quit_on_redirect(true);
2786 r2.Start();
2787 MessageLoop::current()->Run();
2788 EXPECT_EQ(1, d2.received_redirect_count());
2790 r2.FollowDeferredRedirect();
2791 MessageLoop::current()->Run();
2792 EXPECT_EQ(1, d2.response_started_count());
2793 EXPECT_FALSE(d2.received_data_before_response());
2794 EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2.status().status());
2795 std::string contents2("hello!");
2796 EXPECT_EQ(contents2, d2.data_received());
2798 data->CompleteRead();
2799 data2->CompleteRead();
2800 EXPECT_TRUE(data->at_read_eof());
2801 EXPECT_TRUE(data->at_write_eof());
2802 EXPECT_TRUE(data2->at_read_eof());
2803 EXPECT_TRUE(data2->at_write_eof());
2806 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
2807 static const unsigned char kPushBodyFrame[] = {
2808 0x00, 0x00, 0x00, 0x02, // header, ID
2809 0x01, 0x00, 0x00, 0x06, // FIN, length
2810 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2812 scoped_ptr<spdy::SpdyFrame>
2813 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2814 scoped_ptr<spdy::SpdyFrame>
2815 stream1_body(ConstructSpdyBodyFrame(1, true));
2816 MockWrite writes[] = {
2817 CreateMockWrite(*stream1_syn, 1),
2820 scoped_ptr<spdy::SpdyFrame>
2821 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2822 scoped_ptr<spdy::SpdyFrame>
2823 stream2_syn(ConstructSpdyPush(NULL,
2827 "http://www.google.com/foo.dat"));
2828 MockRead reads[] = {
2829 CreateMockRead(*stream1_reply, 2),
2830 CreateMockRead(*stream2_syn, 3),
2831 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2832 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
2833 arraysize(kPushBodyFrame), 5),
2834 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2837 HttpResponseInfo response;
2838 HttpResponseInfo response2;
2839 std::string expected_push_result("pushed");
2840 scoped_ptr<OrderedSocketData> data(new OrderedSocketData(
2841 reads,
2842 arraysize(reads),
2843 writes,
2844 arraysize(writes)));
2845 RunServerPushTest(data.get(),
2846 &response,
2847 &response2,
2848 expected_push_result);
2850 // Verify the SYN_REPLY.
2851 EXPECT_TRUE(response.headers != NULL);
2852 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2854 // Verify the pushed stream.
2855 EXPECT_TRUE(response2.headers != NULL);
2856 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2859 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
2860 static const unsigned char kPushBodyFrame[] = {
2861 0x00, 0x00, 0x00, 0x02, // header, ID
2862 0x01, 0x00, 0x00, 0x06, // FIN, length
2863 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2865 scoped_ptr<spdy::SpdyFrame>
2866 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2867 MockWrite writes[] = {
2868 CreateMockWrite(*stream1_syn, 1),
2871 scoped_ptr<spdy::SpdyFrame>
2872 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2873 scoped_ptr<spdy::SpdyFrame>
2874 stream2_syn(ConstructSpdyPush(NULL,
2878 "http://www.google.com/foo.dat"));
2879 scoped_ptr<spdy::SpdyFrame>
2880 stream1_body(ConstructSpdyBodyFrame(1, true));
2881 MockRead reads[] = {
2882 CreateMockRead(*stream1_reply, 2),
2883 CreateMockRead(*stream2_syn, 3),
2884 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
2885 arraysize(kPushBodyFrame), 5),
2886 CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2887 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2890 HttpResponseInfo response;
2891 HttpResponseInfo response2;
2892 std::string expected_push_result("pushed");
2893 scoped_ptr<OrderedSocketData> data(new OrderedSocketData(
2894 reads,
2895 arraysize(reads),
2896 writes,
2897 arraysize(writes)));
2898 RunServerPushTest(data.get(),
2899 &response,
2900 &response2,
2901 expected_push_result);
2903 // Verify the SYN_REPLY.
2904 EXPECT_TRUE(response.headers != NULL);
2905 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2907 // Verify the pushed stream.
2908 EXPECT_TRUE(response2.headers != NULL);
2909 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2912 TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
2913 scoped_ptr<spdy::SpdyFrame>
2914 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2915 scoped_ptr<spdy::SpdyFrame>
2916 stream1_body(ConstructSpdyBodyFrame(1, true));
2917 MockWrite writes[] = {
2918 CreateMockWrite(*stream1_syn, 1),
2921 scoped_ptr<spdy::SpdyFrame>
2922 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2923 scoped_ptr<spdy::SpdyFrame>
2924 stream2_syn(ConstructSpdyPush(NULL,
2928 "http://www.google.com/foo.dat"));
2929 scoped_ptr<spdy::SpdyFrame>
2930 stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR));
2931 MockRead reads[] = {
2932 CreateMockRead(*stream1_reply, 2),
2933 CreateMockRead(*stream2_syn, 3),
2934 CreateMockRead(*stream2_rst, 4),
2935 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2936 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
2939 scoped_ptr<OrderedSocketData> data(
2940 new OrderedSocketData(reads, arraysize(reads),
2941 writes, arraysize(writes)));
2942 NormalSpdyTransactionHelper helper(CreateGetRequest(),
2943 BoundNetLog(), GetParam());
2945 helper.RunPreTestSetup();
2946 helper.AddData(data.get());
2948 HttpNetworkTransaction* trans = helper.trans();
2950 // Start the transaction with basic parameters.
2951 TestCompletionCallback callback;
2952 int rv = trans->Start(
2953 &CreateGetRequest(), callback.callback(), BoundNetLog());
2954 EXPECT_EQ(ERR_IO_PENDING, rv);
2955 rv = callback.WaitForResult();
2956 EXPECT_EQ(OK, rv);
2958 // Verify that we consumed all test data.
2959 EXPECT_TRUE(data->at_read_eof()) << "Read count: "
2960 << data->read_count()
2961 << " Read index: "
2962 << data->read_index();
2963 EXPECT_TRUE(data->at_write_eof()) << "Write count: "
2964 << data->write_count()
2965 << " Write index: "
2966 << data->write_index();
2968 // Verify the SYN_REPLY.
2969 HttpResponseInfo response = *trans->GetResponseInfo();
2970 EXPECT_TRUE(response.headers != NULL);
2971 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
2974 TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
2975 // Verify that we don't leak streams and that we properly send a reset
2976 // if the server pushes the same stream twice.
2977 static const unsigned char kPushBodyFrame[] = {
2978 0x00, 0x00, 0x00, 0x02, // header, ID
2979 0x01, 0x00, 0x00, 0x06, // FIN, length
2980 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
2983 scoped_ptr<spdy::SpdyFrame>
2984 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
2985 scoped_ptr<spdy::SpdyFrame>
2986 stream1_body(ConstructSpdyBodyFrame(1, true));
2987 scoped_ptr<spdy::SpdyFrame>
2988 stream3_rst(ConstructSpdyRstStream(4, spdy::PROTOCOL_ERROR));
2989 MockWrite writes[] = {
2990 CreateMockWrite(*stream1_syn, 1),
2991 CreateMockWrite(*stream3_rst, 5),
2994 scoped_ptr<spdy::SpdyFrame>
2995 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
2996 scoped_ptr<spdy::SpdyFrame>
2997 stream2_syn(ConstructSpdyPush(NULL,
3001 "http://www.google.com/foo.dat"));
3002 scoped_ptr<spdy::SpdyFrame>
3003 stream3_syn(ConstructSpdyPush(NULL,
3007 "http://www.google.com/foo.dat"));
3008 MockRead reads[] = {
3009 CreateMockRead(*stream1_reply, 2),
3010 CreateMockRead(*stream2_syn, 3),
3011 CreateMockRead(*stream3_syn, 4),
3012 CreateMockRead(*stream1_body, 6, SYNCHRONOUS),
3013 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
3014 arraysize(kPushBodyFrame), 7),
3015 MockRead(ASYNC, ERR_IO_PENDING, 8), // Force a pause
3018 HttpResponseInfo response;
3019 HttpResponseInfo response2;
3020 std::string expected_push_result("pushed");
3021 scoped_ptr<OrderedSocketData> data(new OrderedSocketData(
3022 reads,
3023 arraysize(reads),
3024 writes,
3025 arraysize(writes)));
3026 RunServerPushTest(data.get(),
3027 &response,
3028 &response2,
3029 expected_push_result);
3031 // Verify the SYN_REPLY.
3032 EXPECT_TRUE(response.headers != NULL);
3033 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3035 // Verify the pushed stream.
3036 EXPECT_TRUE(response2.headers != NULL);
3037 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3040 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
3041 static const unsigned char kPushBodyFrame1[] = {
3042 0x00, 0x00, 0x00, 0x02, // header, ID
3043 0x01, 0x00, 0x00, 0x1F, // FIN, length
3044 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3046 static const char kPushBodyFrame2[] = " my darling";
3047 static const char kPushBodyFrame3[] = " hello";
3048 static const char kPushBodyFrame4[] = " my baby";
3050 scoped_ptr<spdy::SpdyFrame>
3051 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3052 scoped_ptr<spdy::SpdyFrame>
3053 stream1_body(ConstructSpdyBodyFrame(1, true));
3054 MockWrite writes[] = {
3055 CreateMockWrite(*stream1_syn, 1),
3058 scoped_ptr<spdy::SpdyFrame>
3059 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3060 scoped_ptr<spdy::SpdyFrame>
3061 stream2_syn(ConstructSpdyPush(NULL,
3065 "http://www.google.com/foo.dat"));
3066 MockRead reads[] = {
3067 CreateMockRead(*stream1_reply, 2),
3068 CreateMockRead(*stream2_syn, 3),
3069 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame1),
3070 arraysize(kPushBodyFrame1), 4),
3071 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame2),
3072 arraysize(kPushBodyFrame2) - 1, 5),
3073 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame3),
3074 arraysize(kPushBodyFrame3) - 1, 6),
3075 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame4),
3076 arraysize(kPushBodyFrame4) - 1, 7),
3077 CreateMockRead(*stream1_body, 8, SYNCHRONOUS),
3078 MockRead(ASYNC, ERR_IO_PENDING, 9), // Force a pause
3081 HttpResponseInfo response;
3082 HttpResponseInfo response2;
3083 std::string expected_push_result("pushed my darling hello my baby");
3084 scoped_ptr<OrderedSocketData> data(new OrderedSocketData(
3085 reads,
3086 arraysize(reads),
3087 writes,
3088 arraysize(writes)));
3089 RunServerPushTest(data.get(),
3090 &response,
3091 &response2,
3092 expected_push_result);
3094 // Verify the SYN_REPLY.
3095 EXPECT_TRUE(response.headers != NULL);
3096 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3098 // Verify the pushed stream.
3099 EXPECT_TRUE(response2.headers != NULL);
3100 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3103 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
3104 SpdySession::set_use_flow_control(SpdySession::kDisableFlowControl);
3106 static const unsigned char kPushBodyFrame1[] = {
3107 0x00, 0x00, 0x00, 0x02, // header, ID
3108 0x01, 0x00, 0x00, 0x1F, // FIN, length
3109 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
3111 static const char kPushBodyFrame2[] = " my darling";
3112 static const char kPushBodyFrame3[] = " hello";
3113 static const char kPushBodyFrame4[] = " my baby";
3115 scoped_ptr<spdy::SpdyFrame>
3116 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3117 scoped_ptr<spdy::SpdyFrame>
3118 stream1_body(ConstructSpdyBodyFrame(1, true));
3119 MockWrite writes[] = {
3120 CreateMockWrite(*stream1_syn, 1),
3123 scoped_ptr<spdy::SpdyFrame>
3124 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3125 scoped_ptr<spdy::SpdyFrame>
3126 stream2_syn(ConstructSpdyPush(NULL,
3130 "http://www.google.com/foo.dat"));
3131 MockRead reads[] = {
3132 CreateMockRead(*stream1_reply, 2),
3133 CreateMockRead(*stream2_syn, 3),
3134 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame1),
3135 arraysize(kPushBodyFrame1), 4),
3136 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame2),
3137 arraysize(kPushBodyFrame2) - 1, 5),
3138 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
3139 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame3),
3140 arraysize(kPushBodyFrame3) - 1, 7),
3141 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame4),
3142 arraysize(kPushBodyFrame4) - 1, 8),
3143 CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS),
3144 MockRead(ASYNC, ERR_IO_PENDING, 10) // Force a pause.
3147 HttpResponseInfo response;
3148 HttpResponseInfo response2;
3149 std::string expected_push_result("pushed my darling hello my baby");
3150 scoped_ptr<OrderedSocketData> data(new OrderedSocketData(
3151 reads,
3152 arraysize(reads),
3153 writes,
3154 arraysize(writes)));
3155 RunServerPushTest(data.get(),
3156 &response,
3157 &response2,
3158 expected_push_result);
3160 // Verify the SYN_REPLY.
3161 EXPECT_TRUE(response.headers != NULL);
3162 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3164 // Verify the pushed stream.
3165 EXPECT_TRUE(response2.headers != NULL);
3166 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
3168 SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN);
3171 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
3172 scoped_ptr<spdy::SpdyFrame>
3173 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3174 scoped_ptr<spdy::SpdyFrame>
3175 stream1_body(ConstructSpdyBodyFrame(1, true));
3176 scoped_ptr<spdy::SpdyFrame>
3177 stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_STREAM));
3178 MockWrite writes[] = {
3179 CreateMockWrite(*stream1_syn, 1),
3180 CreateMockWrite(*stream2_rst, 4),
3183 scoped_ptr<spdy::SpdyFrame>
3184 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3185 scoped_ptr<spdy::SpdyFrame>
3186 stream2_syn(ConstructSpdyPush(NULL,
3190 "http://www.google.com/foo.dat"));
3191 MockRead reads[] = {
3192 CreateMockRead(*stream1_reply, 2),
3193 CreateMockRead(*stream2_syn, 3),
3194 CreateMockRead(*stream1_body, 4),
3195 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3198 scoped_ptr<OrderedSocketData> data(
3199 new OrderedSocketData(reads, arraysize(reads),
3200 writes, arraysize(writes)));
3201 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3202 BoundNetLog(), GetParam());
3204 helper.RunPreTestSetup();
3205 helper.AddData(data.get());
3207 HttpNetworkTransaction* trans = helper.trans();
3209 // Start the transaction with basic parameters.
3210 TestCompletionCallback callback;
3211 int rv = trans->Start(
3212 &CreateGetRequest(), callback.callback(), BoundNetLog());
3213 EXPECT_EQ(ERR_IO_PENDING, rv);
3214 rv = callback.WaitForResult();
3215 EXPECT_EQ(OK, rv);
3217 // Verify that we consumed all test data.
3218 EXPECT_TRUE(data->at_read_eof()) << "Read count: "
3219 << data->read_count()
3220 << " Read index: "
3221 << data->read_index();
3222 EXPECT_TRUE(data->at_write_eof()) << "Write count: "
3223 << data->write_count()
3224 << " Write index: "
3225 << data->write_index();
3227 // Verify the SYN_REPLY.
3228 HttpResponseInfo response = *trans->GetResponseInfo();
3229 EXPECT_TRUE(response.headers != NULL);
3230 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3233 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
3234 scoped_ptr<spdy::SpdyFrame>
3235 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3236 scoped_ptr<spdy::SpdyFrame>
3237 stream1_body(ConstructSpdyBodyFrame(1, true));
3238 scoped_ptr<spdy::SpdyFrame>
3239 stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_ASSOCIATED_STREAM));
3240 MockWrite writes[] = {
3241 CreateMockWrite(*stream1_syn, 1),
3242 CreateMockWrite(*stream2_rst, 4),
3245 scoped_ptr<spdy::SpdyFrame>
3246 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3247 scoped_ptr<spdy::SpdyFrame>
3248 stream2_syn(ConstructSpdyPush(NULL,
3252 "http://www.google.com/foo.dat"));
3253 MockRead reads[] = {
3254 CreateMockRead(*stream1_reply, 2),
3255 CreateMockRead(*stream2_syn, 3),
3256 CreateMockRead(*stream1_body, 4),
3257 MockRead(ASYNC, ERR_IO_PENDING, 5), // Force a pause
3260 scoped_ptr<OrderedSocketData> data(
3261 new OrderedSocketData(reads, arraysize(reads),
3262 writes, arraysize(writes)));
3263 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3264 BoundNetLog(), GetParam());
3266 helper.RunPreTestSetup();
3267 helper.AddData(data.get());
3269 HttpNetworkTransaction* trans = helper.trans();
3271 // Start the transaction with basic parameters.
3272 TestCompletionCallback callback;
3273 int rv = trans->Start(
3274 &CreateGetRequest(), callback.callback(), BoundNetLog());
3275 EXPECT_EQ(ERR_IO_PENDING, rv);
3276 rv = callback.WaitForResult();
3277 EXPECT_EQ(OK, rv);
3279 // Verify that we consumed all test data.
3280 EXPECT_TRUE(data->at_read_eof()) << "Read count: "
3281 << data->read_count()
3282 << " Read index: "
3283 << data->read_index();
3284 EXPECT_TRUE(data->at_write_eof()) << "Write count: "
3285 << data->write_count()
3286 << " Write index: "
3287 << data->write_index();
3289 // Verify the SYN_REPLY.
3290 HttpResponseInfo response = *trans->GetResponseInfo();
3291 EXPECT_TRUE(response.headers != NULL);
3292 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3295 TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
3296 scoped_ptr<spdy::SpdyFrame>
3297 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3298 scoped_ptr<spdy::SpdyFrame>
3299 stream1_body(ConstructSpdyBodyFrame(1, true));
3300 scoped_ptr<spdy::SpdyFrame>
3301 stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR));
3302 MockWrite writes[] = {
3303 CreateMockWrite(*stream1_syn, 1),
3304 CreateMockWrite(*stream2_rst, 4),
3307 scoped_ptr<spdy::SpdyFrame>
3308 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
3309 scoped_ptr<spdy::SpdyFrame>
3310 stream2_syn(ConstructSpdyPush(NULL, 0, 2, 1));
3311 MockRead reads[] = {
3312 CreateMockRead(*stream1_reply, 2),
3313 CreateMockRead(*stream2_syn, 3),
3314 CreateMockRead(*stream1_body, 4),
3315 MockRead(ASYNC, ERR_IO_PENDING, 5) // Force a pause
3318 scoped_ptr<OrderedSocketData> data(
3319 new OrderedSocketData(reads, arraysize(reads),
3320 writes, arraysize(writes)));
3321 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3322 BoundNetLog(), GetParam());
3324 helper.RunPreTestSetup();
3325 helper.AddData(data.get());
3327 HttpNetworkTransaction* trans = helper.trans();
3329 // Start the transaction with basic parameters.
3330 TestCompletionCallback callback;
3331 int rv = trans->Start(
3332 &CreateGetRequest(), callback.callback(), BoundNetLog());
3333 EXPECT_EQ(ERR_IO_PENDING, rv);
3334 rv = callback.WaitForResult();
3335 EXPECT_EQ(OK, rv);
3336 // Verify that we consumed all test data.
3337 EXPECT_TRUE(data->at_read_eof()) << "Read count: "
3338 << data->read_count()
3339 << " Read index: "
3340 << data->read_index();
3341 EXPECT_TRUE(data->at_write_eof()) << "Write count: "
3342 << data->write_count()
3343 << " Write index: "
3344 << data->write_index();
3346 // Verify the SYN_REPLY.
3347 HttpResponseInfo response = *trans->GetResponseInfo();
3348 EXPECT_TRUE(response.headers != NULL);
3349 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
3352 // Verify that various SynReply headers parse correctly through the
3353 // HTTP layer.
3354 TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
3355 struct SynReplyHeadersTests {
3356 int num_headers;
3357 const char* extra_headers[5];
3358 const char* expected_headers;
3359 } test_cases[] = {
3360 // This uses a multi-valued cookie header.
3361 { 2,
3362 { "cookie", "val1",
3363 "cookie", "val2", // will get appended separated by NULL
3364 NULL
3366 "cookie: val1\n"
3367 "cookie: val2\n"
3368 "hello: bye\n"
3369 "status: 200\n"
3370 "version: HTTP/1.1\n"
3372 // This is the minimalist set of headers.
3373 { 0,
3374 { NULL },
3375 "hello: bye\n"
3376 "status: 200\n"
3377 "version: HTTP/1.1\n"
3379 // Headers with a comma separated list.
3380 { 1,
3381 { "cookie", "val1,val2",
3382 NULL
3384 "cookie: val1,val2\n"
3385 "hello: bye\n"
3386 "status: 200\n"
3387 "version: HTTP/1.1\n"
3391 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3392 scoped_ptr<spdy::SpdyFrame> req(
3393 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3394 MockWrite writes[] = { CreateMockWrite(*req) };
3396 scoped_ptr<spdy::SpdyFrame> resp(
3397 ConstructSpdyGetSynReply(test_cases[i].extra_headers,
3398 test_cases[i].num_headers,
3399 1));
3400 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3401 MockRead reads[] = {
3402 CreateMockRead(*resp),
3403 CreateMockRead(*body),
3404 MockRead(ASYNC, 0, 0) // EOF
3407 scoped_ptr<DelayedSocketData> data(
3408 new DelayedSocketData(1, reads, arraysize(reads),
3409 writes, arraysize(writes)));
3410 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3411 BoundNetLog(), GetParam());
3412 helper.RunToCompletion(data.get());
3413 TransactionHelperResult out = helper.output();
3415 EXPECT_EQ(OK, out.rv);
3416 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3417 EXPECT_EQ("hello!", out.response_data);
3419 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3420 EXPECT_TRUE(headers.get() != NULL);
3421 void* iter = NULL;
3422 std::string name, value, lines;
3423 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3424 lines.append(name);
3425 lines.append(": ");
3426 lines.append(value);
3427 lines.append("\n");
3429 EXPECT_EQ(std::string(test_cases[i].expected_headers), lines);
3433 // Verify that various SynReply headers parse vary fields correctly
3434 // through the HTTP layer, and the response matches the request.
3435 TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
3436 static const SpdyHeaderInfo syn_reply_info = {
3437 spdy::SYN_REPLY, // Syn Reply
3438 1, // Stream ID
3439 0, // Associated Stream ID
3440 net::ConvertRequestPriorityToSpdyPriority(LOWEST),
3441 // Priority
3442 spdy::CONTROL_FLAG_NONE, // Control Flags
3443 false, // Compressed
3444 spdy::INVALID, // Status
3445 NULL, // Data
3446 0, // Data Length
3447 spdy::DATA_FLAG_NONE // Data Flags
3449 // Modify the following data to change/add test cases:
3450 struct SynReplyTests {
3451 const SpdyHeaderInfo* syn_reply;
3452 bool vary_matches;
3453 int num_headers[2];
3454 const char* extra_headers[2][16];
3455 } test_cases[] = {
3456 // Test the case of a multi-valued cookie. When the value is delimited
3457 // with NUL characters, it needs to be unfolded into multiple headers.
3459 &syn_reply_info,
3460 true,
3461 { 1, 4 },
3462 { { "cookie", "val1,val2",
3463 NULL
3465 { "vary", "cookie",
3466 "status", "200",
3467 "url", "/index.php",
3468 "version", "HTTP/1.1",
3469 NULL
3472 }, { // Multiple vary fields.
3473 &syn_reply_info,
3474 true,
3475 { 2, 5 },
3476 { { "friend", "barney",
3477 "enemy", "snaggletooth",
3478 NULL
3480 { "vary", "friend",
3481 "vary", "enemy",
3482 "status", "200",
3483 "url", "/index.php",
3484 "version", "HTTP/1.1",
3485 NULL
3488 }, { // Test a '*' vary field.
3489 &syn_reply_info,
3490 false,
3491 { 1, 4 },
3492 { { "cookie", "val1,val2",
3493 NULL
3495 { "vary", "*",
3496 "status", "200",
3497 "url", "/index.php",
3498 "version", "HTTP/1.1",
3499 NULL
3502 }, { // Multiple comma-separated vary fields.
3503 &syn_reply_info,
3504 true,
3505 { 2, 4 },
3506 { { "friend", "barney",
3507 "enemy", "snaggletooth",
3508 NULL
3510 { "vary", "friend,enemy",
3511 "status", "200",
3512 "url", "/index.php",
3513 "version", "HTTP/1.1",
3514 NULL
3520 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3521 // Construct the request.
3522 scoped_ptr<spdy::SpdyFrame> frame_req(
3523 ConstructSpdyGet(test_cases[i].extra_headers[0],
3524 test_cases[i].num_headers[0],
3525 false, 1, LOWEST));
3527 MockWrite writes[] = {
3528 CreateMockWrite(*frame_req),
3531 // Construct the reply.
3532 scoped_ptr<spdy::SpdyFrame> frame_reply(
3533 ConstructSpdyPacket(*test_cases[i].syn_reply,
3534 test_cases[i].extra_headers[1],
3535 test_cases[i].num_headers[1],
3536 NULL,
3537 0));
3539 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3540 MockRead reads[] = {
3541 CreateMockRead(*frame_reply),
3542 CreateMockRead(*body),
3543 MockRead(ASYNC, 0, 0) // EOF
3546 // Attach the headers to the request.
3547 int header_count = test_cases[i].num_headers[0];
3549 HttpRequestInfo request = CreateGetRequest();
3550 for (int ct = 0; ct < header_count; ct++) {
3551 const char* header_key = test_cases[i].extra_headers[0][ct * 2];
3552 const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
3553 request.extra_headers.SetHeader(header_key, header_value);
3556 scoped_ptr<DelayedSocketData> data(
3557 new DelayedSocketData(1, reads, arraysize(reads),
3558 writes, arraysize(writes)));
3559 NormalSpdyTransactionHelper helper(request,
3560 BoundNetLog(), GetParam());
3561 helper.RunToCompletion(data.get());
3562 TransactionHelperResult out = helper.output();
3564 EXPECT_EQ(OK, out.rv) << i;
3565 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
3566 EXPECT_EQ("hello!", out.response_data) << i;
3568 // Test the response information.
3569 EXPECT_TRUE(out.response_info.response_time >
3570 out.response_info.request_time) << i;
3571 base::TimeDelta test_delay = out.response_info.response_time -
3572 out.response_info.request_time;
3573 base::TimeDelta min_expected_delay;
3574 min_expected_delay.FromMilliseconds(10);
3575 EXPECT_GT(test_delay.InMillisecondsF(),
3576 min_expected_delay.InMillisecondsF()) << i;
3577 EXPECT_EQ(out.response_info.vary_data.is_valid(),
3578 test_cases[i].vary_matches) << i;
3580 // Check the headers.
3581 scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
3582 ASSERT_TRUE(headers.get() != NULL) << i;
3583 void* iter = NULL;
3584 std::string name, value, lines;
3585 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
3586 lines.append(name);
3587 lines.append(": ");
3588 lines.append(value);
3589 lines.append("\n");
3592 // Construct the expected header reply string.
3593 char reply_buffer[256] = "";
3594 ConstructSpdyReplyString(test_cases[i].extra_headers[1],
3595 test_cases[i].num_headers[1],
3596 reply_buffer,
3597 256);
3599 EXPECT_EQ(std::string(reply_buffer), lines) << i;
3603 // Verify that we don't crash on invalid SynReply responses.
3604 TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
3605 const SpdyHeaderInfo kSynStartHeader = {
3606 spdy::SYN_REPLY, // Kind = SynReply
3607 1, // Stream ID
3608 0, // Associated stream ID
3609 net::ConvertRequestPriorityToSpdyPriority(LOWEST),
3610 // Priority
3611 spdy::CONTROL_FLAG_NONE, // Control Flags
3612 false, // Compressed
3613 spdy::INVALID, // Status
3614 NULL, // Data
3615 0, // Length
3616 spdy::DATA_FLAG_NONE // Data Flags
3619 struct InvalidSynReplyTests {
3620 int num_headers;
3621 const char* headers[10];
3622 } test_cases[] = {
3623 // SYN_REPLY missing status header
3624 { 4,
3625 { "cookie", "val1",
3626 "cookie", "val2",
3627 "url", "/index.php",
3628 "version", "HTTP/1.1",
3629 NULL
3632 // SYN_REPLY missing version header
3633 { 2,
3634 { "status", "200",
3635 "url", "/index.php",
3636 NULL
3639 // SYN_REPLY with no headers
3640 { 0, { NULL }, },
3643 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3644 scoped_ptr<spdy::SpdyFrame> req(
3645 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3646 MockWrite writes[] = {
3647 CreateMockWrite(*req),
3650 scoped_ptr<spdy::SpdyFrame> resp(
3651 ConstructSpdyPacket(kSynStartHeader,
3652 NULL, 0,
3653 test_cases[i].headers,
3654 test_cases[i].num_headers));
3655 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3656 MockRead reads[] = {
3657 CreateMockRead(*resp),
3658 CreateMockRead(*body),
3659 MockRead(ASYNC, 0, 0) // EOF
3662 scoped_ptr<DelayedSocketData> data(
3663 new DelayedSocketData(1, reads, arraysize(reads),
3664 writes, arraysize(writes)));
3665 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3666 BoundNetLog(), GetParam());
3667 helper.RunToCompletion(data.get());
3668 TransactionHelperResult out = helper.output();
3669 EXPECT_EQ(ERR_INCOMPLETE_SPDY_HEADERS, out.rv);
3673 // Verify that we don't crash on some corrupt frames.
3674 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
3675 // This is the length field that's too short.
3676 scoped_ptr<spdy::SpdyFrame> syn_reply_wrong_length(
3677 ConstructSpdyGetSynReply(NULL, 0, 1));
3678 syn_reply_wrong_length->set_length(syn_reply_wrong_length->length() - 4);
3680 struct SynReplyTests {
3681 const spdy::SpdyFrame* syn_reply;
3682 } test_cases[] = {
3683 { syn_reply_wrong_length.get(), },
3686 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
3687 scoped_ptr<spdy::SpdyFrame> req(
3688 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3689 MockWrite writes[] = {
3690 CreateMockWrite(*req),
3691 MockWrite(ASYNC, 0, 0) // EOF
3694 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3695 MockRead reads[] = {
3696 CreateMockRead(*test_cases[i].syn_reply),
3697 CreateMockRead(*body),
3698 MockRead(ASYNC, 0, 0) // EOF
3701 scoped_ptr<DelayedSocketData> data(
3702 new DelayedSocketData(1, reads, arraysize(reads),
3703 writes, arraysize(writes)));
3704 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3705 BoundNetLog(), GetParam());
3706 helper.RunToCompletion(data.get());
3707 TransactionHelperResult out = helper.output();
3708 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3712 // Test that we shutdown correctly on write errors.
3713 TEST_P(SpdyNetworkTransactionTest, WriteError) {
3714 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3715 MockWrite writes[] = {
3716 // We'll write 10 bytes successfully
3717 MockWrite(ASYNC, req->data(), 10),
3718 // Followed by ERROR!
3719 MockWrite(ASYNC, ERR_FAILED),
3722 scoped_ptr<DelayedSocketData> data(
3723 new DelayedSocketData(2, NULL, 0,
3724 writes, arraysize(writes)));
3725 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3726 BoundNetLog(), GetParam());
3727 helper.RunToCompletion(data.get());
3728 TransactionHelperResult out = helper.output();
3729 EXPECT_EQ(ERR_FAILED, out.rv);
3730 data->Reset();
3733 // Test that partial writes work.
3734 TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
3735 // Chop the SYN_STREAM frame into 5 chunks.
3736 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3737 const int kChunks = 5;
3738 scoped_array<MockWrite> writes(ChopWriteFrame(*req.get(), kChunks));
3740 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3741 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3742 MockRead reads[] = {
3743 CreateMockRead(*resp),
3744 CreateMockRead(*body),
3745 MockRead(ASYNC, 0, 0) // EOF
3748 scoped_ptr<DelayedSocketData> data(
3749 new DelayedSocketData(kChunks, reads, arraysize(reads),
3750 writes.get(), kChunks));
3751 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3752 BoundNetLog(), GetParam());
3753 helper.RunToCompletion(data.get());
3754 TransactionHelperResult out = helper.output();
3755 EXPECT_EQ(OK, out.rv);
3756 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3757 EXPECT_EQ("hello!", out.response_data);
3760 // In this test, we enable compression, but get a uncompressed SynReply from
3761 // the server. Verify that teardown is all clean.
3762 TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
3763 // For this test, we turn on the normal compression.
3764 EnableCompression(true);
3766 scoped_ptr<spdy::SpdyFrame> compressed(
3767 ConstructSpdyGet(NULL, 0, true, 1, LOWEST));
3768 scoped_ptr<spdy::SpdyFrame> rst(
3769 ConstructSpdyRstStream(1, spdy::PROTOCOL_ERROR));
3770 MockWrite writes[] = {
3771 CreateMockWrite(*compressed),
3774 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3775 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3776 MockRead reads[] = {
3777 CreateMockRead(*resp),
3780 scoped_ptr<DelayedSocketData> data(
3781 new DelayedSocketData(1, reads, arraysize(reads),
3782 writes, arraysize(writes)));
3783 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3784 BoundNetLog(), GetParam());
3785 helper.RunToCompletion(data.get());
3786 TransactionHelperResult out = helper.output();
3787 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
3788 data->Reset();
3790 EnableCompression(false);
3793 // Test that the NetLog contains good data for a simple GET request.
3794 TEST_P(SpdyNetworkTransactionTest, NetLog) {
3795 static const char* const kExtraHeaders[] = {
3796 "user-agent", "Chrome",
3798 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(kExtraHeaders, 1, false, 1,
3799 LOWEST));
3800 MockWrite writes[] = { CreateMockWrite(*req) };
3802 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3803 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
3804 MockRead reads[] = {
3805 CreateMockRead(*resp),
3806 CreateMockRead(*body),
3807 MockRead(ASYNC, 0, 0) // EOF
3810 net::CapturingBoundNetLog log(net::CapturingNetLog::kUnbounded);
3812 scoped_ptr<DelayedSocketData> data(
3813 new DelayedSocketData(1, reads, arraysize(reads),
3814 writes, arraysize(writes)));
3815 NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
3816 log.bound(), GetParam());
3817 helper.RunToCompletion(data.get());
3818 TransactionHelperResult out = helper.output();
3819 EXPECT_EQ(OK, out.rv);
3820 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3821 EXPECT_EQ("hello!", out.response_data);
3823 // Check that the NetLog was filled reasonably.
3824 // This test is intentionally non-specific about the exact ordering of the
3825 // log; instead we just check to make sure that certain events exist, and that
3826 // they are in the right order.
3827 net::CapturingNetLog::EntryList entries;
3828 log.GetEntries(&entries);
3830 EXPECT_LT(0u, entries.size());
3831 int pos = 0;
3832 pos = net::ExpectLogContainsSomewhere(entries, 0,
3833 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3834 net::NetLog::PHASE_BEGIN);
3835 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3836 net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
3837 net::NetLog::PHASE_END);
3838 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3839 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3840 net::NetLog::PHASE_BEGIN);
3841 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3842 net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
3843 net::NetLog::PHASE_END);
3844 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3845 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3846 net::NetLog::PHASE_BEGIN);
3847 pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
3848 net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
3849 net::NetLog::PHASE_END);
3851 // Check that we logged all the headers correctly
3852 pos = net::ExpectLogContainsSomewhere(
3853 entries, 0,
3854 net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
3855 net::NetLog::PHASE_NONE);
3856 CapturingNetLog::Entry entry = entries[pos];
3857 NetLogSpdySynParameter* request_params =
3858 static_cast<NetLogSpdySynParameter*>(entry.extra_parameters.get());
3859 spdy::SpdyHeaderBlock* headers =
3860 request_params->GetHeaders().get();
3862 spdy::SpdyHeaderBlock expected;
3863 expected["host"] = "www.google.com";
3864 expected["url"] = "/";
3865 expected["scheme"] = "http";
3866 expected["version"] = "HTTP/1.1";
3867 expected["method"] = "GET";
3868 expected["user-agent"] = "Chrome";
3869 EXPECT_EQ(expected.size(), headers->size());
3870 spdy::SpdyHeaderBlock::const_iterator end = expected.end();
3871 for (spdy::SpdyHeaderBlock::const_iterator it = expected.begin();
3872 it != end;
3873 ++it) {
3874 EXPECT_EQ(it->second, (*headers)[it->first]);
3878 // Since we buffer the IO from the stream to the renderer, this test verifies
3879 // that when we read out the maximum amount of data (e.g. we received 50 bytes
3880 // on the network, but issued a Read for only 5 of those bytes) that the data
3881 // flow still works correctly.
3882 TEST_P(SpdyNetworkTransactionTest, BufferFull) {
3883 SpdySession::set_use_flow_control(SpdySession::kDisableFlowControl);
3885 spdy::SpdyFramer framer;
3887 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3888 MockWrite writes[] = { CreateMockWrite(*req) };
3890 // 2 data frames in a single read.
3891 scoped_ptr<spdy::SpdyFrame> data_frame_1(
3892 framer.CreateDataFrame(1, "goodby", 6, spdy::DATA_FLAG_NONE));
3893 scoped_ptr<spdy::SpdyFrame> data_frame_2(
3894 framer.CreateDataFrame(1, "e worl", 6, spdy::DATA_FLAG_NONE));
3895 const spdy::SpdyFrame* data_frames[2] = {
3896 data_frame_1.get(),
3897 data_frame_2.get(),
3899 char combined_data_frames[100];
3900 int combined_data_frames_len =
3901 CombineFrames(data_frames, arraysize(data_frames),
3902 combined_data_frames, arraysize(combined_data_frames));
3903 scoped_ptr<spdy::SpdyFrame> last_frame(
3904 framer.CreateDataFrame(1, "d", 1, spdy::DATA_FLAG_FIN));
3906 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
3907 MockRead reads[] = {
3908 CreateMockRead(*resp),
3909 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3910 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
3911 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
3912 CreateMockRead(*last_frame),
3913 MockRead(ASYNC, 0, 0) // EOF
3916 scoped_ptr<DelayedSocketData> data(
3917 new DelayedSocketData(1, reads, arraysize(reads),
3918 writes, arraysize(writes)));
3921 TestCompletionCallback callback;
3923 NormalSpdyTransactionHelper helper(CreateGetRequest(),
3924 BoundNetLog(), GetParam());
3925 helper.RunPreTestSetup();
3926 helper.AddData(data.get());
3927 HttpNetworkTransaction* trans = helper.trans();
3928 int rv = trans->Start(
3929 &CreateGetRequest(), callback.callback(), BoundNetLog());
3930 EXPECT_EQ(ERR_IO_PENDING, rv);
3932 TransactionHelperResult out = helper.output();
3933 out.rv = callback.WaitForResult();
3934 EXPECT_EQ(out.rv, OK);
3936 const HttpResponseInfo* response = trans->GetResponseInfo();
3937 EXPECT_TRUE(response->headers != NULL);
3938 EXPECT_TRUE(response->was_fetched_via_spdy);
3939 out.status_line = response->headers->GetStatusLine();
3940 out.response_info = *response; // Make a copy so we can verify.
3942 // Read Data
3943 TestCompletionCallback read_callback;
3945 std::string content;
3946 do {
3947 // Read small chunks at a time.
3948 const int kSmallReadSize = 3;
3949 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3950 rv = trans->Read(buf, kSmallReadSize, read_callback.callback());
3951 if (rv == net::ERR_IO_PENDING) {
3952 data->CompleteRead();
3953 rv = read_callback.WaitForResult();
3955 if (rv > 0) {
3956 content.append(buf->data(), rv);
3957 } else if (rv < 0) {
3958 NOTREACHED();
3960 } while (rv > 0);
3962 out.response_data.swap(content);
3964 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
3965 // MockClientSocketFactory) are still alive.
3966 MessageLoop::current()->RunAllPending();
3968 // Verify that we consumed all test data.
3969 helper.VerifyDataConsumed();
3971 EXPECT_EQ(OK, out.rv);
3972 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
3973 EXPECT_EQ("goodbye world", out.response_data);
3975 SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN);
3978 // Verify that basic buffering works; when multiple data frames arrive
3979 // at the same time, ensure that we don't notify a read completion for
3980 // each data frame individually.
3981 TEST_P(SpdyNetworkTransactionTest, Buffering) {
3982 SpdySession::set_use_flow_control(SpdySession::kDisableFlowControl);
3984 spdy::SpdyFramer framer;
3986 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
3987 MockWrite writes[] = { CreateMockWrite(*req) };
3989 // 4 data frames in a single read.
3990 scoped_ptr<spdy::SpdyFrame> data_frame(
3991 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
3992 scoped_ptr<spdy::SpdyFrame> data_frame_fin(
3993 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN));
3994 const spdy::SpdyFrame* data_frames[4] = {
3995 data_frame.get(),
3996 data_frame.get(),
3997 data_frame.get(),
3998 data_frame_fin.get()
4000 char combined_data_frames[100];
4001 int combined_data_frames_len =
4002 CombineFrames(data_frames, arraysize(data_frames),
4003 combined_data_frames, arraysize(combined_data_frames));
4005 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4006 MockRead reads[] = {
4007 CreateMockRead(*resp),
4008 MockRead(ASYNC, ERR_IO_PENDING), // Force a pause
4009 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4010 MockRead(ASYNC, 0, 0) // EOF
4013 scoped_ptr<DelayedSocketData> data(
4014 new DelayedSocketData(1, reads, arraysize(reads),
4015 writes, arraysize(writes)));
4017 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4018 BoundNetLog(), GetParam());
4019 helper.RunPreTestSetup();
4020 helper.AddData(data.get());
4021 HttpNetworkTransaction* trans = helper.trans();
4023 TestCompletionCallback callback;
4024 int rv = trans->Start(
4025 &CreateGetRequest(), callback.callback(), BoundNetLog());
4026 EXPECT_EQ(ERR_IO_PENDING, rv);
4028 TransactionHelperResult out = helper.output();
4029 out.rv = callback.WaitForResult();
4030 EXPECT_EQ(out.rv, OK);
4032 const HttpResponseInfo* response = trans->GetResponseInfo();
4033 EXPECT_TRUE(response->headers != NULL);
4034 EXPECT_TRUE(response->was_fetched_via_spdy);
4035 out.status_line = response->headers->GetStatusLine();
4036 out.response_info = *response; // Make a copy so we can verify.
4038 // Read Data
4039 TestCompletionCallback read_callback;
4041 std::string content;
4042 int reads_completed = 0;
4043 do {
4044 // Read small chunks at a time.
4045 const int kSmallReadSize = 14;
4046 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4047 rv = trans->Read(buf, kSmallReadSize, read_callback.callback());
4048 if (rv == net::ERR_IO_PENDING) {
4049 data->CompleteRead();
4050 rv = read_callback.WaitForResult();
4052 if (rv > 0) {
4053 EXPECT_EQ(kSmallReadSize, rv);
4054 content.append(buf->data(), rv);
4055 } else if (rv < 0) {
4056 FAIL() << "Unexpected read error: " << rv;
4058 reads_completed++;
4059 } while (rv > 0);
4061 EXPECT_EQ(3, reads_completed); // Reads are: 14 bytes, 14 bytes, 0 bytes.
4063 out.response_data.swap(content);
4065 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4066 // MockClientSocketFactory) are still alive.
4067 MessageLoop::current()->RunAllPending();
4069 // Verify that we consumed all test data.
4070 helper.VerifyDataConsumed();
4072 EXPECT_EQ(OK, out.rv);
4073 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4074 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4076 SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN);
4079 // Verify the case where we buffer data but read it after it has been buffered.
4080 TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
4081 spdy::SpdyFramer framer;
4083 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4084 MockWrite writes[] = { CreateMockWrite(*req) };
4086 // 5 data frames in a single read.
4087 scoped_ptr<spdy::SpdyFrame> syn_reply(
4088 ConstructSpdyGetSynReply(NULL, 0, 1));
4089 syn_reply->set_flags(spdy::CONTROL_FLAG_NONE); // turn off FIN bit
4090 scoped_ptr<spdy::SpdyFrame> data_frame(
4091 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
4092 scoped_ptr<spdy::SpdyFrame> data_frame_fin(
4093 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN));
4094 const spdy::SpdyFrame* frames[5] = {
4095 syn_reply.get(),
4096 data_frame.get(),
4097 data_frame.get(),
4098 data_frame.get(),
4099 data_frame_fin.get()
4101 char combined_frames[200];
4102 int combined_frames_len =
4103 CombineFrames(frames, arraysize(frames),
4104 combined_frames, arraysize(combined_frames));
4106 MockRead reads[] = {
4107 MockRead(ASYNC, combined_frames, combined_frames_len),
4108 MockRead(ASYNC, 0, 0) // EOF
4111 scoped_ptr<DelayedSocketData> data(
4112 new DelayedSocketData(1, reads, arraysize(reads),
4113 writes, arraysize(writes)));
4115 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4116 BoundNetLog(), GetParam());
4117 helper.RunPreTestSetup();
4118 helper.AddData(data.get());
4119 HttpNetworkTransaction* trans = helper.trans();
4121 TestCompletionCallback callback;
4122 int rv = trans->Start(
4123 &CreateGetRequest(), callback.callback(), BoundNetLog());
4124 EXPECT_EQ(ERR_IO_PENDING, rv);
4126 TransactionHelperResult out = helper.output();
4127 out.rv = callback.WaitForResult();
4128 EXPECT_EQ(out.rv, OK);
4130 const HttpResponseInfo* response = trans->GetResponseInfo();
4131 EXPECT_TRUE(response->headers != NULL);
4132 EXPECT_TRUE(response->was_fetched_via_spdy);
4133 out.status_line = response->headers->GetStatusLine();
4134 out.response_info = *response; // Make a copy so we can verify.
4136 // Read Data
4137 TestCompletionCallback read_callback;
4139 std::string content;
4140 int reads_completed = 0;
4141 do {
4142 // Read small chunks at a time.
4143 const int kSmallReadSize = 14;
4144 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4145 rv = trans->Read(buf, kSmallReadSize, read_callback.callback());
4146 if (rv > 0) {
4147 EXPECT_EQ(kSmallReadSize, rv);
4148 content.append(buf->data(), rv);
4149 } else if (rv < 0) {
4150 FAIL() << "Unexpected read error: " << rv;
4152 reads_completed++;
4153 } while (rv > 0);
4155 EXPECT_EQ(3, reads_completed);
4157 out.response_data.swap(content);
4159 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4160 // MockClientSocketFactory) are still alive.
4161 MessageLoop::current()->RunAllPending();
4163 // Verify that we consumed all test data.
4164 helper.VerifyDataConsumed();
4166 EXPECT_EQ(OK, out.rv);
4167 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4168 EXPECT_EQ("messagemessagemessagemessage", out.response_data);
4171 // Verify the case where we buffer data and close the connection.
4172 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
4173 spdy::SpdyFramer framer;
4175 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4176 MockWrite writes[] = { CreateMockWrite(*req) };
4178 // All data frames in a single read.
4179 // NOTE: We don't FIN the stream.
4180 scoped_ptr<spdy::SpdyFrame> data_frame(
4181 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
4182 const spdy::SpdyFrame* data_frames[4] = {
4183 data_frame.get(),
4184 data_frame.get(),
4185 data_frame.get(),
4186 data_frame.get()
4188 char combined_data_frames[100];
4189 int combined_data_frames_len =
4190 CombineFrames(data_frames, arraysize(data_frames),
4191 combined_data_frames, arraysize(combined_data_frames));
4192 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4193 MockRead reads[] = {
4194 CreateMockRead(*resp),
4195 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4196 MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
4197 MockRead(ASYNC, 0, 0) // EOF
4200 scoped_ptr<DelayedSocketData> data(
4201 new DelayedSocketData(1, reads, arraysize(reads),
4202 writes, arraysize(writes)));
4204 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4205 BoundNetLog(), GetParam());
4206 helper.RunPreTestSetup();
4207 helper.AddData(data.get());
4208 HttpNetworkTransaction* trans = helper.trans();
4210 TestCompletionCallback callback;
4212 int rv = trans->Start(
4213 &CreateGetRequest(), callback.callback(), BoundNetLog());
4214 EXPECT_EQ(ERR_IO_PENDING, rv);
4216 TransactionHelperResult out = helper.output();
4217 out.rv = callback.WaitForResult();
4218 EXPECT_EQ(out.rv, OK);
4220 const HttpResponseInfo* response = trans->GetResponseInfo();
4221 EXPECT_TRUE(response->headers != NULL);
4222 EXPECT_TRUE(response->was_fetched_via_spdy);
4223 out.status_line = response->headers->GetStatusLine();
4224 out.response_info = *response; // Make a copy so we can verify.
4226 // Read Data
4227 TestCompletionCallback read_callback;
4229 std::string content;
4230 int reads_completed = 0;
4231 do {
4232 // Read small chunks at a time.
4233 const int kSmallReadSize = 14;
4234 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4235 rv = trans->Read(buf, kSmallReadSize, read_callback.callback());
4236 if (rv == net::ERR_IO_PENDING) {
4237 data->CompleteRead();
4238 rv = read_callback.WaitForResult();
4240 if (rv > 0) {
4241 content.append(buf->data(), rv);
4242 } else if (rv < 0) {
4243 // This test intentionally closes the connection, and will get an error.
4244 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
4245 break;
4247 reads_completed++;
4248 } while (rv > 0);
4250 EXPECT_EQ(0, reads_completed);
4252 out.response_data.swap(content);
4254 // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
4255 // MockClientSocketFactory) are still alive.
4256 MessageLoop::current()->RunAllPending();
4258 // Verify that we consumed all test data.
4259 helper.VerifyDataConsumed();
4262 // Verify the case where we buffer data and cancel the transaction.
4263 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
4264 spdy::SpdyFramer framer;
4266 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4267 MockWrite writes[] = { CreateMockWrite(*req) };
4269 // NOTE: We don't FIN the stream.
4270 scoped_ptr<spdy::SpdyFrame> data_frame(
4271 framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE));
4273 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4274 MockRead reads[] = {
4275 CreateMockRead(*resp),
4276 MockRead(ASYNC, ERR_IO_PENDING), // Force a wait
4277 CreateMockRead(*data_frame),
4278 MockRead(ASYNC, 0, 0) // EOF
4281 scoped_ptr<DelayedSocketData> data(
4282 new DelayedSocketData(1, reads, arraysize(reads),
4283 writes, arraysize(writes)));
4285 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4286 BoundNetLog(), GetParam());
4287 helper.RunPreTestSetup();
4288 helper.AddData(data.get());
4289 HttpNetworkTransaction* trans = helper.trans();
4290 TestCompletionCallback callback;
4292 int rv = trans->Start(
4293 &CreateGetRequest(), callback.callback(), BoundNetLog());
4294 EXPECT_EQ(ERR_IO_PENDING, rv);
4296 TransactionHelperResult out = helper.output();
4297 out.rv = callback.WaitForResult();
4298 EXPECT_EQ(out.rv, OK);
4300 const HttpResponseInfo* response = trans->GetResponseInfo();
4301 EXPECT_TRUE(response->headers != NULL);
4302 EXPECT_TRUE(response->was_fetched_via_spdy);
4303 out.status_line = response->headers->GetStatusLine();
4304 out.response_info = *response; // Make a copy so we can verify.
4306 // Read Data
4307 TestCompletionCallback read_callback;
4309 do {
4310 const int kReadSize = 256;
4311 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
4312 rv = trans->Read(buf, kReadSize, read_callback.callback());
4313 if (rv == net::ERR_IO_PENDING) {
4314 // Complete the read now, which causes buffering to start.
4315 data->CompleteRead();
4316 // Destroy the transaction, causing the stream to get cancelled
4317 // and orphaning the buffered IO task.
4318 helper.ResetTrans();
4319 break;
4321 // We shouldn't get here in this test.
4322 FAIL() << "Unexpected read: " << rv;
4323 } while (rv > 0);
4325 // Flush the MessageLoop; this will cause the buffered IO task
4326 // to run for the final time.
4327 MessageLoop::current()->RunAllPending();
4329 // Verify that we consumed all test data.
4330 helper.VerifyDataConsumed();
4333 // Test that if the server requests persistence of settings, that we save
4334 // the settings in the SpdySettingsStorage.
4335 TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
4336 static const SpdyHeaderInfo kSynReplyInfo = {
4337 spdy::SYN_REPLY, // Syn Reply
4338 1, // Stream ID
4339 0, // Associated Stream ID
4340 net::ConvertRequestPriorityToSpdyPriority(LOWEST),
4341 // Priority
4342 spdy::CONTROL_FLAG_NONE, // Control Flags
4343 false, // Compressed
4344 spdy::INVALID, // Status
4345 NULL, // Data
4346 0, // Data Length
4347 spdy::DATA_FLAG_NONE // Data Flags
4349 static const char* const kExtraHeaders[] = {
4350 "status", "200",
4351 "version", "HTTP/1.1"
4354 BoundNetLog net_log;
4355 NormalSpdyTransactionHelper helper(CreateGetRequest(), net_log, GetParam());
4356 helper.RunPreTestSetup();
4358 // Verify that no settings exist initially.
4359 HostPortPair host_port_pair("www.google.com", helper.port());
4360 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4361 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4362 host_port_pair).empty());
4364 // Construct the request.
4365 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4366 MockWrite writes[] = { CreateMockWrite(*req) };
4368 // Construct the reply.
4369 scoped_ptr<spdy::SpdyFrame> reply(
4370 ConstructSpdyPacket(kSynReplyInfo,
4371 kExtraHeaders,
4372 arraysize(kExtraHeaders) / 2,
4373 NULL,
4374 0));
4376 unsigned int kSampleId1 = 0x1;
4377 unsigned int kSampleValue1 = 0x0a0a0a0a;
4378 unsigned int kSampleId2 = 0x2;
4379 unsigned int kSampleValue2 = 0x0b0b0b0b;
4380 unsigned int kSampleId3 = 0xababab;
4381 unsigned int kSampleValue3 = 0x0c0c0c0c;
4382 scoped_ptr<spdy::SpdyFrame> settings_frame;
4384 // Construct the SETTINGS frame.
4385 spdy::SpdySettings settings;
4386 spdy::SettingsFlagsAndId setting(0);
4387 // First add a persisted setting
4388 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4389 setting.set_id(kSampleId1);
4390 settings.push_back(std::make_pair(setting, kSampleValue1));
4391 // Next add a non-persisted setting
4392 setting.set_flags(0);
4393 setting.set_id(kSampleId2);
4394 settings.push_back(std::make_pair(setting, kSampleValue2));
4395 // Next add another persisted setting
4396 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4397 setting.set_id(kSampleId3);
4398 settings.push_back(std::make_pair(setting, kSampleValue3));
4399 settings_frame.reset(ConstructSpdySettings(settings));
4402 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4403 MockRead reads[] = {
4404 CreateMockRead(*reply),
4405 CreateMockRead(*body),
4406 CreateMockRead(*settings_frame),
4407 MockRead(ASYNC, 0, 0) // EOF
4410 scoped_ptr<DelayedSocketData> data(
4411 new DelayedSocketData(1, reads, arraysize(reads),
4412 writes, arraysize(writes)));
4413 helper.AddData(data.get());
4414 helper.RunDefaultTest();
4415 helper.VerifyDataConsumed();
4416 TransactionHelperResult out = helper.output();
4417 EXPECT_EQ(OK, out.rv);
4418 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4419 EXPECT_EQ("hello!", out.response_data);
4422 // Verify we had two persisted settings.
4423 spdy::SpdySettings saved_settings =
4424 spdy_session_pool->http_server_properties()->GetSpdySettings(
4425 host_port_pair);
4426 ASSERT_EQ(2u, saved_settings.size());
4428 // Verify the first persisted setting.
4429 spdy::SpdySetting setting = saved_settings.front();
4430 saved_settings.pop_front();
4431 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4432 EXPECT_EQ(kSampleId1, setting.first.id());
4433 EXPECT_EQ(kSampleValue1, setting.second);
4435 // Verify the second persisted setting.
4436 setting = saved_settings.front();
4437 saved_settings.pop_front();
4438 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4439 EXPECT_EQ(kSampleId3, setting.first.id());
4440 EXPECT_EQ(kSampleValue3, setting.second);
4444 // Test that when there are settings saved that they are sent back to the
4445 // server upon session establishment.
4446 TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
4447 static const SpdyHeaderInfo kSynReplyInfo = {
4448 spdy::SYN_REPLY, // Syn Reply
4449 1, // Stream ID
4450 0, // Associated Stream ID
4451 net::ConvertRequestPriorityToSpdyPriority(LOWEST),
4452 // Priority
4453 spdy::CONTROL_FLAG_NONE, // Control Flags
4454 false, // Compressed
4455 spdy::INVALID, // Status
4456 NULL, // Data
4457 0, // Data Length
4458 spdy::DATA_FLAG_NONE // Data Flags
4460 static const char* kExtraHeaders[] = {
4461 "status", "200",
4462 "version", "HTTP/1.1"
4465 BoundNetLog net_log;
4466 NormalSpdyTransactionHelper helper(CreateGetRequest(), net_log, GetParam());
4467 helper.RunPreTestSetup();
4469 // Verify that no settings exist initially.
4470 HostPortPair host_port_pair("www.google.com", helper.port());
4471 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4472 EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4473 host_port_pair).empty());
4475 unsigned int kSampleId1 = 0x1;
4476 unsigned int kSampleValue1 = 0x0a0a0a0a;
4477 unsigned int kSampleId2 = 0xababab;
4478 unsigned int kSampleValue2 = 0x0c0c0c0c;
4479 // Manually insert settings into the SpdySettingsStorage here.
4481 spdy::SpdySettings settings;
4482 spdy::SettingsFlagsAndId setting(0);
4483 // First add a persisted setting
4484 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4485 setting.set_id(kSampleId1);
4486 settings.push_back(std::make_pair(setting, kSampleValue1));
4487 // Next add another persisted setting
4488 setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST);
4489 setting.set_id(kSampleId2);
4490 settings.push_back(std::make_pair(setting, kSampleValue2));
4492 spdy_session_pool->http_server_properties()->SetSpdySettings(
4493 host_port_pair, settings);
4496 EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4497 host_port_pair).size());
4499 // Construct the SETTINGS frame.
4500 const spdy::SpdySettings& settings =
4501 spdy_session_pool->http_server_properties()->GetSpdySettings(
4502 host_port_pair);
4503 scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings));
4505 // Construct the request.
4506 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4508 MockWrite writes[] = {
4509 CreateMockWrite(*settings_frame),
4510 CreateMockWrite(*req),
4513 // Construct the reply.
4514 scoped_ptr<spdy::SpdyFrame> reply(
4515 ConstructSpdyPacket(kSynReplyInfo,
4516 kExtraHeaders,
4517 arraysize(kExtraHeaders) / 2,
4518 NULL,
4519 0));
4521 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4522 MockRead reads[] = {
4523 CreateMockRead(*reply),
4524 CreateMockRead(*body),
4525 MockRead(ASYNC, 0, 0) // EOF
4528 scoped_ptr<DelayedSocketData> data(
4529 new DelayedSocketData(2, reads, arraysize(reads),
4530 writes, arraysize(writes)));
4531 helper.AddData(data.get());
4532 helper.RunDefaultTest();
4533 helper.VerifyDataConsumed();
4534 TransactionHelperResult out = helper.output();
4535 EXPECT_EQ(OK, out.rv);
4536 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4537 EXPECT_EQ("hello!", out.response_data);
4540 // Verify we had two persisted settings.
4541 spdy::SpdySettings saved_settings =
4542 spdy_session_pool->http_server_properties()->GetSpdySettings(
4543 host_port_pair);
4544 ASSERT_EQ(2u, saved_settings.size());
4546 // Verify the first persisted setting.
4547 spdy::SpdySetting setting = saved_settings.front();
4548 saved_settings.pop_front();
4549 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4550 EXPECT_EQ(kSampleId1, setting.first.id());
4551 EXPECT_EQ(kSampleValue1, setting.second);
4553 // Verify the second persisted setting.
4554 setting = saved_settings.front();
4555 saved_settings.pop_front();
4556 EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags());
4557 EXPECT_EQ(kSampleId2, setting.first.id());
4558 EXPECT_EQ(kSampleValue2, setting.second);
4562 TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
4563 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4564 MockWrite writes[] = { CreateMockWrite(*req) };
4566 scoped_ptr<spdy::SpdyFrame> go_away(ConstructSpdyGoAway());
4567 MockRead reads[] = {
4568 CreateMockRead(*go_away),
4569 MockRead(ASYNC, 0, 0), // EOF
4572 scoped_ptr<DelayedSocketData> data(
4573 new DelayedSocketData(1, reads, arraysize(reads),
4574 writes, arraysize(writes)));
4575 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4576 BoundNetLog(), GetParam());
4577 helper.AddData(data.get());
4578 helper.RunToCompletion(data.get());
4579 TransactionHelperResult out = helper.output();
4580 EXPECT_EQ(ERR_ABORTED, out.rv);
4583 TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
4584 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4585 MockWrite writes[] = { CreateMockWrite(*req) };
4587 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4588 MockRead reads[] = {
4589 CreateMockRead(*resp),
4590 MockRead(SYNCHRONOUS, 0, 0) // EOF
4593 scoped_ptr<DelayedSocketData> data(
4594 new DelayedSocketData(1, reads, arraysize(reads),
4595 writes, arraysize(writes)));
4596 BoundNetLog log;
4597 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4598 log, GetParam());
4599 helper.RunPreTestSetup();
4600 helper.AddData(data.get());
4601 HttpNetworkTransaction* trans = helper.trans();
4603 TestCompletionCallback callback;
4604 TransactionHelperResult out;
4605 out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
4607 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4608 out.rv = callback.WaitForResult();
4609 EXPECT_EQ(out.rv, OK);
4611 const HttpResponseInfo* response = trans->GetResponseInfo();
4612 EXPECT_TRUE(response->headers != NULL);
4613 EXPECT_TRUE(response->was_fetched_via_spdy);
4614 out.rv = ReadTransaction(trans, &out.response_data);
4615 EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4617 // Verify that we consumed all test data.
4618 helper.VerifyDataConsumed();
4621 // Test to make sure we can correctly connect through a proxy.
4622 TEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
4623 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4624 BoundNetLog(), GetParam());
4625 helper.session_deps().reset(new SpdySessionDependencies(
4626 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4627 helper.SetSession(make_scoped_refptr(
4628 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4629 helper.RunPreTestSetup();
4630 HttpNetworkTransaction* trans = helper.trans();
4632 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4633 "Host: www.google.com\r\n"
4634 "Proxy-Connection: keep-alive\r\n\r\n"};
4635 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4636 "Host: www.google.com\r\n"
4637 "Proxy-Connection: keep-alive\r\n\r\n"};
4638 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4639 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4640 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4641 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4643 MockWrite writes_SPDYNPN[] = {
4644 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4645 CreateMockWrite(*req, 2),
4647 MockRead reads_SPDYNPN[] = {
4648 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4649 CreateMockRead(*resp, 3),
4650 CreateMockRead(*body.get(), 4),
4651 MockRead(ASYNC, 0, 0, 5),
4654 MockWrite writes_SPDYSSL[] = {
4655 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4656 CreateMockWrite(*req, 2),
4658 MockRead reads_SPDYSSL[] = {
4659 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4660 CreateMockRead(*resp, 3),
4661 CreateMockRead(*body.get(), 4),
4662 MockRead(ASYNC, 0, 0, 5),
4665 MockWrite writes_SPDYNOSSL[] = {
4666 CreateMockWrite(*req, 0),
4669 MockRead reads_SPDYNOSSL[] = {
4670 CreateMockRead(*resp, 1),
4671 CreateMockRead(*body.get(), 2),
4672 MockRead(ASYNC, 0, 0, 3),
4675 scoped_ptr<OrderedSocketData> data;
4676 switch(GetParam()) {
4677 case SPDYNOSSL:
4678 data.reset(new OrderedSocketData(reads_SPDYNOSSL,
4679 arraysize(reads_SPDYNOSSL),
4680 writes_SPDYNOSSL,
4681 arraysize(writes_SPDYNOSSL)));
4682 break;
4683 case SPDYSSL:
4684 data.reset(new OrderedSocketData(reads_SPDYSSL,
4685 arraysize(reads_SPDYSSL),
4686 writes_SPDYSSL,
4687 arraysize(writes_SPDYSSL)));
4688 break;
4689 case SPDYNPN:
4690 data.reset(new OrderedSocketData(reads_SPDYNPN,
4691 arraysize(reads_SPDYNPN),
4692 writes_SPDYNPN,
4693 arraysize(writes_SPDYNPN)));
4694 break;
4695 default:
4696 NOTREACHED();
4699 helper.AddData(data.get());
4700 TestCompletionCallback callback;
4702 int rv = trans->Start(
4703 &CreateGetRequest(), callback.callback(), BoundNetLog());
4704 EXPECT_EQ(ERR_IO_PENDING, rv);
4706 rv = callback.WaitForResult();
4707 EXPECT_EQ(0, rv);
4709 // Verify the SYN_REPLY.
4710 HttpResponseInfo response = *trans->GetResponseInfo();
4711 EXPECT_TRUE(response.headers != NULL);
4712 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4714 std::string response_data;
4715 ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4716 EXPECT_EQ("hello!", response_data);
4717 helper.VerifyDataConsumed();
4720 // Test to make sure we can correctly connect through a proxy to www.google.com,
4721 // if there already exists a direct spdy connection to www.google.com. See
4722 // http://crbug.com/49874
4723 TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
4724 // When setting up the first transaction, we store the SpdySessionPool so that
4725 // we can use the same pool in the second transaction.
4726 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4727 BoundNetLog(), GetParam());
4729 // Use a proxy service which returns a proxy fallback list from DIRECT to
4730 // myproxy:70. For this test there will be no fallback, so it is equivalent
4731 // to simply DIRECT. The reason for appending the second proxy is to verify
4732 // that the session pool key used does is just "DIRECT".
4733 helper.session_deps().reset(new SpdySessionDependencies(
4734 ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4735 helper.SetSession(make_scoped_refptr(
4736 SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4738 SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4739 helper.RunPreTestSetup();
4741 // Construct and send a simple GET request.
4742 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4743 MockWrite writes[] = {
4744 CreateMockWrite(*req, 1),
4747 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4748 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4749 MockRead reads[] = {
4750 CreateMockRead(*resp, 2),
4751 CreateMockRead(*body, 3),
4752 MockRead(ASYNC, ERR_IO_PENDING, 4), // Force a pause
4753 MockRead(ASYNC, 0, 5) // EOF
4755 scoped_ptr<OrderedSocketData> data(
4756 new OrderedSocketData(reads, arraysize(reads),
4757 writes, arraysize(writes)));
4758 helper.AddData(data.get());
4759 HttpNetworkTransaction* trans = helper.trans();
4761 TestCompletionCallback callback;
4762 TransactionHelperResult out;
4763 out.rv = trans->Start(
4764 &CreateGetRequest(), callback.callback(), BoundNetLog());
4766 EXPECT_EQ(out.rv, ERR_IO_PENDING);
4767 out.rv = callback.WaitForResult();
4768 EXPECT_EQ(out.rv, OK);
4770 const HttpResponseInfo* response = trans->GetResponseInfo();
4771 EXPECT_TRUE(response->headers != NULL);
4772 EXPECT_TRUE(response->was_fetched_via_spdy);
4773 out.rv = ReadTransaction(trans, &out.response_data);
4774 EXPECT_EQ(OK, out.rv);
4775 out.status_line = response->headers->GetStatusLine();
4776 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4777 EXPECT_EQ("hello!", out.response_data);
4779 // Check that the SpdySession is still in the SpdySessionPool.
4780 HostPortPair host_port_pair("www.google.com", helper.port());
4781 HostPortProxyPair session_pool_key_direct(
4782 host_port_pair, ProxyServer::Direct());
4783 EXPECT_TRUE(spdy_session_pool->HasSession(session_pool_key_direct));
4784 HostPortProxyPair session_pool_key_proxy(
4785 host_port_pair,
4786 ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP));
4787 EXPECT_FALSE(spdy_session_pool->HasSession(session_pool_key_proxy));
4789 // Set up data for the proxy connection.
4790 const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4791 "Host: www.google.com\r\n"
4792 "Proxy-Connection: keep-alive\r\n\r\n"};
4793 const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4794 "Host: www.google.com\r\n"
4795 "Proxy-Connection: keep-alive\r\n\r\n"};
4796 const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4797 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(
4798 "http://www.google.com/foo.dat", false, 1, LOWEST));
4799 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1));
4800 scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true));
4802 MockWrite writes_SPDYNPN[] = {
4803 MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4804 CreateMockWrite(*req2, 2),
4806 MockRead reads_SPDYNPN[] = {
4807 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4808 CreateMockRead(*resp2, 3),
4809 CreateMockRead(*body2, 4),
4810 MockRead(ASYNC, 0, 5) // EOF
4813 MockWrite writes_SPDYNOSSL[] = {
4814 CreateMockWrite(*req2, 0),
4816 MockRead reads_SPDYNOSSL[] = {
4817 CreateMockRead(*resp2, 1),
4818 CreateMockRead(*body2, 2),
4819 MockRead(ASYNC, 0, 3) // EOF
4822 MockWrite writes_SPDYSSL[] = {
4823 MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4824 CreateMockWrite(*req2, 2),
4826 MockRead reads_SPDYSSL[] = {
4827 MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4828 CreateMockRead(*resp2, 3),
4829 CreateMockRead(*body2, 4),
4830 MockRead(ASYNC, 0, 0, 5),
4833 scoped_ptr<OrderedSocketData> data_proxy;
4834 switch(GetParam()) {
4835 case SPDYNPN:
4836 data_proxy.reset(new OrderedSocketData(reads_SPDYNPN,
4837 arraysize(reads_SPDYNPN),
4838 writes_SPDYNPN,
4839 arraysize(writes_SPDYNPN)));
4840 break;
4841 case SPDYNOSSL:
4842 data_proxy.reset(new OrderedSocketData(reads_SPDYNOSSL,
4843 arraysize(reads_SPDYNOSSL),
4844 writes_SPDYNOSSL,
4845 arraysize(writes_SPDYNOSSL)));
4846 break;
4847 case SPDYSSL:
4848 data_proxy.reset(new OrderedSocketData(reads_SPDYSSL,
4849 arraysize(reads_SPDYSSL),
4850 writes_SPDYSSL,
4851 arraysize(writes_SPDYSSL)));
4852 break;
4853 default:
4854 NOTREACHED();
4857 // Create another request to www.google.com, but this time through a proxy.
4858 HttpRequestInfo request_proxy;
4859 request_proxy.method = "GET";
4860 request_proxy.url = GURL("http://www.google.com/foo.dat");
4861 request_proxy.load_flags = 0;
4862 scoped_ptr<SpdySessionDependencies> ssd_proxy(new SpdySessionDependencies());
4863 // Ensure that this transaction uses the same SpdySessionPool.
4864 scoped_refptr<HttpNetworkSession> session_proxy(
4865 SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
4866 NormalSpdyTransactionHelper helper_proxy(request_proxy,
4867 BoundNetLog(), GetParam());
4868 HttpNetworkSessionPeer session_peer(session_proxy);
4869 scoped_ptr<net::ProxyService> proxy_service(
4870 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
4871 session_peer.SetProxyService(proxy_service.get());
4872 helper_proxy.session_deps().swap(ssd_proxy);
4873 helper_proxy.SetSession(session_proxy);
4874 helper_proxy.RunPreTestSetup();
4875 helper_proxy.AddData(data_proxy.get());
4877 HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
4878 TestCompletionCallback callback_proxy;
4879 int rv = trans_proxy->Start(
4880 &request_proxy, callback_proxy.callback(), BoundNetLog());
4881 EXPECT_EQ(ERR_IO_PENDING, rv);
4882 rv = callback_proxy.WaitForResult();
4883 EXPECT_EQ(0, rv);
4885 HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
4886 EXPECT_TRUE(response_proxy.headers != NULL);
4887 EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
4889 std::string response_data;
4890 ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
4891 EXPECT_EQ("hello!", response_data);
4893 data->CompleteRead();
4894 helper_proxy.VerifyDataConsumed();
4897 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4898 // on a new connection, if the connection was previously known to be good.
4899 // This can happen when a server reboots without saying goodbye, or when
4900 // we're behind a NAT that masked the RST.
4901 TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
4902 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4903 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4904 MockRead reads[] = {
4905 CreateMockRead(*resp),
4906 CreateMockRead(*body),
4907 MockRead(ASYNC, ERR_IO_PENDING),
4908 MockRead(ASYNC, ERR_CONNECTION_RESET),
4911 MockRead reads2[] = {
4912 CreateMockRead(*resp),
4913 CreateMockRead(*body),
4914 MockRead(ASYNC, 0, 0) // EOF
4917 // This test has a couple of variants.
4918 enum {
4919 // Induce the RST while waiting for our transaction to send.
4920 VARIANT_RST_DURING_SEND_COMPLETION,
4921 // Induce the RST while waiting for our transaction to read.
4922 // In this case, the send completed - everything copied into the SNDBUF.
4923 VARIANT_RST_DURING_READ_COMPLETION
4926 for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4927 variant <= VARIANT_RST_DURING_READ_COMPLETION;
4928 ++variant) {
4929 scoped_ptr<DelayedSocketData> data1(
4930 new DelayedSocketData(1, reads, arraysize(reads),
4931 NULL, 0));
4933 scoped_ptr<DelayedSocketData> data2(
4934 new DelayedSocketData(1, reads2, arraysize(reads2),
4935 NULL, 0));
4937 NormalSpdyTransactionHelper helper(CreateGetRequest(),
4938 BoundNetLog(), GetParam());
4939 helper.AddData(data1.get());
4940 helper.AddData(data2.get());
4941 helper.RunPreTestSetup();
4943 for (int i = 0; i < 2; ++i) {
4944 scoped_ptr<HttpNetworkTransaction> trans(
4945 new HttpNetworkTransaction(helper.session()));
4947 TestCompletionCallback callback;
4948 int rv = trans->Start(
4949 &helper.request(), callback.callback(), BoundNetLog());
4950 EXPECT_EQ(ERR_IO_PENDING, rv);
4951 // On the second transaction, we trigger the RST.
4952 if (i == 1) {
4953 if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4954 // Writes to the socket complete asynchronously on SPDY by running
4955 // through the message loop. Complete the write here.
4956 MessageLoop::current()->RunAllPending();
4959 // Now schedule the ERR_CONNECTION_RESET.
4960 EXPECT_EQ(3u, data1->read_index());
4961 data1->CompleteRead();
4962 EXPECT_EQ(4u, data1->read_index());
4964 rv = callback.WaitForResult();
4965 EXPECT_EQ(OK, rv);
4967 const HttpResponseInfo* response = trans->GetResponseInfo();
4968 ASSERT_TRUE(response != NULL);
4969 EXPECT_TRUE(response->headers != NULL);
4970 EXPECT_TRUE(response->was_fetched_via_spdy);
4971 std::string response_data;
4972 rv = ReadTransaction(trans.get(), &response_data);
4973 EXPECT_EQ(OK, rv);
4974 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4975 EXPECT_EQ("hello!", response_data);
4978 helper.VerifyDataConsumed();
4982 // Test that turning SPDY on and off works properly.
4983 TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
4984 net::HttpStreamFactory::set_spdy_enabled(true);
4985 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
4986 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
4988 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
4989 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
4990 MockRead spdy_reads[] = {
4991 CreateMockRead(*resp),
4992 CreateMockRead(*body),
4993 MockRead(ASYNC, 0, 0) // EOF
4996 scoped_ptr<DelayedSocketData> data(
4997 new DelayedSocketData(1,
4998 spdy_reads, arraysize(spdy_reads),
4999 spdy_writes, arraysize(spdy_writes)));
5000 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5001 BoundNetLog(), GetParam());
5002 helper.RunToCompletion(data.get());
5003 TransactionHelperResult out = helper.output();
5004 EXPECT_EQ(OK, out.rv);
5005 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5006 EXPECT_EQ("hello!", out.response_data);
5008 net::HttpStreamFactory::set_spdy_enabled(false);
5009 MockRead http_reads[] = {
5010 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5011 MockRead("hello from http"),
5012 MockRead(SYNCHRONOUS, OK),
5014 scoped_ptr<DelayedSocketData> data2(
5015 new DelayedSocketData(1, http_reads, arraysize(http_reads),
5016 NULL, 0));
5017 NormalSpdyTransactionHelper helper2(CreateGetRequest(),
5018 BoundNetLog(), GetParam());
5019 helper2.SetSpdyDisabled();
5020 helper2.RunToCompletion(data2.get());
5021 TransactionHelperResult out2 = helper2.output();
5022 EXPECT_EQ(OK, out2.rv);
5023 EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
5024 EXPECT_EQ("hello from http", out2.response_data);
5026 net::HttpStreamFactory::set_spdy_enabled(true);
5029 // Tests that Basic authentication works over SPDY
5030 TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
5031 net::HttpStreamFactory::set_spdy_enabled(true);
5033 // The first request will be a bare GET, the second request will be a
5034 // GET with an Authorization header.
5035 scoped_ptr<spdy::SpdyFrame> req_get(
5036 ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5037 const char* const kExtraAuthorizationHeaders[] = {
5038 "authorization",
5039 "Basic Zm9vOmJhcg==",
5041 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
5042 ConstructSpdyGet(
5043 kExtraAuthorizationHeaders,
5044 arraysize(kExtraAuthorizationHeaders) / 2,
5045 false, 3, LOWEST));
5046 MockWrite spdy_writes[] = {
5047 CreateMockWrite(*req_get, 1),
5048 CreateMockWrite(*req_get_authorization, 4),
5051 // The first response is a 401 authentication challenge, and the second
5052 // response will be a 200 response since the second request includes a valid
5053 // Authorization header.
5054 const char* const kExtraAuthenticationHeaders[] = {
5055 "www-authenticate",
5056 "Basic realm=\"MyRealm\""
5058 scoped_ptr<spdy::SpdyFrame> resp_authentication(
5059 ConstructSpdySynReplyError(
5060 "401 Authentication Required",
5061 kExtraAuthenticationHeaders,
5062 arraysize(kExtraAuthenticationHeaders) / 2,
5063 1));
5064 scoped_ptr<spdy::SpdyFrame> body_authentication(
5065 ConstructSpdyBodyFrame(1, true));
5066 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
5067 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
5068 MockRead spdy_reads[] = {
5069 CreateMockRead(*resp_authentication, 2),
5070 CreateMockRead(*body_authentication, 3),
5071 CreateMockRead(*resp_data, 5),
5072 CreateMockRead(*body_data, 6),
5073 MockRead(ASYNC, 0, 7),
5076 scoped_ptr<OrderedSocketData> data(
5077 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
5078 spdy_writes, arraysize(spdy_writes)));
5079 HttpRequestInfo request(CreateGetRequest());
5080 BoundNetLog net_log;
5081 NormalSpdyTransactionHelper helper(request, net_log, GetParam());
5083 helper.RunPreTestSetup();
5084 helper.AddData(data.get());
5085 HttpNetworkTransaction* trans = helper.trans();
5086 TestCompletionCallback callback;
5087 const int rv_start = trans->Start(&request, callback.callback(), net_log);
5088 EXPECT_EQ(ERR_IO_PENDING, rv_start);
5089 const int rv_start_complete = callback.WaitForResult();
5090 EXPECT_EQ(OK, rv_start_complete);
5092 // Make sure the response has an auth challenge.
5093 const HttpResponseInfo* const response_start = trans->GetResponseInfo();
5094 ASSERT_TRUE(response_start != NULL);
5095 ASSERT_TRUE(response_start->headers != NULL);
5096 EXPECT_EQ(401, response_start->headers->response_code());
5097 EXPECT_TRUE(response_start->was_fetched_via_spdy);
5098 AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
5099 ASSERT_TRUE(auth_challenge != NULL);
5100 EXPECT_FALSE(auth_challenge->is_proxy);
5101 EXPECT_EQ("basic", auth_challenge->scheme);
5102 EXPECT_EQ("MyRealm", auth_challenge->realm);
5104 // Restart with a username/password.
5105 AuthCredentials credentials(ASCIIToUTF16("foo"), ASCIIToUTF16("bar"));
5106 TestCompletionCallback callback_restart;
5107 const int rv_restart = trans->RestartWithAuth(
5108 credentials, callback_restart.callback());
5109 EXPECT_EQ(ERR_IO_PENDING, rv_restart);
5110 const int rv_restart_complete = callback_restart.WaitForResult();
5111 EXPECT_EQ(OK, rv_restart_complete);
5112 // TODO(cbentzel): This is actually the same response object as before, but
5113 // data has changed.
5114 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
5115 ASSERT_TRUE(response_restart != NULL);
5116 ASSERT_TRUE(response_restart->headers != NULL);
5117 EXPECT_EQ(200, response_restart->headers->response_code());
5118 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
5121 TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
5122 static const unsigned char kPushBodyFrame[] = {
5123 0x00, 0x00, 0x00, 0x02, // header, ID
5124 0x01, 0x00, 0x00, 0x06, // FIN, length
5125 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5127 scoped_ptr<spdy::SpdyFrame>
5128 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5129 scoped_ptr<spdy::SpdyFrame>
5130 stream1_body(ConstructSpdyBodyFrame(1, true));
5131 MockWrite writes[] = {
5132 CreateMockWrite(*stream1_syn, 1),
5135 static const char* const kInitialHeaders[] = {
5136 "url",
5137 "http://www.google.com/foo.dat",
5139 static const char* const kLateHeaders[] = {
5140 "hello",
5141 "bye",
5142 "status",
5143 "200",
5144 "version",
5145 "HTTP/1.1"
5147 scoped_ptr<spdy::SpdyFrame>
5148 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
5149 arraysize(kInitialHeaders) / 2,
5150 false,
5152 LOWEST,
5153 spdy::SYN_STREAM,
5154 spdy::CONTROL_FLAG_NONE,
5155 NULL,
5157 1));
5158 scoped_ptr<spdy::SpdyFrame>
5159 stream2_headers(ConstructSpdyControlFrame(kLateHeaders,
5160 arraysize(kLateHeaders) / 2,
5161 false,
5163 LOWEST,
5164 spdy::HEADERS,
5165 spdy::CONTROL_FLAG_NONE,
5166 NULL,
5168 0));
5170 scoped_ptr<spdy::SpdyFrame>
5171 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5172 MockRead reads[] = {
5173 CreateMockRead(*stream1_reply, 2),
5174 CreateMockRead(*stream2_syn, 3),
5175 CreateMockRead(*stream2_headers, 4),
5176 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5177 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
5178 arraysize(kPushBodyFrame), 6),
5179 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5182 HttpResponseInfo response;
5183 HttpResponseInfo response2;
5184 std::string expected_push_result("pushed");
5185 scoped_ptr<OrderedSocketData> data(new OrderedSocketData(
5186 reads,
5187 arraysize(reads),
5188 writes,
5189 arraysize(writes)));
5190 RunServerPushTest(data.get(),
5191 &response,
5192 &response2,
5193 expected_push_result);
5195 // Verify the SYN_REPLY.
5196 EXPECT_TRUE(response.headers != NULL);
5197 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5199 // Verify the pushed stream.
5200 EXPECT_TRUE(response2.headers != NULL);
5201 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5204 TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
5205 // We push a stream and attempt to claim it before the headers come down.
5206 static const unsigned char kPushBodyFrame[] = {
5207 0x00, 0x00, 0x00, 0x02, // header, ID
5208 0x01, 0x00, 0x00, 0x06, // FIN, length
5209 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5211 scoped_ptr<spdy::SpdyFrame>
5212 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5213 scoped_ptr<spdy::SpdyFrame>
5214 stream1_body(ConstructSpdyBodyFrame(1, true));
5215 MockWrite writes[] = {
5216 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5219 static const char* const kInitialHeaders[] = {
5220 "url",
5221 "http://www.google.com/foo.dat",
5223 static const char* const kLateHeaders[] = {
5224 "hello",
5225 "bye",
5226 "status",
5227 "200",
5228 "version",
5229 "HTTP/1.1"
5231 scoped_ptr<spdy::SpdyFrame>
5232 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
5233 arraysize(kInitialHeaders) / 2,
5234 false,
5236 LOWEST,
5237 spdy::SYN_STREAM,
5238 spdy::CONTROL_FLAG_NONE,
5239 NULL,
5241 1));
5242 scoped_ptr<spdy::SpdyFrame>
5243 stream2_headers(ConstructSpdyControlFrame(kLateHeaders,
5244 arraysize(kLateHeaders) / 2,
5245 false,
5247 LOWEST,
5248 spdy::HEADERS,
5249 spdy::CONTROL_FLAG_NONE,
5250 NULL,
5252 0));
5254 scoped_ptr<spdy::SpdyFrame>
5255 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5256 MockRead reads[] = {
5257 CreateMockRead(*stream1_reply, 1),
5258 CreateMockRead(*stream2_syn, 2),
5259 CreateMockRead(*stream1_body, 3),
5260 CreateMockRead(*stream2_headers, 4),
5261 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
5262 arraysize(kPushBodyFrame), 5),
5263 MockRead(ASYNC, 0, 5), // EOF
5266 HttpResponseInfo response;
5267 HttpResponseInfo response2;
5268 std::string expected_push_result("pushed");
5269 scoped_refptr<DeterministicSocketData> data(new DeterministicSocketData(
5270 reads,
5271 arraysize(reads),
5272 writes,
5273 arraysize(writes)));
5275 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5276 BoundNetLog(), GetParam());
5277 helper.SetDeterministic();
5278 helper.AddDeterministicData(static_cast<DeterministicSocketData*>(data));
5279 helper.RunPreTestSetup();
5281 HttpNetworkTransaction* trans = helper.trans();
5283 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5284 // and the body of the primary stream, but before we've received the HEADERS
5285 // for the pushed stream.
5286 data->SetStop(3);
5288 // Start the transaction.
5289 TestCompletionCallback callback;
5290 int rv = trans->Start(
5291 &CreateGetRequest(), callback.callback(), BoundNetLog());
5292 EXPECT_EQ(ERR_IO_PENDING, rv);
5293 data->Run();
5294 rv = callback.WaitForResult();
5295 EXPECT_EQ(0, rv);
5297 // Request the pushed path. At this point, we've received the push, but the
5298 // headers are not yet complete.
5299 scoped_ptr<HttpNetworkTransaction> trans2(
5300 new HttpNetworkTransaction(helper.session()));
5301 rv = trans2->Start(
5302 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5303 EXPECT_EQ(ERR_IO_PENDING, rv);
5304 data->RunFor(3);
5305 MessageLoop::current()->RunAllPending();
5307 // Read the server push body.
5308 std::string result2;
5309 ReadResult(trans2.get(), data.get(), &result2);
5310 // Read the response body.
5311 std::string result;
5312 ReadResult(trans, data, &result);
5314 // Verify that we consumed all test data.
5315 EXPECT_TRUE(data->at_read_eof());
5316 EXPECT_TRUE(data->at_write_eof());
5318 // Verify that the received push data is same as the expected push data.
5319 EXPECT_EQ(result2.compare(expected_push_result), 0)
5320 << "Received data: "
5321 << result2
5322 << "||||| Expected data: "
5323 << expected_push_result;
5325 // Verify the SYN_REPLY.
5326 // Copy the response info, because trans goes away.
5327 response = *trans->GetResponseInfo();
5328 response2 = *trans2->GetResponseInfo();
5330 VerifyStreamsClosed(helper);
5332 // Verify the SYN_REPLY.
5333 EXPECT_TRUE(response.headers != NULL);
5334 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5336 // Verify the pushed stream.
5337 EXPECT_TRUE(response2.headers != NULL);
5338 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5341 TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
5342 // We push a stream and attempt to claim it before the headers come down.
5343 static const unsigned char kPushBodyFrame[] = {
5344 0x00, 0x00, 0x00, 0x02, // header, ID
5345 0x01, 0x00, 0x00, 0x06, // FIN, length
5346 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5348 scoped_ptr<spdy::SpdyFrame>
5349 stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5350 scoped_ptr<spdy::SpdyFrame>
5351 stream1_body(ConstructSpdyBodyFrame(1, true));
5352 MockWrite writes[] = {
5353 CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5356 static const char* const kInitialHeaders[] = {
5357 "url",
5358 "http://www.google.com/foo.dat",
5360 static const char* const kMiddleHeaders[] = {
5361 "hello",
5362 "bye",
5364 static const char* const kLateHeaders[] = {
5365 "status",
5366 "200",
5367 "version",
5368 "HTTP/1.1"
5370 scoped_ptr<spdy::SpdyFrame>
5371 stream2_syn(ConstructSpdyControlFrame(kInitialHeaders,
5372 arraysize(kInitialHeaders) / 2,
5373 false,
5375 LOWEST,
5376 spdy::SYN_STREAM,
5377 spdy::CONTROL_FLAG_NONE,
5378 NULL,
5380 1));
5381 scoped_ptr<spdy::SpdyFrame>
5382 stream2_headers1(ConstructSpdyControlFrame(kMiddleHeaders,
5383 arraysize(kMiddleHeaders) / 2,
5384 false,
5386 LOWEST,
5387 spdy::HEADERS,
5388 spdy::CONTROL_FLAG_NONE,
5389 NULL,
5391 0));
5392 scoped_ptr<spdy::SpdyFrame>
5393 stream2_headers2(ConstructSpdyControlFrame(kLateHeaders,
5394 arraysize(kLateHeaders) / 2,
5395 false,
5397 LOWEST,
5398 spdy::HEADERS,
5399 spdy::CONTROL_FLAG_NONE,
5400 NULL,
5402 0));
5404 scoped_ptr<spdy::SpdyFrame>
5405 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5406 MockRead reads[] = {
5407 CreateMockRead(*stream1_reply, 1),
5408 CreateMockRead(*stream2_syn, 2),
5409 CreateMockRead(*stream1_body, 3),
5410 CreateMockRead(*stream2_headers1, 4),
5411 CreateMockRead(*stream2_headers2, 5),
5412 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
5413 arraysize(kPushBodyFrame), 6),
5414 MockRead(ASYNC, 0, 6), // EOF
5417 HttpResponseInfo response;
5418 HttpResponseInfo response2;
5419 std::string expected_push_result("pushed");
5420 scoped_refptr<DeterministicSocketData> data(new DeterministicSocketData(
5421 reads,
5422 arraysize(reads),
5423 writes,
5424 arraysize(writes)));
5426 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5427 BoundNetLog(), GetParam());
5428 helper.SetDeterministic();
5429 helper.AddDeterministicData(static_cast<DeterministicSocketData*>(data));
5430 helper.RunPreTestSetup();
5432 HttpNetworkTransaction* trans = helper.trans();
5434 // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5435 // the first HEADERS frame, and the body of the primary stream, but before
5436 // we've received the final HEADERS for the pushed stream.
5437 data->SetStop(4);
5439 // Start the transaction.
5440 TestCompletionCallback callback;
5441 int rv = trans->Start(
5442 &CreateGetRequest(), callback.callback(), BoundNetLog());
5443 EXPECT_EQ(ERR_IO_PENDING, rv);
5444 data->Run();
5445 rv = callback.WaitForResult();
5446 EXPECT_EQ(0, rv);
5448 // Request the pushed path. At this point, we've received the push, but the
5449 // headers are not yet complete.
5450 scoped_ptr<HttpNetworkTransaction> trans2(
5451 new HttpNetworkTransaction(helper.session()));
5452 rv = trans2->Start(
5453 &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5454 EXPECT_EQ(ERR_IO_PENDING, rv);
5455 data->RunFor(3);
5456 MessageLoop::current()->RunAllPending();
5458 // Read the server push body.
5459 std::string result2;
5460 ReadResult(trans2.get(), data, &result2);
5461 // Read the response body.
5462 std::string result;
5463 ReadResult(trans, data, &result);
5465 // Verify that we consumed all test data.
5466 EXPECT_TRUE(data->at_read_eof());
5467 EXPECT_TRUE(data->at_write_eof());
5469 // Verify that the received push data is same as the expected push data.
5470 EXPECT_EQ(result2.compare(expected_push_result), 0)
5471 << "Received data: "
5472 << result2
5473 << "||||| Expected data: "
5474 << expected_push_result;
5476 // Verify the SYN_REPLY.
5477 // Copy the response info, because trans goes away.
5478 response = *trans->GetResponseInfo();
5479 response2 = *trans2->GetResponseInfo();
5481 VerifyStreamsClosed(helper);
5483 // Verify the SYN_REPLY.
5484 EXPECT_TRUE(response.headers != NULL);
5485 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5487 // Verify the pushed stream.
5488 EXPECT_TRUE(response2.headers != NULL);
5489 EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5491 // Verify we got all the headers
5492 EXPECT_TRUE(response2.headers->HasHeaderValue(
5493 "url",
5494 "http://www.google.com/foo.dat"));
5495 EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5496 EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
5497 EXPECT_TRUE(response2.headers->HasHeaderValue("version", "HTTP/1.1"));
5500 TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
5501 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5502 MockWrite writes[] = { CreateMockWrite(*req) };
5504 static const char* const kInitialHeaders[] = {
5505 "status",
5506 "200 OK",
5507 "version",
5508 "HTTP/1.1"
5510 static const char* const kLateHeaders[] = {
5511 "hello",
5512 "bye",
5514 scoped_ptr<spdy::SpdyFrame>
5515 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
5516 arraysize(kInitialHeaders) / 2,
5517 false,
5519 LOWEST,
5520 spdy::SYN_REPLY,
5521 spdy::CONTROL_FLAG_NONE,
5522 NULL,
5524 0));
5525 scoped_ptr<spdy::SpdyFrame>
5526 stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
5527 arraysize(kLateHeaders) / 2,
5528 false,
5530 LOWEST,
5531 spdy::HEADERS,
5532 spdy::CONTROL_FLAG_NONE,
5533 NULL,
5535 0));
5536 scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, true));
5537 MockRead reads[] = {
5538 CreateMockRead(*stream1_reply),
5539 CreateMockRead(*stream1_headers),
5540 CreateMockRead(*stream1_body),
5541 MockRead(ASYNC, 0, 0) // EOF
5544 scoped_ptr<DelayedSocketData> data(
5545 new DelayedSocketData(1, reads, arraysize(reads),
5546 writes, arraysize(writes)));
5547 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5548 BoundNetLog(), GetParam());
5549 helper.RunToCompletion(data.get());
5550 TransactionHelperResult out = helper.output();
5551 EXPECT_EQ(OK, out.rv);
5552 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5553 EXPECT_EQ("hello!", out.response_data);
5556 TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
5557 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5558 MockWrite writes[] = { CreateMockWrite(*req) };
5560 static const char* const kInitialHeaders[] = {
5561 "status",
5562 "200 OK",
5563 "version",
5564 "HTTP/1.1"
5566 static const char* const kLateHeaders[] = {
5567 "hello",
5568 "bye",
5570 scoped_ptr<spdy::SpdyFrame>
5571 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
5572 arraysize(kInitialHeaders) / 2,
5573 false,
5575 LOWEST,
5576 spdy::SYN_REPLY,
5577 spdy::CONTROL_FLAG_NONE,
5578 NULL,
5580 0));
5581 scoped_ptr<spdy::SpdyFrame>
5582 stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
5583 arraysize(kLateHeaders) / 2,
5584 false,
5586 LOWEST,
5587 spdy::HEADERS,
5588 spdy::CONTROL_FLAG_NONE,
5589 NULL,
5591 0));
5592 scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, false));
5593 scoped_ptr<spdy::SpdyFrame> stream1_body2(ConstructSpdyBodyFrame(1, true));
5594 MockRead reads[] = {
5595 CreateMockRead(*stream1_reply),
5596 CreateMockRead(*stream1_body),
5597 CreateMockRead(*stream1_headers),
5598 CreateMockRead(*stream1_body2),
5599 MockRead(ASYNC, 0, 0) // EOF
5602 scoped_ptr<DelayedSocketData> data(
5603 new DelayedSocketData(1, reads, arraysize(reads),
5604 writes, arraysize(writes)));
5605 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5606 BoundNetLog(), GetParam());
5607 helper.RunToCompletion(data.get());
5608 TransactionHelperResult out = helper.output();
5609 EXPECT_EQ(OK, out.rv);
5610 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
5611 EXPECT_EQ("hello!hello!", out.response_data);
5614 TEST_P(SpdyNetworkTransactionTest, SynReplyWithDuplicateLateHeaders) {
5615 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5616 MockWrite writes[] = { CreateMockWrite(*req) };
5618 static const char* const kInitialHeaders[] = {
5619 "status",
5620 "200 OK",
5621 "version",
5622 "HTTP/1.1"
5624 static const char* const kLateHeaders[] = {
5625 "status",
5626 "500 Server Error",
5628 scoped_ptr<spdy::SpdyFrame>
5629 stream1_reply(ConstructSpdyControlFrame(kInitialHeaders,
5630 arraysize(kInitialHeaders) / 2,
5631 false,
5633 LOWEST,
5634 spdy::SYN_REPLY,
5635 spdy::CONTROL_FLAG_NONE,
5636 NULL,
5638 0));
5639 scoped_ptr<spdy::SpdyFrame>
5640 stream1_headers(ConstructSpdyControlFrame(kLateHeaders,
5641 arraysize(kLateHeaders) / 2,
5642 false,
5644 LOWEST,
5645 spdy::HEADERS,
5646 spdy::CONTROL_FLAG_NONE,
5647 NULL,
5649 0));
5650 scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, false));
5651 scoped_ptr<spdy::SpdyFrame> stream1_body2(ConstructSpdyBodyFrame(1, true));
5652 MockRead reads[] = {
5653 CreateMockRead(*stream1_reply),
5654 CreateMockRead(*stream1_body),
5655 CreateMockRead(*stream1_headers),
5656 CreateMockRead(*stream1_body2),
5657 MockRead(ASYNC, 0, 0) // EOF
5660 scoped_ptr<DelayedSocketData> data(
5661 new DelayedSocketData(1, reads, arraysize(reads),
5662 writes, arraysize(writes)));
5663 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5664 BoundNetLog(), GetParam());
5665 helper.RunToCompletion(data.get());
5666 TransactionHelperResult out = helper.output();
5667 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5670 TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
5671 // In this test we want to verify that we can't accidentally push content
5672 // which can't be pushed by this content server.
5673 // This test assumes that:
5674 // - if we're requesting http://www.foo.com/barbaz
5675 // - the browser has made a connection to "www.foo.com".
5677 // A list of the URL to fetch, followed by the URL being pushed.
5678 static const char* const kTestCases[] = {
5679 "http://www.google.com/foo.html",
5680 "http://www.google.com:81/foo.js", // Bad port
5682 "http://www.google.com/foo.html",
5683 "https://www.google.com/foo.js", // Bad protocol
5685 "http://www.google.com/foo.html",
5686 "ftp://www.google.com/foo.js", // Invalid Protocol
5688 "http://www.google.com/foo.html",
5689 "http://blat.www.google.com/foo.js", // Cross subdomain
5691 "http://www.google.com/foo.html",
5692 "http://www.foo.com/foo.js", // Cross domain
5696 static const unsigned char kPushBodyFrame[] = {
5697 0x00, 0x00, 0x00, 0x02, // header, ID
5698 0x01, 0x00, 0x00, 0x06, // FIN, length
5699 'p', 'u', 's', 'h', 'e', 'd' // "pushed"
5702 for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
5703 const char* url_to_fetch = kTestCases[index];
5704 const char* url_to_push = kTestCases[index + 1];
5706 scoped_ptr<spdy::SpdyFrame>
5707 stream1_syn(ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
5708 scoped_ptr<spdy::SpdyFrame>
5709 stream1_body(ConstructSpdyBodyFrame(1, true));
5710 scoped_ptr<spdy::SpdyFrame> push_rst(
5711 ConstructSpdyRstStream(2, spdy::REFUSED_STREAM));
5712 MockWrite writes[] = {
5713 CreateMockWrite(*stream1_syn, 1),
5714 CreateMockWrite(*push_rst, 4),
5717 scoped_ptr<spdy::SpdyFrame>
5718 stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1));
5719 scoped_ptr<spdy::SpdyFrame>
5720 stream2_syn(ConstructSpdyPush(NULL,
5724 url_to_push));
5725 scoped_ptr<spdy::SpdyFrame> rst(
5726 ConstructSpdyRstStream(2, spdy::CANCEL));
5728 MockRead reads[] = {
5729 CreateMockRead(*stream1_reply, 2),
5730 CreateMockRead(*stream2_syn, 3),
5731 CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5732 MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame),
5733 arraysize(kPushBodyFrame), 6),
5734 MockRead(ASYNC, ERR_IO_PENDING, 7), // Force a pause
5737 HttpResponseInfo response;
5738 scoped_ptr<OrderedSocketData> data(new OrderedSocketData(
5739 reads,
5740 arraysize(reads),
5741 writes,
5742 arraysize(writes)));
5744 HttpRequestInfo request;
5745 request.method = "GET";
5746 request.url = GURL(url_to_fetch);
5747 request.load_flags = 0;
5748 NormalSpdyTransactionHelper helper(request,
5749 BoundNetLog(), GetParam());
5750 helper.RunPreTestSetup();
5751 helper.AddData(data.get());
5753 HttpNetworkTransaction* trans = helper.trans();
5755 // Start the transaction with basic parameters.
5756 TestCompletionCallback callback;
5758 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5759 EXPECT_EQ(ERR_IO_PENDING, rv);
5760 rv = callback.WaitForResult();
5762 // Read the response body.
5763 std::string result;
5764 ReadResult(trans, data.get(), &result);
5766 // Verify that we consumed all test data.
5767 EXPECT_TRUE(data->at_read_eof());
5768 EXPECT_TRUE(data->at_write_eof());
5770 // Verify the SYN_REPLY.
5771 // Copy the response info, because trans goes away.
5772 response = *trans->GetResponseInfo();
5774 VerifyStreamsClosed(helper);
5776 // Verify the SYN_REPLY.
5777 EXPECT_TRUE(response.headers != NULL);
5778 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5782 TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
5783 // Construct the request.
5784 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
5785 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
5786 MockWrite writes[] = {
5787 CreateMockWrite(*req, 1),
5788 CreateMockWrite(*req2, 3),
5791 scoped_ptr<spdy::SpdyFrame> refused(
5792 ConstructSpdyRstStream(1, spdy::REFUSED_STREAM));
5793 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 3));
5794 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(3, true));
5795 MockRead reads[] = {
5796 CreateMockRead(*refused, 2),
5797 CreateMockRead(*resp, 4),
5798 CreateMockRead(*body, 5),
5799 MockRead(ASYNC, 0, 6) // EOF
5802 scoped_ptr<OrderedSocketData> data(
5803 new OrderedSocketData(reads, arraysize(reads),
5804 writes, arraysize(writes)));
5805 NormalSpdyTransactionHelper helper(CreateGetRequest(),
5806 BoundNetLog(), GetParam());
5808 helper.RunPreTestSetup();
5809 helper.AddData(data.get());
5811 HttpNetworkTransaction* trans = helper.trans();
5813 // Start the transaction with basic parameters.
5814 TestCompletionCallback callback;
5815 int rv = trans->Start(
5816 &CreateGetRequest(), callback.callback(), BoundNetLog());
5817 EXPECT_EQ(ERR_IO_PENDING, rv);
5818 rv = callback.WaitForResult();
5819 EXPECT_EQ(OK, rv);
5821 // Verify that we consumed all test data.
5822 EXPECT_TRUE(data->at_read_eof()) << "Read count: "
5823 << data->read_count()
5824 << " Read index: "
5825 << data->read_index();
5826 EXPECT_TRUE(data->at_write_eof()) << "Write count: "
5827 << data->write_count()
5828 << " Write index: "
5829 << data->write_index();
5831 // Verify the SYN_REPLY.
5832 HttpResponseInfo response = *trans->GetResponseInfo();
5833 EXPECT_TRUE(response.headers != NULL);
5834 EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5837 } // namespace net