| OLD | NEW | 
|---|
|  | (Empty) | 
| 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. |  | 
| 4 |  | 
| 5 #include "net/http/http_network_transaction.h" |  | 
| 6 |  | 
| 7 #include <string> |  | 
| 8 #include <vector> |  | 
| 9 |  | 
| 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" |  | 
| 24 |  | 
| 25 //----------------------------------------------------------------------------- |  | 
| 26 |  | 
| 27 namespace net { |  | 
| 28 |  | 
| 29 enum SpdyNetworkTransactionTestTypes { |  | 
| 30   SPDYNPN, |  | 
| 31   SPDYNOSSL, |  | 
| 32   SPDYSSL, |  | 
| 33 }; |  | 
| 34 class SpdyNetworkTransactionTest |  | 
| 35     : public ::testing::TestWithParam<SpdyNetworkTransactionTestTypes> { |  | 
| 36  protected: |  | 
| 37 |  | 
| 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; |  | 
| 44   } |  | 
| 45 |  | 
| 46   virtual void TearDown() { |  | 
| 47     // Empty the current queue. |  | 
| 48     MessageLoop::current()->RunAllPending(); |  | 
| 49   } |  | 
| 50 |  | 
| 51   struct TransactionHelperResult { |  | 
| 52     int rv; |  | 
| 53     std::string status_line; |  | 
| 54     std::string response_data; |  | 
| 55     HttpResponseInfo response_info; |  | 
| 56   }; |  | 
| 57 |  | 
| 58   void EnableCompression(bool enabled) { |  | 
| 59     spdy::SpdyFramer::set_enable_compression_default(enabled); |  | 
| 60   } |  | 
| 61 |  | 
| 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(); |  | 
| 86             } |  | 
| 87           } |  | 
| 88 |  | 
| 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. |  | 
| 96 |  | 
| 97       // Forcefully close existing sessions here. |  | 
| 98       session()->spdy_session_pool()->CloseAllSessions(); |  | 
| 99     } |  | 
| 100 |  | 
| 101     void SetDeterministic() { |  | 
| 102       session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic( |  | 
| 103           session_deps_.get()); |  | 
| 104       deterministic_ = true; |  | 
| 105     } |  | 
| 106 |  | 
| 107     void SetSpdyDisabled() { |  | 
| 108       spdy_enabled_ = false; |  | 
| 109     } |  | 
| 110 |  | 
| 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); |  | 
| 120 |  | 
| 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"); |  | 
| 125 |  | 
| 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::SetNextProtos(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(); |  | 
| 144       } |  | 
| 145 |  | 
| 146       // We're now ready to use SSL-npn SPDY. |  | 
| 147       trans_.reset(new HttpNetworkTransaction(session_)); |  | 
| 148     } |  | 
| 149 |  | 
| 150     // Start the transaction, read some data, finish. |  | 
| 151     void RunDefaultTest() { |  | 
| 152       output_.rv = trans_->Start(&request_, callback.callback(), log_); |  | 
| 153 |  | 
| 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; |  | 
| 158 |  | 
| 159       output_.rv = callback.WaitForResult(); |  | 
| 160       if (output_.rv != OK) { |  | 
| 161         session_->spdy_session_pool()->CloseCurrentSessions(); |  | 
| 162         return; |  | 
| 163       } |  | 
| 164 |  | 
| 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); |  | 
| 175       } |  | 
| 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); |  | 
| 181       } |  | 
| 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); |  | 
| 187     } |  | 
| 188 |  | 
| 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(); |  | 
| 203       } |  | 
| 204     } |  | 
| 205 |  | 
| 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(); |  | 
| 220       } |  | 
| 221     } |  | 
| 222 |  | 
| 223     void RunToCompletion(StaticSocketDataProvider* data) { |  | 
| 224       RunPreTestSetup(); |  | 
| 225       AddData(data); |  | 
| 226       RunDefaultTest(); |  | 
| 227       VerifyDataConsumed(); |  | 
| 228     } |  | 
| 229 |  | 
| 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); |  | 
| 237       } |  | 
| 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); |  | 
| 252       } |  | 
| 253     } |  | 
| 254 |  | 
| 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); |  | 
| 262       } |  | 
| 263       ssl_vector_.push_back(ssl_); |  | 
| 264       if (test_type_ == SPDYNPN || test_type_ == SPDYSSL) { |  | 
| 265         session_deps_->deterministic_socket_factory-> |  | 
| 266             AddSSLSocketDataProvider(ssl_.get()); |  | 
| 267       } |  | 
| 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); |  | 
| 280       } |  | 
| 281     } |  | 
| 282 |  | 
| 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); |  | 
| 288     } |  | 
| 289     void AddDataNoSSL(DeterministicSocketData* data) { |  | 
| 290       DCHECK(deterministic_); |  | 
| 291       session_deps_->deterministic_socket_factory->AddSocketDataProvider(data); |  | 
| 292     } |  | 
| 293 |  | 
| 294     void SetSession(const scoped_refptr<HttpNetworkSession>& session) { |  | 
| 295       session_ = session; |  | 
| 296     } |  | 
| 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_; |  | 
| 303     } |  | 
| 304     scoped_ptr<SpdySessionDependencies>& session_deps() { |  | 
| 305       return session_deps_; |  | 
| 306     } |  | 
| 307     int port() const { return port_; } |  | 
| 308     SpdyNetworkTransactionTestTypes test_type() const { return test_type_; } |  | 
| 309 |  | 
| 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_; |  | 
| 333   }; |  | 
| 334 |  | 
| 335   void ConnectStatusHelperWithExpectedStatus(const MockRead& status, |  | 
| 336                                              int expected_status); |  | 
| 337 |  | 
| 338   void ConnectStatusHelper(const MockRead& status); |  | 
| 339 |  | 
| 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_; |  | 
| 345   } |  | 
| 346 |  | 
| 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; |  | 
| 353     } |  | 
| 354     return google_get_request_; |  | 
| 355   } |  | 
| 356 |  | 
| 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; |  | 
| 364     } |  | 
| 365     return google_get_request_; |  | 
| 366   } |  | 
| 367 |  | 
| 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; |  | 
| 376     } |  | 
| 377     return google_post_request_; |  | 
| 378   } |  | 
| 379 |  | 
| 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; |  | 
| 391     } |  | 
| 392     return google_chunked_post_request_; |  | 
| 393   } |  | 
| 394 |  | 
| 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; |  | 
| 403 |  | 
| 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(); |  | 
| 415         } |  | 
| 416         rv = callback.WaitForResult(); |  | 
| 417       } else if (rv <= 0) { |  | 
| 418         break; |  | 
| 419       } |  | 
| 420       result->append(buf->data(), rv); |  | 
| 421       bytes_read += rv; |  | 
| 422     } |  | 
| 423     return bytes_read; |  | 
| 424   } |  | 
| 425 |  | 
| 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()); |  | 
| 442   } |  | 
| 443 |  | 
| 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); |  | 
| 452 |  | 
| 453     HttpNetworkTransaction* trans = helper.trans(); |  | 
| 454 |  | 
| 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(); |  | 
| 461 |  | 
| 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(); |  | 
| 469 |  | 
| 470     // The data for the pushed path may be coming in more than 1 packet. Compile |  | 
| 471     // the results into a single string. |  | 
| 472 |  | 
| 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); |  | 
| 479 |  | 
| 480     // Verify that we consumed all test data. |  | 
| 481     EXPECT_TRUE(data->at_read_eof()); |  | 
| 482     EXPECT_TRUE(data->at_write_eof()); |  | 
| 483 |  | 
| 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; |  | 
| 489 |  | 
| 490     // Verify the SYN_REPLY. |  | 
| 491     // Copy the response info, because trans goes away. |  | 
| 492     *response = *trans->GetResponseInfo(); |  | 
| 493     *push_response = *trans2->GetResponseInfo(); |  | 
| 494 |  | 
| 495     VerifyStreamsClosed(helper); |  | 
| 496   } |  | 
| 497 |  | 
| 498   static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper, |  | 
| 499                                     int result) { |  | 
| 500     helper->ResetTrans(); |  | 
| 501   } |  | 
| 502 |  | 
| 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(); |  | 
| 516   } |  | 
| 517 |  | 
| 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_; |  | 
| 526 }; |  | 
| 527 |  | 
| 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)); |  | 
| 534 |  | 
| 535 |  | 
| 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)); |  | 
| 542 } |  | 
| 543 |  | 
| 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) }; |  | 
| 548 |  | 
| 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 |  | 
| 555   }; |  | 
| 556 |  | 
| 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); |  | 
| 567 } |  | 
| 568 |  | 
| 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) }; |  | 
| 575 |  | 
| 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(); |  | 
| 597     } |  | 
| 598 |  | 
| 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 |  | 
| 605     }; |  | 
| 606 |  | 
| 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; |  | 
| 612 |  | 
| 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); |  | 
| 619   } |  | 
| 620 } |  | 
| 621 |  | 
| 622 // Start three gets simultaniously; making sure that multiplexed |  | 
| 623 // streams work properly. |  | 
| 624 |  | 
| 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. |  | 
| 628 |  | 
| 629 // TODO(gavinp): create a working generalized TransactionHelper that |  | 
| 630 // can allow multiple streams in flight. |  | 
| 631 |  | 
| 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)); |  | 
| 637 |  | 
| 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)); |  | 
| 642 |  | 
| 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)); |  | 
| 647 |  | 
| 648   MockWrite writes[] = { |  | 
| 649     CreateMockWrite(*req), |  | 
| 650     CreateMockWrite(*req2), |  | 
| 651     CreateMockWrite(*req3), |  | 
| 652   }; |  | 
| 653   MockRead reads[] = { |  | 
| 654     CreateMockRead(*resp, 1), |  | 
| 655     CreateMockRead(*body), |  | 
| 656     CreateMockRead(*resp2, 4), |  | 
| 657     CreateMockRead(*body2), |  | 
| 658     CreateMockRead(*resp3, 7), |  | 
| 659     CreateMockRead(*body3), |  | 
| 660 |  | 
| 661     CreateMockRead(*fbody), |  | 
| 662     CreateMockRead(*fbody2), |  | 
| 663     CreateMockRead(*fbody3), |  | 
| 664 |  | 
| 665     MockRead(ASYNC, 0, 0),  // EOF |  | 
| 666   }; |  | 
| 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)); |  | 
| 672 |  | 
| 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())); |  | 
| 689 |  | 
| 690   TestCompletionCallback callback1; |  | 
| 691   TestCompletionCallback callback2; |  | 
| 692   TestCompletionCallback callback3; |  | 
| 693 |  | 
| 694   HttpRequestInfo httpreq1 = CreateGetRequest(); |  | 
| 695   HttpRequestInfo httpreq2 = CreateGetRequest(); |  | 
| 696   HttpRequestInfo httpreq3 = CreateGetRequest(); |  | 
| 697 |  | 
| 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); |  | 
| 704 |  | 
| 705   out.rv = callback1.WaitForResult(); |  | 
| 706   ASSERT_EQ(OK, out.rv); |  | 
| 707   out.rv = callback3.WaitForResult(); |  | 
| 708   ASSERT_EQ(OK, out.rv); |  | 
| 709 |  | 
| 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; |  | 
| 715 |  | 
| 716   trans2->GetResponseInfo(); |  | 
| 717 |  | 
| 718   out.rv = ReadTransaction(trans1.get(), &out.response_data); |  | 
| 719   helper.VerifyDataConsumed(); |  | 
| 720   EXPECT_EQ(OK, out.rv); |  | 
| 721 |  | 
| 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); |  | 
| 725 } |  | 
| 726 |  | 
| 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)); |  | 
| 732 |  | 
| 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)); |  | 
| 737 |  | 
| 738   MockWrite writes[] = { |  | 
| 739     CreateMockWrite(*req), |  | 
| 740     CreateMockWrite(*req2), |  | 
| 741   }; |  | 
| 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 |  | 
| 750   }; |  | 
| 751   scoped_ptr<OrderedSocketData> data( |  | 
| 752       new OrderedSocketData(reads, arraysize(reads), |  | 
| 753                             writes, arraysize(writes))); |  | 
| 754 |  | 
| 755   MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); |  | 
| 756 |  | 
| 757   scoped_ptr<OrderedSocketData> data_placeholder( |  | 
| 758       new OrderedSocketData(NULL, 0, NULL, 0)); |  | 
| 759   data_placeholder->set_connect_data(never_finishing_connect); |  | 
| 760 |  | 
| 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())); |  | 
| 774 |  | 
| 775   TestCompletionCallback callback1; |  | 
| 776   TestCompletionCallback callback2; |  | 
| 777 |  | 
| 778   HttpRequestInfo httpreq1 = CreateGetRequest(); |  | 
| 779   HttpRequestInfo httpreq2 = CreateGetRequest(); |  | 
| 780 |  | 
| 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); |  | 
| 785 |  | 
| 786   out.rv = callback1.WaitForResult(); |  | 
| 787   ASSERT_EQ(OK, out.rv); |  | 
| 788   out.rv = callback2.WaitForResult(); |  | 
| 789   ASSERT_EQ(OK, out.rv); |  | 
| 790 |  | 
| 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); |  | 
| 800 |  | 
| 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); |  | 
| 810 |  | 
| 811   helper.VerifyDataConsumed(); |  | 
| 812 } |  | 
| 813 |  | 
| 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)); |  | 
| 819 |  | 
| 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)); |  | 
| 824 |  | 
| 825   MockWrite writes[] = { |  | 
| 826     CreateMockWrite(*req), |  | 
| 827     CreateMockWrite(*req2), |  | 
| 828   }; |  | 
| 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 |  | 
| 837   }; |  | 
| 838   scoped_ptr<OrderedSocketData> preconnect_data( |  | 
| 839       new OrderedSocketData(reads, arraysize(reads), |  | 
| 840                             writes, arraysize(writes))); |  | 
| 841 |  | 
| 842   MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING); |  | 
| 843 |  | 
| 844   scoped_ptr<OrderedSocketData> data_placeholder( |  | 
| 845       new OrderedSocketData(NULL, 0, NULL, 0)); |  | 
| 846   data_placeholder->set_connect_data(never_finishing_connect); |  | 
| 847 |  | 
| 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()); |  | 
| 858 |  | 
| 859   scoped_ptr<HttpNetworkTransaction> trans1( |  | 
| 860       new HttpNetworkTransaction(helper.session())); |  | 
| 861   scoped_ptr<HttpNetworkTransaction> trans2( |  | 
| 862       new HttpNetworkTransaction(helper.session())); |  | 
| 863 |  | 
| 864   TestCompletionCallback callback1; |  | 
| 865   TestCompletionCallback callback2; |  | 
| 866 |  | 
| 867   HttpRequestInfo httpreq = CreateGetRequest(); |  | 
| 868 |  | 
| 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(); |  | 
| 876   } |  | 
| 877 |  | 
| 878   http_stream_factory->PreconnectStreams( |  | 
| 879       1, httpreq, preconnect_ssl_config, preconnect_ssl_config); |  | 
| 880 |  | 
| 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); |  | 
| 885 |  | 
| 886   out.rv = callback1.WaitForResult(); |  | 
| 887   ASSERT_EQ(OK, out.rv); |  | 
| 888   out.rv = callback2.WaitForResult(); |  | 
| 889   ASSERT_EQ(OK, out.rv); |  | 
| 890 |  | 
| 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); |  | 
| 900 |  | 
| 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); |  | 
| 910 |  | 
| 911   helper.VerifyDataConsumed(); |  | 
| 912 } |  | 
| 913 |  | 
| 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)); |  | 
| 925 |  | 
| 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)); |  | 
| 930 |  | 
| 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)); |  | 
| 935 |  | 
| 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; |  | 
| 940 |  | 
| 941   settings.push_back(spdy::SpdySetting(id, max_concurrent_streams)); |  | 
| 942   scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings)); |  | 
| 943 |  | 
| 944   MockWrite writes[] = { |  | 
| 945     CreateMockWrite(*req), |  | 
| 946     CreateMockWrite(*req2), |  | 
| 947     CreateMockWrite(*req3), |  | 
| 948   }; |  | 
| 949 |  | 
| 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), |  | 
| 961 |  | 
| 962     MockRead(ASYNC, 0, 0),  // EOF |  | 
| 963   }; |  | 
| 964 |  | 
| 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)); |  | 
| 970 |  | 
| 971   BoundNetLog log; |  | 
| 972   TransactionHelperResult out; |  | 
| 973   { |  | 
| 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())); |  | 
| 988 |  | 
| 989     TestCompletionCallback callback1; |  | 
| 990     TestCompletionCallback callback2; |  | 
| 991     TestCompletionCallback callback3; |  | 
| 992 |  | 
| 993     HttpRequestInfo httpreq1 = CreateGetRequest(); |  | 
| 994     HttpRequestInfo httpreq2 = CreateGetRequest(); |  | 
| 995     HttpRequestInfo httpreq3 = CreateGetRequest(); |  | 
| 996 |  | 
| 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); |  | 
| 1003 |  | 
| 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 |  | 
| 1011 |  | 
| 1012     out.rv = callback3.WaitForResult(); |  | 
| 1013     ASSERT_EQ(OK, out.rv); |  | 
| 1014 |  | 
| 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); |  | 
| 1025 |  | 
| 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); |  | 
| 1033 |  | 
| 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); |  | 
| 1041 |  | 
| 1042     helper.VerifyDataConsumed(); |  | 
| 1043   } |  | 
| 1044   EXPECT_EQ(OK, out.rv); |  | 
| 1045 } |  | 
| 1046 |  | 
| 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)); |  | 
| 1058 |  | 
| 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)); |  | 
| 1063 |  | 
| 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)); |  | 
| 1068 |  | 
| 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)); |  | 
| 1073 |  | 
| 1074 |  | 
| 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; |  | 
| 1079 |  | 
| 1080   settings.push_back(spdy::SpdySetting(id, max_concurrent_streams)); |  | 
| 1081   scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings)); |  | 
| 1082 |  | 
| 1083   MockWrite writes[] = { CreateMockWrite(*req), |  | 
| 1084     CreateMockWrite(*req2), |  | 
| 1085     CreateMockWrite(*req4), |  | 
| 1086     CreateMockWrite(*req3), |  | 
| 1087   }; |  | 
| 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), |  | 
| 1101 |  | 
| 1102     MockRead(ASYNC, 0, 0),  // EOF |  | 
| 1103   }; |  | 
| 1104 |  | 
| 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)); |  | 
| 1110 |  | 
| 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())); |  | 
| 1130 |  | 
| 1131   TestCompletionCallback callback1; |  | 
| 1132   TestCompletionCallback callback2; |  | 
| 1133   TestCompletionCallback callback3; |  | 
| 1134   TestCompletionCallback callback4; |  | 
| 1135 |  | 
| 1136   HttpRequestInfo httpreq1 = CreateGetRequest(); |  | 
| 1137   HttpRequestInfo httpreq2 = CreateGetRequest(); |  | 
| 1138   HttpRequestInfo httpreq3 = CreateGetRequest(); |  | 
| 1139   HttpRequestInfo httpreq4 = CreateGetRequest(); |  | 
| 1140   httpreq4.priority = HIGHEST; |  | 
| 1141 |  | 
| 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); |  | 
| 1148 |  | 
| 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); |  | 
| 1155 |  | 
| 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 |  | 
| 1159 |  | 
| 1160   out.rv = callback3.WaitForResult(); |  | 
| 1161   ASSERT_EQ(OK, out.rv); |  | 
| 1162 |  | 
| 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); |  | 
| 1172 |  | 
| 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); |  | 
| 1180 |  | 
| 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); |  | 
| 1190 |  | 
| 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); |  | 
| 1202 } |  | 
| 1203 |  | 
| 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)); |  | 
| 1214 |  | 
| 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)); |  | 
| 1219 |  | 
| 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; |  | 
| 1224 |  | 
| 1225   settings.push_back(spdy::SpdySetting(id, max_concurrent_streams)); |  | 
| 1226   scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings)); |  | 
| 1227 |  | 
| 1228   MockWrite writes[] = { CreateMockWrite(*req), |  | 
| 1229     CreateMockWrite(*req2), |  | 
| 1230   }; |  | 
| 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 |  | 
| 1240   }; |  | 
| 1241 |  | 
| 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)); |  | 
| 1247 |  | 
| 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())); |  | 
| 1264 |  | 
| 1265   TestCompletionCallback callback1; |  | 
| 1266   TestCompletionCallback callback2; |  | 
| 1267   TestCompletionCallback callback3; |  | 
| 1268 |  | 
| 1269   HttpRequestInfo httpreq1 = CreateGetRequest(); |  | 
| 1270   HttpRequestInfo httpreq2 = CreateGetRequest(); |  | 
| 1271   HttpRequestInfo httpreq3 = CreateGetRequest(); |  | 
| 1272 |  | 
| 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); |  | 
| 1279 |  | 
| 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); |  | 
| 1287 |  | 
| 1288   EXPECT_EQ(8U, data->read_index()); |  | 
| 1289 |  | 
| 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); |  | 
| 1300 |  | 
| 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); |  | 
| 1311 } |  | 
| 1312 |  | 
| 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)))) { |  | 
| 1321   } |  | 
| 1322 |  | 
| 1323   virtual ~KillerCallback() {} |  | 
| 1324 |  | 
| 1325   const CompletionCallback& callback() const { return callback_; } |  | 
| 1326 |  | 
| 1327  private: |  | 
| 1328   void OnComplete(int result) { |  | 
| 1329     if (result < 0) |  | 
| 1330       delete transaction_; |  | 
| 1331 |  | 
| 1332     SetResult(result); |  | 
| 1333   } |  | 
| 1334 |  | 
| 1335   HttpNetworkTransaction* transaction_; |  | 
| 1336   CompletionCallback callback_; |  | 
| 1337 }; |  | 
| 1338 |  | 
| 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)); |  | 
| 1348 |  | 
| 1349   scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST)); |  | 
| 1350   scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); |  | 
| 1351 |  | 
| 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; |  | 
| 1356 |  | 
| 1357   settings.push_back(spdy::SpdySetting(id, max_concurrent_streams)); |  | 
| 1358   scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings)); |  | 
| 1359 |  | 
| 1360   MockWrite writes[] = { CreateMockWrite(*req), |  | 
| 1361     CreateMockWrite(*req2), |  | 
| 1362   }; |  | 
| 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! |  | 
| 1370   }; |  | 
| 1371 |  | 
| 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)); |  | 
| 1377 |  | 
| 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())); |  | 
| 1391 |  | 
| 1392   TestCompletionCallback callback1; |  | 
| 1393   TestCompletionCallback callback2; |  | 
| 1394   KillerCallback callback3(trans3); |  | 
| 1395 |  | 
| 1396   HttpRequestInfo httpreq1 = CreateGetRequest(); |  | 
| 1397   HttpRequestInfo httpreq2 = CreateGetRequest(); |  | 
| 1398   HttpRequestInfo httpreq3 = CreateGetRequest(); |  | 
| 1399 |  | 
| 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); |  | 
| 1406 |  | 
| 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); |  | 
| 1413 |  | 
| 1414   EXPECT_EQ(6U, data->read_index()); |  | 
| 1415 |  | 
| 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); |  | 
| 1424 |  | 
| 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); |  | 
| 1431 |  | 
| 1432   helper.VerifyDataConsumed(); |  | 
| 1433 } |  | 
| 1434 |  | 
| 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/"); |  | 
| 1441 |  | 
| 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 |  | 
| 1453   }; |  | 
| 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" |  | 
| 1461   }; |  | 
| 1462   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0, |  | 
| 1463     kPutHeaders, arraysize(kPutHeaders) / 2)); |  | 
| 1464   MockWrite writes[] = { |  | 
| 1465     CreateMockWrite(*req) |  | 
| 1466   }; |  | 
| 1467 |  | 
| 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 |  | 
| 1480   }; |  | 
| 1481   static const char* const kStandardGetHeaders[] = { |  | 
| 1482     "status", "200", |  | 
| 1483     "version", "HTTP/1.1" |  | 
| 1484     "content-length", "1234" |  | 
| 1485   }; |  | 
| 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 |  | 
| 1492   }; |  | 
| 1493 |  | 
| 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(); |  | 
| 1501 |  | 
| 1502   EXPECT_EQ(OK, out.rv); |  | 
| 1503   EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |  | 
| 1504 } |  | 
| 1505 |  | 
| 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/"); |  | 
| 1512 |  | 
| 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 |  | 
| 1524   }; |  | 
| 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" |  | 
| 1532   }; |  | 
| 1533   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket(kSynStartHeader, NULL, 0, |  | 
| 1534     kHeadHeaders, arraysize(kHeadHeaders) / 2)); |  | 
| 1535   MockWrite writes[] = { |  | 
| 1536     CreateMockWrite(*req) |  | 
| 1537   }; |  | 
| 1538 |  | 
| 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 |  | 
| 1551   }; |  | 
| 1552   static const char* const kStandardGetHeaders[] = { |  | 
| 1553     "status", "200", |  | 
| 1554     "version", "HTTP/1.1" |  | 
| 1555     "content-length", "1234" |  | 
| 1556   }; |  | 
| 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 |  | 
| 1563   }; |  | 
| 1564 |  | 
| 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(); |  | 
| 1572 |  | 
| 1573   EXPECT_EQ(OK, out.rv); |  | 
| 1574   EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |  | 
| 1575 } |  | 
| 1576 |  | 
| 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 |  | 
| 1584   }; |  | 
| 1585 |  | 
| 1586   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0)); |  | 
| 1587   MockRead reads[] = { |  | 
| 1588     CreateMockRead(*resp), |  | 
| 1589     CreateMockRead(*body), |  | 
| 1590     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 1591   }; |  | 
| 1592 |  | 
| 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); |  | 
| 1603 } |  | 
| 1604 |  | 
| 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), |  | 
| 1615   }; |  | 
| 1616 |  | 
| 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 |  | 
| 1623   }; |  | 
| 1624 |  | 
| 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); |  | 
| 1635 } |  | 
| 1636 |  | 
| 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; |  | 
| 1645 |  | 
| 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), |  | 
| 1653   }; |  | 
| 1654 |  | 
| 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 |  | 
| 1661   }; |  | 
| 1662 |  | 
| 1663   scoped_ptr<DelayedSocketData> data( |  | 
| 1664       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 1665                             writes, arraysize(writes))); |  | 
| 1666 |  | 
| 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); |  | 
| 1674 } |  | 
| 1675 |  | 
| 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(); |  | 
| 1684 |  | 
| 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()); |  | 
| 1692 |  | 
| 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), |  | 
| 1700   }; |  | 
| 1701 |  | 
| 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 |  | 
| 1708   }; |  | 
| 1709 |  | 
| 1710   scoped_ptr<DelayedSocketData> data( |  | 
| 1711       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 1712                             writes, arraysize(writes))); |  | 
| 1713 |  | 
| 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); |  | 
| 1721 } |  | 
| 1722 |  | 
| 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!" }; |  | 
| 1726 |  | 
| 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)); |  | 
| 1733 |  | 
| 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 |  | 
| 1747   }; |  | 
| 1748 |  | 
| 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(); |  | 
| 1757 |  | 
| 1758   TransactionHelperResult out = helper.output(); |  | 
| 1759   EXPECT_EQ(ERR_SYN_REPLY_NOT_RECEIVED, out.rv); |  | 
| 1760 } |  | 
| 1761 |  | 
| 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), |  | 
| 1773   }; |  | 
| 1774 |  | 
| 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 |  | 
| 1779   }; |  | 
| 1780 |  | 
| 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(); |  | 
| 1790 |  | 
| 1791   TestCompletionCallback callback; |  | 
| 1792   int rv = trans->Start( |  | 
| 1793       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 1794   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 1795 |  | 
| 1796   data->SetStop(2); |  | 
| 1797   data->Run(); |  | 
| 1798   helper.ResetTrans(); |  | 
| 1799   data->SetStop(20); |  | 
| 1800   data->Run(); |  | 
| 1801 |  | 
| 1802   helper.VerifyDataConsumed(); |  | 
| 1803 } |  | 
| 1804 |  | 
| 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 |  | 
| 1811   }; |  | 
| 1812 |  | 
| 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); |  | 
| 1820 } |  | 
| 1821 |  | 
| 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) }; |  | 
| 1827 |  | 
| 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 |  | 
| 1835   }; |  | 
| 1836 |  | 
| 1837   scoped_ptr<DelayedSocketData> data( |  | 
| 1838       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 1839                             writes, arraysize(writes))); |  | 
| 1840 |  | 
| 1841   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 1842                                      BoundNetLog(), GetParam()); |  | 
| 1843   helper.RunPreTestSetup(); |  | 
| 1844   helper.AddData(data.get()); |  | 
| 1845 |  | 
| 1846   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 1847 |  | 
| 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); |  | 
| 1853 |  | 
| 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); |  | 
| 1861 |  | 
| 1862   helper.VerifyDataConsumed(); |  | 
| 1863 } |  | 
| 1864 |  | 
| 1865 // Test that sent data frames and received WINDOW_UPDATE frames change |  | 
| 1866 // the send_window_size_ correctly. |  | 
| 1867 |  | 
| 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. |  | 
| 1880 |  | 
| 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); |  | 
| 1888 |  | 
| 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)); |  | 
| 1898 |  | 
| 1899   MockWrite writes[] = { |  | 
| 1900     CreateMockWrite(*req), |  | 
| 1901     CreateMockWrite(*body), |  | 
| 1902     CreateMockWrite(*body_end), |  | 
| 1903   }; |  | 
| 1904 |  | 
| 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 |  | 
| 1923   }; |  | 
| 1924 |  | 
| 1925   scoped_ptr<DelayedSocketData> data( |  | 
| 1926       new DelayedSocketData(0, reads, arraysize(reads), |  | 
| 1927                             writes, arraysize(writes))); |  | 
| 1928 |  | 
| 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()); |  | 
| 1936 |  | 
| 1937   NormalSpdyTransactionHelper helper(request, BoundNetLog(), GetParam()); |  | 
| 1938   helper.AddData(data.get()); |  | 
| 1939   helper.RunPreTestSetup(); |  | 
| 1940 |  | 
| 1941   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 1942 |  | 
| 1943   TestCompletionCallback callback; |  | 
| 1944   int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); |  | 
| 1945 |  | 
| 1946   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 1947   rv = callback.WaitForResult(); |  | 
| 1948   EXPECT_EQ(OK, rv); |  | 
| 1949 |  | 
| 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(); |  | 
| 1958 |  | 
| 1959   SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN); |  | 
| 1960 } |  | 
| 1961 |  | 
| 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); |  | 
| 1966 |  | 
| 1967   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 1968   scoped_ptr<spdy::SpdyFrame> window_update( |  | 
| 1969       ConstructSpdyWindowUpdate(1, kUploadDataSize)); |  | 
| 1970 |  | 
| 1971   MockWrite writes[] = { |  | 
| 1972     CreateMockWrite(*req), |  | 
| 1973     CreateMockWrite(*window_update), |  | 
| 1974   }; |  | 
| 1975 |  | 
| 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 |  | 
| 1989   }; |  | 
| 1990 |  | 
| 1991   scoped_ptr<DelayedSocketData> data( |  | 
| 1992       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 1993                             writes, arraysize(writes))); |  | 
| 1994 |  | 
| 1995   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 1996                                      BoundNetLog(), GetParam()); |  | 
| 1997   helper.AddData(data.get()); |  | 
| 1998   helper.RunPreTestSetup(); |  | 
| 1999   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 2000 |  | 
| 2001   TestCompletionCallback callback; |  | 
| 2002   int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); |  | 
| 2003 |  | 
| 2004   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 2005   rv = callback.WaitForResult(); |  | 
| 2006   EXPECT_EQ(OK, rv); |  | 
| 2007 |  | 
| 2008   SpdyHttpStream* stream = |  | 
| 2009       static_cast<SpdyHttpStream*>(trans->stream_.get()); |  | 
| 2010   ASSERT_TRUE(stream != NULL); |  | 
| 2011   ASSERT_TRUE(stream->stream() != NULL); |  | 
| 2012 |  | 
| 2013   EXPECT_EQ( |  | 
| 2014       static_cast<int>(spdy::kSpdyStreamInitialWindowSize) - kUploadDataSize, |  | 
| 2015       stream->stream()->recv_window_size()); |  | 
| 2016 |  | 
| 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); |  | 
| 2022 |  | 
| 2023   // Force sending of WINDOW_UPDATE by setting initial_recv_window_size to a |  | 
| 2024   // small value. |  | 
| 2025   stream->stream()->set_initial_recv_window_size(kUploadDataSize / 2); |  | 
| 2026 |  | 
| 2027   // Issue a read which will cause a WINDOW_UPDATE to be sent and window |  | 
| 2028   // size increased to default. |  | 
| 2029   scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kUploadDataSize)); |  | 
| 2030   rv = trans->Read(buf, kUploadDataSize, CompletionCallback()); |  | 
| 2031   EXPECT_EQ(kUploadDataSize, rv); |  | 
| 2032   std::string content(buf->data(), buf->data()+kUploadDataSize); |  | 
| 2033   EXPECT_STREQ(kUploadData, content.c_str()); |  | 
| 2034 |  | 
| 2035   // Schedule the reading of empty data frame with FIN |  | 
| 2036   data->CompleteRead(); |  | 
| 2037 |  | 
| 2038   // Force write of WINDOW_UPDATE which was scheduled during the above |  | 
| 2039   // read. |  | 
| 2040   MessageLoop::current()->RunAllPending(); |  | 
| 2041 |  | 
| 2042   // Read EOF. |  | 
| 2043   data->CompleteRead(); |  | 
| 2044 |  | 
| 2045   helper.VerifyDataConsumed(); |  | 
| 2046 |  | 
| 2047   SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN); |  | 
| 2048 } |  | 
| 2049 |  | 
| 2050 // Test that WINDOW_UPDATE frame causing overflow is handled correctly.  We |  | 
| 2051 // use the same trick as in the above test to enforce our scenario. |  | 
| 2052 TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) { |  | 
| 2053   SpdySession::set_use_flow_control(SpdySession::kEnableFlowControl); |  | 
| 2054 |  | 
| 2055   // number of full frames we hope to write (but will not, used to |  | 
| 2056   // set content-length header correctly) |  | 
| 2057   static int kFrameCount = 3; |  | 
| 2058 |  | 
| 2059   scoped_ptr<std::string> content( |  | 
| 2060       new std::string(kMaxSpdyFrameChunkSize, 'a')); |  | 
| 2061   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost( |  | 
| 2062       kMaxSpdyFrameChunkSize * kFrameCount, NULL, 0)); |  | 
| 2063   scoped_ptr<spdy::SpdyFrame> body( |  | 
| 2064       ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false)); |  | 
| 2065   scoped_ptr<spdy::SpdyFrame> rst( |  | 
| 2066       ConstructSpdyRstStream(1, spdy::FLOW_CONTROL_ERROR)); |  | 
| 2067 |  | 
| 2068   // We're not going to write a data frame with FIN, we'll receive a bad |  | 
| 2069   // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame. |  | 
| 2070   MockWrite writes[] = { |  | 
| 2071     CreateMockWrite(*req), |  | 
| 2072     CreateMockWrite(*body), |  | 
| 2073     CreateMockWrite(*rst), |  | 
| 2074   }; |  | 
| 2075 |  | 
| 2076   static const int32 kDeltaWindowSize = 0x7fffffff;  // cause an overflow |  | 
| 2077   scoped_ptr<spdy::SpdyFrame> window_update( |  | 
| 2078       ConstructSpdyWindowUpdate(1, kDeltaWindowSize)); |  | 
| 2079   scoped_ptr<spdy::SpdyFrame> window_update2( |  | 
| 2080       ConstructSpdyWindowUpdate(2, kDeltaWindowSize)); |  | 
| 2081   scoped_ptr<spdy::SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0)); |  | 
| 2082 |  | 
| 2083   MockRead reads[] = { |  | 
| 2084     CreateMockRead(*window_update2), |  | 
| 2085     CreateMockRead(*window_update2), |  | 
| 2086     CreateMockRead(*window_update), |  | 
| 2087     CreateMockRead(*window_update), |  | 
| 2088     CreateMockRead(*window_update), |  | 
| 2089     MockRead(ASYNC, ERR_IO_PENDING, 0),  // Wait for the RST to be written. |  | 
| 2090     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 2091   }; |  | 
| 2092 |  | 
| 2093   scoped_ptr<DelayedSocketData> data( |  | 
| 2094       new DelayedSocketData(0, reads, arraysize(reads), |  | 
| 2095                             writes, arraysize(writes))); |  | 
| 2096 |  | 
| 2097   // Setup the request |  | 
| 2098   HttpRequestInfo request; |  | 
| 2099   request.method = "POST"; |  | 
| 2100   request.url = GURL("http://www.google.com/"); |  | 
| 2101   request.upload_data = new UploadData(); |  | 
| 2102   for (int i = 0; i < kFrameCount; ++i) |  | 
| 2103     request.upload_data->AppendBytes(content->c_str(), content->size()); |  | 
| 2104 |  | 
| 2105   NormalSpdyTransactionHelper helper(request, |  | 
| 2106                                      BoundNetLog(), GetParam()); |  | 
| 2107   helper.AddData(data.get()); |  | 
| 2108   helper.RunPreTestSetup(); |  | 
| 2109 |  | 
| 2110   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 2111 |  | 
| 2112   TestCompletionCallback callback; |  | 
| 2113   int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); |  | 
| 2114 |  | 
| 2115   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 2116   rv = callback.WaitForResult(); |  | 
| 2117   EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv); |  | 
| 2118 |  | 
| 2119   data->CompleteRead(); |  | 
| 2120 |  | 
| 2121   ASSERT_TRUE(helper.session() != NULL); |  | 
| 2122   ASSERT_TRUE(helper.session()->spdy_session_pool() != NULL); |  | 
| 2123   helper.session()->spdy_session_pool()->CloseAllSessions(); |  | 
| 2124   helper.VerifyDataConsumed(); |  | 
| 2125 |  | 
| 2126   SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN); |  | 
| 2127 } |  | 
| 2128 |  | 
| 2129 // Test that after hitting a send window size of 0, the write process |  | 
| 2130 // stalls and upon receiving WINDOW_UPDATE frame write resumes. |  | 
| 2131 |  | 
| 2132 // This test constructs a POST request followed by enough data frames |  | 
| 2133 // containing 'a' that would make the window size 0, followed by another |  | 
| 2134 // data frame containing default content (which is "hello!") and this frame |  | 
| 2135 // also contains a FIN flag.  DelayedSocketData is used to enforce all |  | 
| 2136 // writes go through before a read could happen.  However, the last frame |  | 
| 2137 // ("hello!")  is not supposed to go through since by the time its turn |  | 
| 2138 // arrives, window size is 0.  At this point MessageLoop::Run() called via |  | 
| 2139 // callback would block.  Therefore we call MessageLoop::RunAllPending() |  | 
| 2140 // which returns after performing all possible writes.  We use DCHECKS to |  | 
| 2141 // ensure that last data frame is still there and stream has stalled. |  | 
| 2142 // After that, next read is artifically enforced, which causes a |  | 
| 2143 // WINDOW_UPDATE to be read and I/O process resumes. |  | 
| 2144 TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) { |  | 
| 2145   SpdySession::set_use_flow_control(SpdySession::kEnableFlowControl); |  | 
| 2146 |  | 
| 2147   // Number of frames we need to send to zero out the window size: data |  | 
| 2148   // frames plus SYN_STREAM plus the last data frame; also we need another |  | 
| 2149   // data frame that we will send once the WINDOW_UPDATE is received, |  | 
| 2150   // therefore +3. |  | 
| 2151   size_t nwrites = |  | 
| 2152       spdy::kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3; |  | 
| 2153 |  | 
| 2154   // Calculate last frame's size; 0 size data frame is legal. |  | 
| 2155   size_t last_frame_size = |  | 
| 2156       spdy::kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize; |  | 
| 2157 |  | 
| 2158   // Construct content for a data frame of maximum size. |  | 
| 2159   scoped_ptr<std::string> content( |  | 
| 2160       new std::string(kMaxSpdyFrameChunkSize, 'a')); |  | 
| 2161 |  | 
| 2162   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPost( |  | 
| 2163       spdy::kSpdyStreamInitialWindowSize + kUploadDataSize, NULL, 0)); |  | 
| 2164 |  | 
| 2165   // Full frames. |  | 
| 2166   scoped_ptr<spdy::SpdyFrame> body1( |  | 
| 2167       ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false)); |  | 
| 2168 |  | 
| 2169   // Last frame to zero out the window size. |  | 
| 2170   scoped_ptr<spdy::SpdyFrame> body2( |  | 
| 2171       ConstructSpdyBodyFrame(1, content->c_str(), last_frame_size, false)); |  | 
| 2172 |  | 
| 2173   // Data frame to be sent once WINDOW_UPDATE frame is received. |  | 
| 2174   scoped_ptr<spdy::SpdyFrame> body3(ConstructSpdyBodyFrame(1, true)); |  | 
| 2175 |  | 
| 2176   // Fill in mock writes. |  | 
| 2177   scoped_array<MockWrite> writes(new MockWrite[nwrites]); |  | 
| 2178   size_t i = 0; |  | 
| 2179   writes[i] = CreateMockWrite(*req); |  | 
| 2180   for (i = 1; i < nwrites-2; i++) |  | 
| 2181     writes[i] = CreateMockWrite(*body1); |  | 
| 2182   writes[i++] = CreateMockWrite(*body2); |  | 
| 2183   writes[i] = CreateMockWrite(*body3); |  | 
| 2184 |  | 
| 2185   // Construct read frame, give enough space to upload the rest of the |  | 
| 2186   // data. |  | 
| 2187   scoped_ptr<spdy::SpdyFrame> window_update( |  | 
| 2188       ConstructSpdyWindowUpdate(1, kUploadDataSize)); |  | 
| 2189   scoped_ptr<spdy::SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0)); |  | 
| 2190   MockRead reads[] = { |  | 
| 2191     CreateMockRead(*window_update), |  | 
| 2192     CreateMockRead(*window_update), |  | 
| 2193     CreateMockRead(*reply), |  | 
| 2194     CreateMockRead(*body2), |  | 
| 2195     CreateMockRead(*body3), |  | 
| 2196     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 2197   }; |  | 
| 2198 |  | 
| 2199   // Force all writes to happen before any read, last write will not |  | 
| 2200   // actually queue a frame, due to window size being 0. |  | 
| 2201   scoped_ptr<DelayedSocketData> data( |  | 
| 2202       new DelayedSocketData(nwrites, reads, arraysize(reads), |  | 
| 2203                             writes.get(), nwrites)); |  | 
| 2204 |  | 
| 2205   HttpRequestInfo request; |  | 
| 2206   request.method = "POST"; |  | 
| 2207   request.url = GURL("http://www.google.com/"); |  | 
| 2208   request.upload_data = new UploadData(); |  | 
| 2209   scoped_ptr<std::string> upload_data( |  | 
| 2210       new std::string(spdy::kSpdyStreamInitialWindowSize, 'a')); |  | 
| 2211   upload_data->append(kUploadData, kUploadDataSize); |  | 
| 2212   request.upload_data->AppendBytes(upload_data->c_str(), upload_data->size()); |  | 
| 2213   NormalSpdyTransactionHelper helper(request, |  | 
| 2214                                      BoundNetLog(), GetParam()); |  | 
| 2215   helper.AddData(data.get()); |  | 
| 2216   helper.RunPreTestSetup(); |  | 
| 2217 |  | 
| 2218   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 2219 |  | 
| 2220   TestCompletionCallback callback; |  | 
| 2221   int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); |  | 
| 2222   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 2223 |  | 
| 2224   MessageLoop::current()->RunAllPending(); // Write as much as we can. |  | 
| 2225 |  | 
| 2226   SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get()); |  | 
| 2227   ASSERT_TRUE(stream != NULL); |  | 
| 2228   ASSERT_TRUE(stream->stream() != NULL); |  | 
| 2229   EXPECT_EQ(0, stream->stream()->send_window_size()); |  | 
| 2230   // All the body data should have been read. |  | 
| 2231   // TODO(satorux): This is because of the weirdness in reading the request |  | 
| 2232   // body in OnSendBodyComplete(). See crbug.com/113107. |  | 
| 2233   EXPECT_TRUE(stream->request_body_stream_->IsEOF()); |  | 
| 2234   // But the body is not yet fully sent ("hello!" is not yet sent). |  | 
| 2235   EXPECT_FALSE(stream->stream()->body_sent()); |  | 
| 2236 |  | 
| 2237   data->ForceNextRead();   // Read in WINDOW_UPDATE frame. |  | 
| 2238   rv = callback.WaitForResult(); |  | 
| 2239   helper.VerifyDataConsumed(); |  | 
| 2240 |  | 
| 2241   SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN); |  | 
| 2242 } |  | 
| 2243 |  | 
| 2244 TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) { |  | 
| 2245   // Construct the request. |  | 
| 2246   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 2247   MockWrite writes[] = { |  | 
| 2248     CreateMockWrite(*req), |  | 
| 2249   }; |  | 
| 2250 |  | 
| 2251   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 2252   MockRead reads[] = { |  | 
| 2253     CreateMockRead(*resp), |  | 
| 2254     // This following read isn't used by the test, except during the |  | 
| 2255     // RunAllPending() call at the end since the SpdySession survives the |  | 
| 2256     // HttpNetworkTransaction and still tries to continue Read()'ing.  Any |  | 
| 2257     // MockRead will do here. |  | 
| 2258     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 2259   }; |  | 
| 2260 |  | 
| 2261   StaticSocketDataProvider data(reads, arraysize(reads), |  | 
| 2262                                 writes, arraysize(writes)); |  | 
| 2263 |  | 
| 2264   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 2265                                      BoundNetLog(), GetParam()); |  | 
| 2266   helper.RunPreTestSetup(); |  | 
| 2267   helper.AddData(&data); |  | 
| 2268   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 2269 |  | 
| 2270   TestCompletionCallback callback; |  | 
| 2271   int rv = trans->Start( |  | 
| 2272       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 2273   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 2274   helper.ResetTrans();  // Cancel the transaction. |  | 
| 2275 |  | 
| 2276   // Flush the MessageLoop while the SpdySessionDependencies (in particular, the |  | 
| 2277   // MockClientSocketFactory) are still alive. |  | 
| 2278   MessageLoop::current()->RunAllPending(); |  | 
| 2279   helper.VerifyDataNotConsumed(); |  | 
| 2280 } |  | 
| 2281 |  | 
| 2282 // Verify that the client sends a Rst Frame upon cancelling the stream. |  | 
| 2283 TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) { |  | 
| 2284   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 2285   scoped_ptr<spdy::SpdyFrame> rst( |  | 
| 2286       ConstructSpdyRstStream(1, spdy::CANCEL)); |  | 
| 2287   MockWrite writes[] = { |  | 
| 2288     CreateMockWrite(*req, 0, SYNCHRONOUS), |  | 
| 2289     CreateMockWrite(*rst, 2, SYNCHRONOUS), |  | 
| 2290   }; |  | 
| 2291 |  | 
| 2292   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 2293   MockRead reads[] = { |  | 
| 2294     CreateMockRead(*resp, 1, ASYNC), |  | 
| 2295     MockRead(ASYNC, 0, 0, 3)  // EOF |  | 
| 2296   }; |  | 
| 2297 |  | 
| 2298   scoped_refptr<DeterministicSocketData> data( |  | 
| 2299       new DeterministicSocketData(reads, arraysize(reads), |  | 
| 2300                             writes, arraysize(writes))); |  | 
| 2301 |  | 
| 2302   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 2303                                      BoundNetLog(), |  | 
| 2304                                      GetParam()); |  | 
| 2305   helper.SetDeterministic(); |  | 
| 2306   helper.RunPreTestSetup(); |  | 
| 2307   helper.AddDeterministicData(data.get()); |  | 
| 2308   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 2309 |  | 
| 2310   TestCompletionCallback callback; |  | 
| 2311 |  | 
| 2312   int rv = trans->Start( |  | 
| 2313       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 2314   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 2315 |  | 
| 2316   data->SetStop(2); |  | 
| 2317   data->Run(); |  | 
| 2318   helper.ResetTrans(); |  | 
| 2319   data->SetStop(20); |  | 
| 2320   data->Run(); |  | 
| 2321 |  | 
| 2322   helper.VerifyDataConsumed(); |  | 
| 2323 } |  | 
| 2324 |  | 
| 2325 // Verify that the client can correctly deal with the user callback attempting |  | 
| 2326 // to start another transaction on a session that is closing down. See |  | 
| 2327 // http://crbug.com/47455 |  | 
| 2328 TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) { |  | 
| 2329   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 2330   MockWrite writes[] = { CreateMockWrite(*req) }; |  | 
| 2331   MockWrite writes2[] = { CreateMockWrite(*req) }; |  | 
| 2332 |  | 
| 2333   // The indicated length of this packet is longer than its actual length. When |  | 
| 2334   // the session receives an empty packet after this one, it shuts down the |  | 
| 2335   // session, and calls the read callback with the incomplete data. |  | 
| 2336   const uint8 kGetBodyFrame2[] = { |  | 
| 2337     0x00, 0x00, 0x00, 0x01, |  | 
| 2338     0x01, 0x00, 0x00, 0x07, |  | 
| 2339     'h', 'e', 'l', 'l', 'o', '!', |  | 
| 2340   }; |  | 
| 2341 |  | 
| 2342   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 2343   MockRead reads[] = { |  | 
| 2344     CreateMockRead(*resp, 2), |  | 
| 2345     MockRead(ASYNC, ERR_IO_PENDING, 3),  // Force a pause |  | 
| 2346     MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2), |  | 
| 2347              arraysize(kGetBodyFrame2), 4), |  | 
| 2348     MockRead(ASYNC, ERR_IO_PENDING, 5),  // Force a pause |  | 
| 2349     MockRead(ASYNC, 0, 0, 6),  // EOF |  | 
| 2350   }; |  | 
| 2351   MockRead reads2[] = { |  | 
| 2352     CreateMockRead(*resp, 2), |  | 
| 2353     MockRead(ASYNC, 0, 0, 3),  // EOF |  | 
| 2354   }; |  | 
| 2355 |  | 
| 2356   scoped_ptr<OrderedSocketData> data( |  | 
| 2357       new OrderedSocketData(reads, arraysize(reads), |  | 
| 2358                             writes, arraysize(writes))); |  | 
| 2359   scoped_ptr<DelayedSocketData> data2( |  | 
| 2360       new DelayedSocketData(1, reads2, arraysize(reads2), |  | 
| 2361                             writes2, arraysize(writes2))); |  | 
| 2362 |  | 
| 2363   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 2364                                      BoundNetLog(), GetParam()); |  | 
| 2365   helper.RunPreTestSetup(); |  | 
| 2366   helper.AddData(data.get()); |  | 
| 2367   helper.AddData(data2.get()); |  | 
| 2368   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 2369 |  | 
| 2370   // Start the transaction with basic parameters. |  | 
| 2371   TestCompletionCallback callback; |  | 
| 2372   int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); |  | 
| 2373   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 2374   rv = callback.WaitForResult(); |  | 
| 2375 |  | 
| 2376   const int kSize = 3000; |  | 
| 2377   scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize)); |  | 
| 2378   rv = trans->Read( |  | 
| 2379       buf, kSize, |  | 
| 2380       base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback, |  | 
| 2381                  helper.session())); |  | 
| 2382   // This forces an err_IO_pending, which sets the callback. |  | 
| 2383   data->CompleteRead(); |  | 
| 2384   // This finishes the read. |  | 
| 2385   data->CompleteRead(); |  | 
| 2386   helper.VerifyDataConsumed(); |  | 
| 2387 } |  | 
| 2388 |  | 
| 2389 // Verify that the client can correctly deal with the user callback deleting the |  | 
| 2390 // transaction. Failures will usually be valgrind errors. See |  | 
| 2391 // http://crbug.com/46925 |  | 
| 2392 TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) { |  | 
| 2393   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 2394   MockWrite writes[] = { CreateMockWrite(*req) }; |  | 
| 2395 |  | 
| 2396   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 2397   scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 2398   MockRead reads[] = { |  | 
| 2399     CreateMockRead(*resp.get(), 2), |  | 
| 2400     MockRead(ASYNC, ERR_IO_PENDING, 3),  // Force a pause |  | 
| 2401     CreateMockRead(*body.get(), 4), |  | 
| 2402     MockRead(ASYNC, 0, 0, 5),  // EOF |  | 
| 2403   }; |  | 
| 2404 |  | 
| 2405   scoped_ptr<OrderedSocketData> data( |  | 
| 2406       new OrderedSocketData(reads, arraysize(reads), |  | 
| 2407                             writes, arraysize(writes))); |  | 
| 2408 |  | 
| 2409   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 2410                                      BoundNetLog(), GetParam()); |  | 
| 2411   helper.RunPreTestSetup(); |  | 
| 2412   helper.AddData(data.get()); |  | 
| 2413   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 2414 |  | 
| 2415   // Start the transaction with basic parameters. |  | 
| 2416   TestCompletionCallback callback; |  | 
| 2417   int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); |  | 
| 2418   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 2419   rv = callback.WaitForResult(); |  | 
| 2420 |  | 
| 2421   // Setup a user callback which will delete the session, and clear out the |  | 
| 2422   // memory holding the stream object. Note that the callback deletes trans. |  | 
| 2423   const int kSize = 3000; |  | 
| 2424   scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize)); |  | 
| 2425   rv = trans->Read( |  | 
| 2426       buf, kSize, |  | 
| 2427       base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback, |  | 
| 2428                  base::Unretained(&helper))); |  | 
| 2429   ASSERT_EQ(ERR_IO_PENDING, rv); |  | 
| 2430   data->CompleteRead(); |  | 
| 2431 |  | 
| 2432   // Finish running rest of tasks. |  | 
| 2433   MessageLoop::current()->RunAllPending(); |  | 
| 2434   helper.VerifyDataConsumed(); |  | 
| 2435 } |  | 
| 2436 |  | 
| 2437 // Send a spdy request to www.google.com that gets redirected to www.foo.com. |  | 
| 2438 TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) { |  | 
| 2439   // These are headers which the net::URLRequest tacks on. |  | 
| 2440   const char* const kExtraHeaders[] = { |  | 
| 2441     "accept-encoding", |  | 
| 2442     "gzip,deflate", |  | 
| 2443   }; |  | 
| 2444   const SpdyHeaderInfo kSynStartHeader = MakeSpdyHeader(spdy::SYN_STREAM); |  | 
| 2445   const char* const kStandardGetHeaders[] = { |  | 
| 2446     "host", |  | 
| 2447     "www.google.com", |  | 
| 2448     "method", |  | 
| 2449     "GET", |  | 
| 2450     "scheme", |  | 
| 2451     "http", |  | 
| 2452     "url", |  | 
| 2453     "/", |  | 
| 2454     "user-agent", |  | 
| 2455     "", |  | 
| 2456     "version", |  | 
| 2457     "HTTP/1.1" |  | 
| 2458   }; |  | 
| 2459   const char* const kStandardGetHeaders2[] = { |  | 
| 2460     "host", |  | 
| 2461     "www.foo.com", |  | 
| 2462     "method", |  | 
| 2463     "GET", |  | 
| 2464     "scheme", |  | 
| 2465     "http", |  | 
| 2466     "url", |  | 
| 2467     "/index.php", |  | 
| 2468     "user-agent", |  | 
| 2469     "", |  | 
| 2470     "version", |  | 
| 2471     "HTTP/1.1" |  | 
| 2472   }; |  | 
| 2473 |  | 
| 2474   // Setup writes/reads to www.google.com |  | 
| 2475   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyPacket( |  | 
| 2476       kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders) / 2, |  | 
| 2477       kStandardGetHeaders, arraysize(kStandardGetHeaders) / 2)); |  | 
| 2478   scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyPacket( |  | 
| 2479       kSynStartHeader, kExtraHeaders, arraysize(kExtraHeaders) / 2, |  | 
| 2480       kStandardGetHeaders2, arraysize(kStandardGetHeaders2) / 2)); |  | 
| 2481   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReplyRedirect(1)); |  | 
| 2482   MockWrite writes[] = { |  | 
| 2483     CreateMockWrite(*req, 1), |  | 
| 2484   }; |  | 
| 2485   MockRead reads[] = { |  | 
| 2486     CreateMockRead(*resp, 2), |  | 
| 2487     MockRead(ASYNC, 0, 0, 3)  // EOF |  | 
| 2488   }; |  | 
| 2489 |  | 
| 2490   // Setup writes/reads to www.foo.com |  | 
| 2491   scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 2492   scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true)); |  | 
| 2493   MockWrite writes2[] = { |  | 
| 2494     CreateMockWrite(*req2, 1), |  | 
| 2495   }; |  | 
| 2496   MockRead reads2[] = { |  | 
| 2497     CreateMockRead(*resp2, 2), |  | 
| 2498     CreateMockRead(*body2, 3), |  | 
| 2499     MockRead(ASYNC, 0, 0, 4)  // EOF |  | 
| 2500   }; |  | 
| 2501   scoped_ptr<OrderedSocketData> data( |  | 
| 2502       new OrderedSocketData(reads, arraysize(reads), |  | 
| 2503                             writes, arraysize(writes))); |  | 
| 2504   scoped_ptr<OrderedSocketData> data2( |  | 
| 2505       new OrderedSocketData(reads2, arraysize(reads2), |  | 
| 2506                             writes2, arraysize(writes2))); |  | 
| 2507 |  | 
| 2508   // TODO(erikchen): Make test support SPDYSSL, SPDYNPN |  | 
| 2509   HttpStreamFactory::set_force_spdy_over_ssl(false); |  | 
| 2510   HttpStreamFactory::set_force_spdy_always(true); |  | 
| 2511   TestDelegate d; |  | 
| 2512   { |  | 
| 2513     net::URLRequest r(GURL("http://www.google.com/"), &d); |  | 
| 2514     SpdyURLRequestContext* spdy_url_request_context = |  | 
| 2515         new SpdyURLRequestContext(); |  | 
| 2516     r.set_context(spdy_url_request_context); |  | 
| 2517     spdy_url_request_context->socket_factory(). |  | 
| 2518         AddSocketDataProvider(data.get()); |  | 
| 2519     spdy_url_request_context->socket_factory(). |  | 
| 2520         AddSocketDataProvider(data2.get()); |  | 
| 2521 |  | 
| 2522     d.set_quit_on_redirect(true); |  | 
| 2523     r.Start(); |  | 
| 2524     MessageLoop::current()->Run(); |  | 
| 2525 |  | 
| 2526     EXPECT_EQ(1, d.received_redirect_count()); |  | 
| 2527 |  | 
| 2528     r.FollowDeferredRedirect(); |  | 
| 2529     MessageLoop::current()->Run(); |  | 
| 2530     EXPECT_EQ(1, d.response_started_count()); |  | 
| 2531     EXPECT_FALSE(d.received_data_before_response()); |  | 
| 2532     EXPECT_EQ(net::URLRequestStatus::SUCCESS, r.status().status()); |  | 
| 2533     std::string contents("hello!"); |  | 
| 2534     EXPECT_EQ(contents, d.data_received()); |  | 
| 2535   } |  | 
| 2536   EXPECT_TRUE(data->at_read_eof()); |  | 
| 2537   EXPECT_TRUE(data->at_write_eof()); |  | 
| 2538   EXPECT_TRUE(data2->at_read_eof()); |  | 
| 2539   EXPECT_TRUE(data2->at_write_eof()); |  | 
| 2540 } |  | 
| 2541 |  | 
| 2542 // Detect response with upper case headers and reset the stream. |  | 
| 2543 TEST_P(SpdyNetworkTransactionTest, UpperCaseHeaders) { |  | 
| 2544   scoped_ptr<spdy::SpdyFrame> |  | 
| 2545       syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 2546   scoped_ptr<spdy::SpdyFrame> |  | 
| 2547       rst(ConstructSpdyRstStream(1, spdy::PROTOCOL_ERROR)); |  | 
| 2548   MockWrite writes[] = { |  | 
| 2549     CreateMockWrite(*syn, 0), |  | 
| 2550     CreateMockWrite(*rst, 2), |  | 
| 2551   }; |  | 
| 2552 |  | 
| 2553   const char* const kExtraHeaders[] = {"X-UpperCase", "yes"}; |  | 
| 2554   scoped_ptr<spdy::SpdyFrame> |  | 
| 2555       reply(ConstructSpdyGetSynReply(kExtraHeaders, 1, 1)); |  | 
| 2556   MockRead reads[] = { |  | 
| 2557     CreateMockRead(*reply, 1), |  | 
| 2558     MockRead(ASYNC, ERR_IO_PENDING, 3),  // Force a pause |  | 
| 2559   }; |  | 
| 2560 |  | 
| 2561   HttpResponseInfo response; |  | 
| 2562   HttpResponseInfo response2; |  | 
| 2563   scoped_ptr<OrderedSocketData> data(new OrderedSocketData( |  | 
| 2564       reads, |  | 
| 2565       arraysize(reads), |  | 
| 2566       writes, |  | 
| 2567       arraysize(writes))); |  | 
| 2568   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 2569                                      BoundNetLog(), GetParam()); |  | 
| 2570   helper.RunToCompletion(data.get()); |  | 
| 2571   TransactionHelperResult out = helper.output(); |  | 
| 2572   EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); |  | 
| 2573 } |  | 
| 2574 |  | 
| 2575 // Detect response with upper case headers in a HEADERS frame and reset the |  | 
| 2576 // stream. |  | 
| 2577 TEST_P(SpdyNetworkTransactionTest, UpperCaseHeadersInHeadersFrame) { |  | 
| 2578   scoped_ptr<spdy::SpdyFrame> |  | 
| 2579       syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 2580   scoped_ptr<spdy::SpdyFrame> |  | 
| 2581       rst(ConstructSpdyRstStream(1, spdy::PROTOCOL_ERROR)); |  | 
| 2582   MockWrite writes[] = { |  | 
| 2583     CreateMockWrite(*syn, 0), |  | 
| 2584     CreateMockWrite(*rst, 2), |  | 
| 2585   }; |  | 
| 2586 |  | 
| 2587   static const char* const kInitialHeaders[] = { |  | 
| 2588     "status", "200 OK", |  | 
| 2589     "version", "HTTP/1.1" |  | 
| 2590   }; |  | 
| 2591   static const char* const kLateHeaders[] = { |  | 
| 2592     "X-UpperCase", "yes", |  | 
| 2593   }; |  | 
| 2594   scoped_ptr<spdy::SpdyFrame> |  | 
| 2595       stream1_reply(ConstructSpdyControlFrame(kInitialHeaders, |  | 
| 2596                                               arraysize(kInitialHeaders) / 2, |  | 
| 2597                                               false, |  | 
| 2598                                               1, |  | 
| 2599                                               LOWEST, |  | 
| 2600                                               spdy::SYN_REPLY, |  | 
| 2601                                               spdy::CONTROL_FLAG_NONE, |  | 
| 2602                                               NULL, |  | 
| 2603                                               0, |  | 
| 2604                                               0)); |  | 
| 2605   scoped_ptr<spdy::SpdyFrame> |  | 
| 2606       stream1_headers(ConstructSpdyControlFrame(kLateHeaders, |  | 
| 2607                                                 arraysize(kLateHeaders) / 2, |  | 
| 2608                                                 false, |  | 
| 2609                                                 1, |  | 
| 2610                                                 LOWEST, |  | 
| 2611                                                 spdy::HEADERS, |  | 
| 2612                                                 spdy::CONTROL_FLAG_NONE, |  | 
| 2613                                                 NULL, |  | 
| 2614                                                 0, |  | 
| 2615                                                 0)); |  | 
| 2616   scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, true)); |  | 
| 2617   MockRead reads[] = { |  | 
| 2618     CreateMockRead(*stream1_reply), |  | 
| 2619     CreateMockRead(*stream1_headers), |  | 
| 2620     CreateMockRead(*stream1_body), |  | 
| 2621     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 2622   }; |  | 
| 2623 |  | 
| 2624   scoped_ptr<DelayedSocketData> data( |  | 
| 2625       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 2626                             writes, arraysize(writes))); |  | 
| 2627   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 2628                                      BoundNetLog(), GetParam()); |  | 
| 2629   helper.RunToCompletion(data.get()); |  | 
| 2630   TransactionHelperResult out = helper.output(); |  | 
| 2631   EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); |  | 
| 2632 } |  | 
| 2633 |  | 
| 2634 // Detect push stream with upper case headers and reset the stream. |  | 
| 2635 TEST_P(SpdyNetworkTransactionTest, UpperCaseHeadersOnPush) { |  | 
| 2636   scoped_ptr<spdy::SpdyFrame> |  | 
| 2637       syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 2638   scoped_ptr<spdy::SpdyFrame> |  | 
| 2639       rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR)); |  | 
| 2640   MockWrite writes[] = { |  | 
| 2641     CreateMockWrite(*syn, 0), |  | 
| 2642     CreateMockWrite(*rst, 2), |  | 
| 2643   }; |  | 
| 2644 |  | 
| 2645   scoped_ptr<spdy::SpdyFrame> |  | 
| 2646       reply(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 2647   const char* const extra_headers[] = {"X-UpperCase", "yes"}; |  | 
| 2648   scoped_ptr<spdy::SpdyFrame> |  | 
| 2649       push(ConstructSpdyPush(extra_headers, 1, 2, 1)); |  | 
| 2650   scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 2651   MockRead reads[] = { |  | 
| 2652     CreateMockRead(*reply, 1), |  | 
| 2653     CreateMockRead(*push, 1), |  | 
| 2654     CreateMockRead(*body, 1), |  | 
| 2655     MockRead(ASYNC, ERR_IO_PENDING, 3),  // Force a pause |  | 
| 2656   }; |  | 
| 2657 |  | 
| 2658   HttpResponseInfo response; |  | 
| 2659   HttpResponseInfo response2; |  | 
| 2660   scoped_ptr<OrderedSocketData> data(new OrderedSocketData( |  | 
| 2661       reads, |  | 
| 2662       arraysize(reads), |  | 
| 2663       writes, |  | 
| 2664       arraysize(writes))); |  | 
| 2665   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 2666                                      BoundNetLog(), GetParam()); |  | 
| 2667   helper.RunToCompletion(data.get()); |  | 
| 2668   TransactionHelperResult out = helper.output(); |  | 
| 2669   EXPECT_EQ(OK, out.rv); |  | 
| 2670 } |  | 
| 2671 |  | 
| 2672 // Send a spdy request to www.google.com. Get a pushed stream that redirects to |  | 
| 2673 // www.foo.com. |  | 
| 2674 TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) { |  | 
| 2675   // These are headers which the net::URLRequest tacks on. |  | 
| 2676   const char* const kExtraHeaders[] = { |  | 
| 2677     "accept-encoding", |  | 
| 2678     "gzip,deflate", |  | 
| 2679   }; |  | 
| 2680   const SpdyHeaderInfo kSynStartHeader = MakeSpdyHeader(spdy::SYN_STREAM); |  | 
| 2681   const char* const kStandardGetHeaders[] = { |  | 
| 2682     "host", |  | 
| 2683     "www.google.com", |  | 
| 2684     "method", |  | 
| 2685     "GET", |  | 
| 2686     "scheme", |  | 
| 2687     "http", |  | 
| 2688     "url", |  | 
| 2689     "/", |  | 
| 2690     "user-agent", |  | 
| 2691     "", |  | 
| 2692     "version", |  | 
| 2693     "HTTP/1.1" |  | 
| 2694   }; |  | 
| 2695 |  | 
| 2696   // Setup writes/reads to www.google.com |  | 
| 2697   scoped_ptr<spdy::SpdyFrame> req( |  | 
| 2698       ConstructSpdyPacket(kSynStartHeader, |  | 
| 2699                           kExtraHeaders, |  | 
| 2700                           arraysize(kExtraHeaders) / 2, |  | 
| 2701                           kStandardGetHeaders, |  | 
| 2702                           arraysize(kStandardGetHeaders) / 2)); |  | 
| 2703   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 2704   scoped_ptr<spdy::SpdyFrame> rep( |  | 
| 2705       ConstructSpdyPush(NULL, |  | 
| 2706                         0, |  | 
| 2707                         2, |  | 
| 2708                         1, |  | 
| 2709                         "http://www.google.com/foo.dat", |  | 
| 2710                         "301 Moved Permanently", |  | 
| 2711                         "http://www.foo.com/index.php")); |  | 
| 2712   scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 2713   scoped_ptr<spdy::SpdyFrame> rst(ConstructSpdyRstStream(2, spdy::CANCEL)); |  | 
| 2714   MockWrite writes[] = { |  | 
| 2715     CreateMockWrite(*req, 1), |  | 
| 2716     CreateMockWrite(*rst, 6), |  | 
| 2717   }; |  | 
| 2718   MockRead reads[] = { |  | 
| 2719     CreateMockRead(*resp, 2), |  | 
| 2720     CreateMockRead(*rep, 3), |  | 
| 2721     CreateMockRead(*body, 4), |  | 
| 2722     MockRead(ASYNC, ERR_IO_PENDING, 5),  // Force a pause |  | 
| 2723     MockRead(ASYNC, 0, 0, 7)  // EOF |  | 
| 2724   }; |  | 
| 2725 |  | 
| 2726   // Setup writes/reads to www.foo.com |  | 
| 2727   const char* const kStandardGetHeaders2[] = { |  | 
| 2728     "host", |  | 
| 2729     "www.foo.com", |  | 
| 2730     "method", |  | 
| 2731     "GET", |  | 
| 2732     "scheme", |  | 
| 2733     "http", |  | 
| 2734     "url", |  | 
| 2735     "/index.php", |  | 
| 2736     "user-agent", |  | 
| 2737     "", |  | 
| 2738     "version", |  | 
| 2739     "HTTP/1.1" |  | 
| 2740   }; |  | 
| 2741   scoped_ptr<spdy::SpdyFrame> req2( |  | 
| 2742       ConstructSpdyPacket(kSynStartHeader, |  | 
| 2743                           kExtraHeaders, |  | 
| 2744                           arraysize(kExtraHeaders) / 2, |  | 
| 2745                           kStandardGetHeaders2, |  | 
| 2746                           arraysize(kStandardGetHeaders2) / 2)); |  | 
| 2747   scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 2748   scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true)); |  | 
| 2749   MockWrite writes2[] = { |  | 
| 2750     CreateMockWrite(*req2, 1), |  | 
| 2751   }; |  | 
| 2752   MockRead reads2[] = { |  | 
| 2753     CreateMockRead(*resp2, 2), |  | 
| 2754     CreateMockRead(*body2, 3), |  | 
| 2755     MockRead(ASYNC, 0, 0, 5)  // EOF |  | 
| 2756   }; |  | 
| 2757   scoped_ptr<OrderedSocketData> data( |  | 
| 2758       new OrderedSocketData(reads, arraysize(reads), |  | 
| 2759                             writes, arraysize(writes))); |  | 
| 2760   scoped_ptr<OrderedSocketData> data2( |  | 
| 2761       new OrderedSocketData(reads2, arraysize(reads2), |  | 
| 2762                             writes2, arraysize(writes2))); |  | 
| 2763 |  | 
| 2764   // TODO(erikchen): Make test support SPDYSSL, SPDYNPN |  | 
| 2765   HttpStreamFactory::set_force_spdy_over_ssl(false); |  | 
| 2766   HttpStreamFactory::set_force_spdy_always(true); |  | 
| 2767   TestDelegate d; |  | 
| 2768   TestDelegate d2; |  | 
| 2769   scoped_refptr<SpdyURLRequestContext> spdy_url_request_context( |  | 
| 2770       new SpdyURLRequestContext()); |  | 
| 2771   { |  | 
| 2772     net::URLRequest r(GURL("http://www.google.com/"), &d); |  | 
| 2773     r.set_context(spdy_url_request_context); |  | 
| 2774     spdy_url_request_context->socket_factory(). |  | 
| 2775         AddSocketDataProvider(data.get()); |  | 
| 2776 |  | 
| 2777     r.Start(); |  | 
| 2778     MessageLoop::current()->Run(); |  | 
| 2779 |  | 
| 2780     EXPECT_EQ(0, d.received_redirect_count()); |  | 
| 2781     std::string contents("hello!"); |  | 
| 2782     EXPECT_EQ(contents, d.data_received()); |  | 
| 2783 |  | 
| 2784     net::URLRequest r2(GURL("http://www.google.com/foo.dat"), &d2); |  | 
| 2785     r2.set_context(spdy_url_request_context); |  | 
| 2786     spdy_url_request_context->socket_factory(). |  | 
| 2787         AddSocketDataProvider(data2.get()); |  | 
| 2788 |  | 
| 2789     d2.set_quit_on_redirect(true); |  | 
| 2790     r2.Start(); |  | 
| 2791     MessageLoop::current()->Run(); |  | 
| 2792     EXPECT_EQ(1, d2.received_redirect_count()); |  | 
| 2793 |  | 
| 2794     r2.FollowDeferredRedirect(); |  | 
| 2795     MessageLoop::current()->Run(); |  | 
| 2796     EXPECT_EQ(1, d2.response_started_count()); |  | 
| 2797     EXPECT_FALSE(d2.received_data_before_response()); |  | 
| 2798     EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2.status().status()); |  | 
| 2799     std::string contents2("hello!"); |  | 
| 2800     EXPECT_EQ(contents2, d2.data_received()); |  | 
| 2801   } |  | 
| 2802   data->CompleteRead(); |  | 
| 2803   data2->CompleteRead(); |  | 
| 2804   EXPECT_TRUE(data->at_read_eof()); |  | 
| 2805   EXPECT_TRUE(data->at_write_eof()); |  | 
| 2806   EXPECT_TRUE(data2->at_read_eof()); |  | 
| 2807   EXPECT_TRUE(data2->at_write_eof()); |  | 
| 2808 } |  | 
| 2809 |  | 
| 2810 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) { |  | 
| 2811   static const unsigned char kPushBodyFrame[] = { |  | 
| 2812     0x00, 0x00, 0x00, 0x02,                                      // header, ID |  | 
| 2813     0x01, 0x00, 0x00, 0x06,                                      // FIN, length |  | 
| 2814     'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed" |  | 
| 2815   }; |  | 
| 2816   scoped_ptr<spdy::SpdyFrame> |  | 
| 2817       stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 2818   scoped_ptr<spdy::SpdyFrame> |  | 
| 2819       stream1_body(ConstructSpdyBodyFrame(1, true)); |  | 
| 2820   MockWrite writes[] = { |  | 
| 2821     CreateMockWrite(*stream1_syn, 1), |  | 
| 2822   }; |  | 
| 2823 |  | 
| 2824   scoped_ptr<spdy::SpdyFrame> |  | 
| 2825       stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 2826   scoped_ptr<spdy::SpdyFrame> |  | 
| 2827       stream2_syn(ConstructSpdyPush(NULL, |  | 
| 2828                                     0, |  | 
| 2829                                     2, |  | 
| 2830                                     1, |  | 
| 2831                                     "http://www.google.com/foo.dat")); |  | 
| 2832   MockRead reads[] = { |  | 
| 2833     CreateMockRead(*stream1_reply, 2), |  | 
| 2834     CreateMockRead(*stream2_syn, 3), |  | 
| 2835     CreateMockRead(*stream1_body, 4, SYNCHRONOUS), |  | 
| 2836     MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), |  | 
| 2837              arraysize(kPushBodyFrame), 5), |  | 
| 2838     MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause |  | 
| 2839   }; |  | 
| 2840 |  | 
| 2841   HttpResponseInfo response; |  | 
| 2842   HttpResponseInfo response2; |  | 
| 2843   std::string expected_push_result("pushed"); |  | 
| 2844   scoped_ptr<OrderedSocketData> data(new OrderedSocketData( |  | 
| 2845       reads, |  | 
| 2846       arraysize(reads), |  | 
| 2847       writes, |  | 
| 2848       arraysize(writes))); |  | 
| 2849   RunServerPushTest(data.get(), |  | 
| 2850                     &response, |  | 
| 2851                     &response2, |  | 
| 2852                     expected_push_result); |  | 
| 2853 |  | 
| 2854   // Verify the SYN_REPLY. |  | 
| 2855   EXPECT_TRUE(response.headers != NULL); |  | 
| 2856   EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |  | 
| 2857 |  | 
| 2858   // Verify the pushed stream. |  | 
| 2859   EXPECT_TRUE(response2.headers != NULL); |  | 
| 2860   EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); |  | 
| 2861 } |  | 
| 2862 |  | 
| 2863 TEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) { |  | 
| 2864   static const unsigned char kPushBodyFrame[] = { |  | 
| 2865     0x00, 0x00, 0x00, 0x02,                                      // header, ID |  | 
| 2866     0x01, 0x00, 0x00, 0x06,                                      // FIN, length |  | 
| 2867     'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed" |  | 
| 2868   }; |  | 
| 2869   scoped_ptr<spdy::SpdyFrame> |  | 
| 2870       stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 2871   MockWrite writes[] = { |  | 
| 2872     CreateMockWrite(*stream1_syn, 1), |  | 
| 2873   }; |  | 
| 2874 |  | 
| 2875   scoped_ptr<spdy::SpdyFrame> |  | 
| 2876       stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 2877   scoped_ptr<spdy::SpdyFrame> |  | 
| 2878       stream2_syn(ConstructSpdyPush(NULL, |  | 
| 2879                                     0, |  | 
| 2880                                     2, |  | 
| 2881                                     1, |  | 
| 2882                                     "http://www.google.com/foo.dat")); |  | 
| 2883   scoped_ptr<spdy::SpdyFrame> |  | 
| 2884       stream1_body(ConstructSpdyBodyFrame(1, true)); |  | 
| 2885   MockRead reads[] = { |  | 
| 2886     CreateMockRead(*stream1_reply, 2), |  | 
| 2887     CreateMockRead(*stream2_syn, 3), |  | 
| 2888     MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), |  | 
| 2889              arraysize(kPushBodyFrame), 5), |  | 
| 2890     CreateMockRead(*stream1_body, 4, SYNCHRONOUS), |  | 
| 2891     MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause |  | 
| 2892   }; |  | 
| 2893 |  | 
| 2894   HttpResponseInfo response; |  | 
| 2895   HttpResponseInfo response2; |  | 
| 2896   std::string expected_push_result("pushed"); |  | 
| 2897   scoped_ptr<OrderedSocketData> data(new OrderedSocketData( |  | 
| 2898       reads, |  | 
| 2899       arraysize(reads), |  | 
| 2900       writes, |  | 
| 2901       arraysize(writes))); |  | 
| 2902   RunServerPushTest(data.get(), |  | 
| 2903                     &response, |  | 
| 2904                     &response2, |  | 
| 2905                     expected_push_result); |  | 
| 2906 |  | 
| 2907   // Verify the SYN_REPLY. |  | 
| 2908   EXPECT_TRUE(response.headers != NULL); |  | 
| 2909   EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |  | 
| 2910 |  | 
| 2911   // Verify the pushed stream. |  | 
| 2912   EXPECT_TRUE(response2.headers != NULL); |  | 
| 2913   EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); |  | 
| 2914 } |  | 
| 2915 |  | 
| 2916 TEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) { |  | 
| 2917   scoped_ptr<spdy::SpdyFrame> |  | 
| 2918       stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 2919   scoped_ptr<spdy::SpdyFrame> |  | 
| 2920       stream1_body(ConstructSpdyBodyFrame(1, true)); |  | 
| 2921   MockWrite writes[] = { |  | 
| 2922     CreateMockWrite(*stream1_syn, 1), |  | 
| 2923   }; |  | 
| 2924 |  | 
| 2925   scoped_ptr<spdy::SpdyFrame> |  | 
| 2926       stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 2927   scoped_ptr<spdy::SpdyFrame> |  | 
| 2928       stream2_syn(ConstructSpdyPush(NULL, |  | 
| 2929                                     0, |  | 
| 2930                                     2, |  | 
| 2931                                     1, |  | 
| 2932                                     "http://www.google.com/foo.dat")); |  | 
| 2933   scoped_ptr<spdy::SpdyFrame> |  | 
| 2934     stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR)); |  | 
| 2935   MockRead reads[] = { |  | 
| 2936     CreateMockRead(*stream1_reply, 2), |  | 
| 2937     CreateMockRead(*stream2_syn, 3), |  | 
| 2938     CreateMockRead(*stream2_rst, 4), |  | 
| 2939     CreateMockRead(*stream1_body, 5, SYNCHRONOUS), |  | 
| 2940     MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause |  | 
| 2941   }; |  | 
| 2942 |  | 
| 2943   scoped_ptr<OrderedSocketData> data( |  | 
| 2944       new OrderedSocketData(reads, arraysize(reads), |  | 
| 2945                             writes, arraysize(writes))); |  | 
| 2946   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 2947                                      BoundNetLog(), GetParam()); |  | 
| 2948 |  | 
| 2949   helper.RunPreTestSetup(); |  | 
| 2950   helper.AddData(data.get()); |  | 
| 2951 |  | 
| 2952   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 2953 |  | 
| 2954   // Start the transaction with basic parameters. |  | 
| 2955   TestCompletionCallback callback; |  | 
| 2956   int rv = trans->Start( |  | 
| 2957       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 2958   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 2959   rv = callback.WaitForResult(); |  | 
| 2960   EXPECT_EQ(OK, rv); |  | 
| 2961 |  | 
| 2962   // Verify that we consumed all test data. |  | 
| 2963   EXPECT_TRUE(data->at_read_eof()) << "Read count: " |  | 
| 2964                                    << data->read_count() |  | 
| 2965                                    << " Read index: " |  | 
| 2966                                    << data->read_index(); |  | 
| 2967   EXPECT_TRUE(data->at_write_eof()) << "Write count: " |  | 
| 2968                                     << data->write_count() |  | 
| 2969                                     << " Write index: " |  | 
| 2970                                     << data->write_index(); |  | 
| 2971 |  | 
| 2972   // Verify the SYN_REPLY. |  | 
| 2973   HttpResponseInfo response = *trans->GetResponseInfo(); |  | 
| 2974   EXPECT_TRUE(response.headers != NULL); |  | 
| 2975   EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |  | 
| 2976 } |  | 
| 2977 |  | 
| 2978 TEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) { |  | 
| 2979   // Verify that we don't leak streams and that we properly send a reset |  | 
| 2980   // if the server pushes the same stream twice. |  | 
| 2981   static const unsigned char kPushBodyFrame[] = { |  | 
| 2982     0x00, 0x00, 0x00, 0x02,                                      // header, ID |  | 
| 2983     0x01, 0x00, 0x00, 0x06,                                      // FIN, length |  | 
| 2984     'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed" |  | 
| 2985   }; |  | 
| 2986 |  | 
| 2987   scoped_ptr<spdy::SpdyFrame> |  | 
| 2988       stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 2989   scoped_ptr<spdy::SpdyFrame> |  | 
| 2990       stream1_body(ConstructSpdyBodyFrame(1, true)); |  | 
| 2991   scoped_ptr<spdy::SpdyFrame> |  | 
| 2992       stream3_rst(ConstructSpdyRstStream(4, spdy::PROTOCOL_ERROR)); |  | 
| 2993   MockWrite writes[] = { |  | 
| 2994     CreateMockWrite(*stream1_syn, 1), |  | 
| 2995     CreateMockWrite(*stream3_rst, 5), |  | 
| 2996   }; |  | 
| 2997 |  | 
| 2998   scoped_ptr<spdy::SpdyFrame> |  | 
| 2999       stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 3000   scoped_ptr<spdy::SpdyFrame> |  | 
| 3001       stream2_syn(ConstructSpdyPush(NULL, |  | 
| 3002                                     0, |  | 
| 3003                                     2, |  | 
| 3004                                     1, |  | 
| 3005                                     "http://www.google.com/foo.dat")); |  | 
| 3006   scoped_ptr<spdy::SpdyFrame> |  | 
| 3007       stream3_syn(ConstructSpdyPush(NULL, |  | 
| 3008                                     0, |  | 
| 3009                                     4, |  | 
| 3010                                     1, |  | 
| 3011                                     "http://www.google.com/foo.dat")); |  | 
| 3012   MockRead reads[] = { |  | 
| 3013     CreateMockRead(*stream1_reply, 2), |  | 
| 3014     CreateMockRead(*stream2_syn, 3), |  | 
| 3015     CreateMockRead(*stream3_syn, 4), |  | 
| 3016     CreateMockRead(*stream1_body, 6, SYNCHRONOUS), |  | 
| 3017     MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), |  | 
| 3018              arraysize(kPushBodyFrame), 7), |  | 
| 3019     MockRead(ASYNC, ERR_IO_PENDING, 8),  // Force a pause |  | 
| 3020   }; |  | 
| 3021 |  | 
| 3022   HttpResponseInfo response; |  | 
| 3023   HttpResponseInfo response2; |  | 
| 3024   std::string expected_push_result("pushed"); |  | 
| 3025   scoped_ptr<OrderedSocketData> data(new OrderedSocketData( |  | 
| 3026       reads, |  | 
| 3027       arraysize(reads), |  | 
| 3028       writes, |  | 
| 3029       arraysize(writes))); |  | 
| 3030   RunServerPushTest(data.get(), |  | 
| 3031                     &response, |  | 
| 3032                     &response2, |  | 
| 3033                     expected_push_result); |  | 
| 3034 |  | 
| 3035   // Verify the SYN_REPLY. |  | 
| 3036   EXPECT_TRUE(response.headers != NULL); |  | 
| 3037   EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |  | 
| 3038 |  | 
| 3039   // Verify the pushed stream. |  | 
| 3040   EXPECT_TRUE(response2.headers != NULL); |  | 
| 3041   EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); |  | 
| 3042 } |  | 
| 3043 |  | 
| 3044 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) { |  | 
| 3045   static const unsigned char kPushBodyFrame1[] = { |  | 
| 3046     0x00, 0x00, 0x00, 0x02,                                      // header, ID |  | 
| 3047     0x01, 0x00, 0x00, 0x1F,                                      // FIN, length |  | 
| 3048     'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed" |  | 
| 3049   }; |  | 
| 3050   static const char kPushBodyFrame2[] = " my darling"; |  | 
| 3051   static const char kPushBodyFrame3[] = " hello"; |  | 
| 3052   static const char kPushBodyFrame4[] = " my baby"; |  | 
| 3053 |  | 
| 3054   scoped_ptr<spdy::SpdyFrame> |  | 
| 3055       stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 3056   scoped_ptr<spdy::SpdyFrame> |  | 
| 3057       stream1_body(ConstructSpdyBodyFrame(1, true)); |  | 
| 3058   MockWrite writes[] = { |  | 
| 3059     CreateMockWrite(*stream1_syn, 1), |  | 
| 3060   }; |  | 
| 3061 |  | 
| 3062   scoped_ptr<spdy::SpdyFrame> |  | 
| 3063       stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 3064   scoped_ptr<spdy::SpdyFrame> |  | 
| 3065       stream2_syn(ConstructSpdyPush(NULL, |  | 
| 3066                                     0, |  | 
| 3067                                     2, |  | 
| 3068                                     1, |  | 
| 3069                                     "http://www.google.com/foo.dat")); |  | 
| 3070   MockRead reads[] = { |  | 
| 3071     CreateMockRead(*stream1_reply, 2), |  | 
| 3072     CreateMockRead(*stream2_syn, 3), |  | 
| 3073     MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame1), |  | 
| 3074              arraysize(kPushBodyFrame1), 4), |  | 
| 3075     MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame2), |  | 
| 3076              arraysize(kPushBodyFrame2) - 1, 5), |  | 
| 3077     MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame3), |  | 
| 3078              arraysize(kPushBodyFrame3) - 1, 6), |  | 
| 3079     MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame4), |  | 
| 3080              arraysize(kPushBodyFrame4) - 1, 7), |  | 
| 3081     CreateMockRead(*stream1_body, 8, SYNCHRONOUS), |  | 
| 3082     MockRead(ASYNC, ERR_IO_PENDING, 9),  // Force a pause |  | 
| 3083   }; |  | 
| 3084 |  | 
| 3085   HttpResponseInfo response; |  | 
| 3086   HttpResponseInfo response2; |  | 
| 3087   std::string expected_push_result("pushed my darling hello my baby"); |  | 
| 3088   scoped_ptr<OrderedSocketData> data(new OrderedSocketData( |  | 
| 3089       reads, |  | 
| 3090       arraysize(reads), |  | 
| 3091       writes, |  | 
| 3092       arraysize(writes))); |  | 
| 3093   RunServerPushTest(data.get(), |  | 
| 3094                     &response, |  | 
| 3095                     &response2, |  | 
| 3096                     expected_push_result); |  | 
| 3097 |  | 
| 3098   // Verify the SYN_REPLY. |  | 
| 3099   EXPECT_TRUE(response.headers != NULL); |  | 
| 3100   EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |  | 
| 3101 |  | 
| 3102   // Verify the pushed stream. |  | 
| 3103   EXPECT_TRUE(response2.headers != NULL); |  | 
| 3104   EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); |  | 
| 3105 } |  | 
| 3106 |  | 
| 3107 TEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) { |  | 
| 3108   SpdySession::set_use_flow_control(SpdySession::kDisableFlowControl); |  | 
| 3109 |  | 
| 3110   static const unsigned char kPushBodyFrame1[] = { |  | 
| 3111     0x00, 0x00, 0x00, 0x02,                                      // header, ID |  | 
| 3112     0x01, 0x00, 0x00, 0x1F,                                      // FIN, length |  | 
| 3113     'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed" |  | 
| 3114   }; |  | 
| 3115   static const char kPushBodyFrame2[] = " my darling"; |  | 
| 3116   static const char kPushBodyFrame3[] = " hello"; |  | 
| 3117   static const char kPushBodyFrame4[] = " my baby"; |  | 
| 3118 |  | 
| 3119   scoped_ptr<spdy::SpdyFrame> |  | 
| 3120       stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 3121   scoped_ptr<spdy::SpdyFrame> |  | 
| 3122       stream1_body(ConstructSpdyBodyFrame(1, true)); |  | 
| 3123   MockWrite writes[] = { |  | 
| 3124     CreateMockWrite(*stream1_syn, 1), |  | 
| 3125   }; |  | 
| 3126 |  | 
| 3127   scoped_ptr<spdy::SpdyFrame> |  | 
| 3128       stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 3129   scoped_ptr<spdy::SpdyFrame> |  | 
| 3130       stream2_syn(ConstructSpdyPush(NULL, |  | 
| 3131                                     0, |  | 
| 3132                                     2, |  | 
| 3133                                     1, |  | 
| 3134                                     "http://www.google.com/foo.dat")); |  | 
| 3135   MockRead reads[] = { |  | 
| 3136     CreateMockRead(*stream1_reply, 2), |  | 
| 3137     CreateMockRead(*stream2_syn, 3), |  | 
| 3138     MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame1), |  | 
| 3139              arraysize(kPushBodyFrame1), 4), |  | 
| 3140     MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame2), |  | 
| 3141              arraysize(kPushBodyFrame2) - 1, 5), |  | 
| 3142     MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause |  | 
| 3143     MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame3), |  | 
| 3144              arraysize(kPushBodyFrame3) - 1, 7), |  | 
| 3145     MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame4), |  | 
| 3146              arraysize(kPushBodyFrame4) - 1, 8), |  | 
| 3147     CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS), |  | 
| 3148     MockRead(ASYNC, ERR_IO_PENDING, 10)  // Force a pause. |  | 
| 3149   }; |  | 
| 3150 |  | 
| 3151   HttpResponseInfo response; |  | 
| 3152   HttpResponseInfo response2; |  | 
| 3153   std::string expected_push_result("pushed my darling hello my baby"); |  | 
| 3154   scoped_ptr<OrderedSocketData> data(new OrderedSocketData( |  | 
| 3155       reads, |  | 
| 3156       arraysize(reads), |  | 
| 3157       writes, |  | 
| 3158       arraysize(writes))); |  | 
| 3159   RunServerPushTest(data.get(), |  | 
| 3160                     &response, |  | 
| 3161                     &response2, |  | 
| 3162                     expected_push_result); |  | 
| 3163 |  | 
| 3164   // Verify the SYN_REPLY. |  | 
| 3165   EXPECT_TRUE(response.headers != NULL); |  | 
| 3166   EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |  | 
| 3167 |  | 
| 3168   // Verify the pushed stream. |  | 
| 3169   EXPECT_TRUE(response2.headers != NULL); |  | 
| 3170   EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); |  | 
| 3171 |  | 
| 3172   SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN); |  | 
| 3173 } |  | 
| 3174 |  | 
| 3175 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) { |  | 
| 3176   scoped_ptr<spdy::SpdyFrame> |  | 
| 3177       stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 3178   scoped_ptr<spdy::SpdyFrame> |  | 
| 3179       stream1_body(ConstructSpdyBodyFrame(1, true)); |  | 
| 3180   scoped_ptr<spdy::SpdyFrame> |  | 
| 3181       stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_STREAM)); |  | 
| 3182   MockWrite writes[] = { |  | 
| 3183     CreateMockWrite(*stream1_syn, 1), |  | 
| 3184     CreateMockWrite(*stream2_rst, 4), |  | 
| 3185   }; |  | 
| 3186 |  | 
| 3187   scoped_ptr<spdy::SpdyFrame> |  | 
| 3188       stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 3189   scoped_ptr<spdy::SpdyFrame> |  | 
| 3190       stream2_syn(ConstructSpdyPush(NULL, |  | 
| 3191                                     0, |  | 
| 3192                                     2, |  | 
| 3193                                     0, |  | 
| 3194                                     "http://www.google.com/foo.dat")); |  | 
| 3195   MockRead reads[] = { |  | 
| 3196     CreateMockRead(*stream1_reply, 2), |  | 
| 3197     CreateMockRead(*stream2_syn, 3), |  | 
| 3198     CreateMockRead(*stream1_body, 4), |  | 
| 3199     MockRead(ASYNC, ERR_IO_PENDING, 5)  // Force a pause |  | 
| 3200   }; |  | 
| 3201 |  | 
| 3202   scoped_ptr<OrderedSocketData> data( |  | 
| 3203       new OrderedSocketData(reads, arraysize(reads), |  | 
| 3204                             writes, arraysize(writes))); |  | 
| 3205   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 3206                                      BoundNetLog(), GetParam()); |  | 
| 3207 |  | 
| 3208   helper.RunPreTestSetup(); |  | 
| 3209   helper.AddData(data.get()); |  | 
| 3210 |  | 
| 3211   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 3212 |  | 
| 3213   // Start the transaction with basic parameters. |  | 
| 3214   TestCompletionCallback callback; |  | 
| 3215   int rv = trans->Start( |  | 
| 3216       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 3217   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 3218   rv = callback.WaitForResult(); |  | 
| 3219   EXPECT_EQ(OK, rv); |  | 
| 3220 |  | 
| 3221   // Verify that we consumed all test data. |  | 
| 3222   EXPECT_TRUE(data->at_read_eof()) << "Read count: " |  | 
| 3223                                    << data->read_count() |  | 
| 3224                                    << " Read index: " |  | 
| 3225                                    << data->read_index(); |  | 
| 3226   EXPECT_TRUE(data->at_write_eof()) << "Write count: " |  | 
| 3227                                     << data->write_count() |  | 
| 3228                                     << " Write index: " |  | 
| 3229                                     << data->write_index(); |  | 
| 3230 |  | 
| 3231   // Verify the SYN_REPLY. |  | 
| 3232   HttpResponseInfo response = *trans->GetResponseInfo(); |  | 
| 3233   EXPECT_TRUE(response.headers != NULL); |  | 
| 3234   EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |  | 
| 3235 } |  | 
| 3236 |  | 
| 3237 TEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) { |  | 
| 3238   scoped_ptr<spdy::SpdyFrame> |  | 
| 3239       stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 3240   scoped_ptr<spdy::SpdyFrame> |  | 
| 3241       stream1_body(ConstructSpdyBodyFrame(1, true)); |  | 
| 3242   scoped_ptr<spdy::SpdyFrame> |  | 
| 3243       stream2_rst(ConstructSpdyRstStream(2, spdy::INVALID_ASSOCIATED_STREAM)); |  | 
| 3244   MockWrite writes[] = { |  | 
| 3245     CreateMockWrite(*stream1_syn, 1), |  | 
| 3246     CreateMockWrite(*stream2_rst, 4), |  | 
| 3247   }; |  | 
| 3248 |  | 
| 3249   scoped_ptr<spdy::SpdyFrame> |  | 
| 3250       stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 3251   scoped_ptr<spdy::SpdyFrame> |  | 
| 3252       stream2_syn(ConstructSpdyPush(NULL, |  | 
| 3253                                     0, |  | 
| 3254                                     2, |  | 
| 3255                                     9, |  | 
| 3256                                     "http://www.google.com/foo.dat")); |  | 
| 3257   MockRead reads[] = { |  | 
| 3258     CreateMockRead(*stream1_reply, 2), |  | 
| 3259     CreateMockRead(*stream2_syn, 3), |  | 
| 3260     CreateMockRead(*stream1_body, 4), |  | 
| 3261     MockRead(ASYNC, ERR_IO_PENDING, 5),  // Force a pause |  | 
| 3262   }; |  | 
| 3263 |  | 
| 3264   scoped_ptr<OrderedSocketData> data( |  | 
| 3265       new OrderedSocketData(reads, arraysize(reads), |  | 
| 3266                             writes, arraysize(writes))); |  | 
| 3267   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 3268                                      BoundNetLog(), GetParam()); |  | 
| 3269 |  | 
| 3270   helper.RunPreTestSetup(); |  | 
| 3271   helper.AddData(data.get()); |  | 
| 3272 |  | 
| 3273   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 3274 |  | 
| 3275   // Start the transaction with basic parameters. |  | 
| 3276   TestCompletionCallback callback; |  | 
| 3277   int rv = trans->Start( |  | 
| 3278       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 3279   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 3280   rv = callback.WaitForResult(); |  | 
| 3281   EXPECT_EQ(OK, rv); |  | 
| 3282 |  | 
| 3283   // Verify that we consumed all test data. |  | 
| 3284   EXPECT_TRUE(data->at_read_eof()) << "Read count: " |  | 
| 3285                                    << data->read_count() |  | 
| 3286                                    << " Read index: " |  | 
| 3287                                    << data->read_index(); |  | 
| 3288   EXPECT_TRUE(data->at_write_eof()) << "Write count: " |  | 
| 3289                                     << data->write_count() |  | 
| 3290                                     << " Write index: " |  | 
| 3291                                     << data->write_index(); |  | 
| 3292 |  | 
| 3293   // Verify the SYN_REPLY. |  | 
| 3294   HttpResponseInfo response = *trans->GetResponseInfo(); |  | 
| 3295   EXPECT_TRUE(response.headers != NULL); |  | 
| 3296   EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |  | 
| 3297 } |  | 
| 3298 |  | 
| 3299 TEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) { |  | 
| 3300   scoped_ptr<spdy::SpdyFrame> |  | 
| 3301       stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 3302   scoped_ptr<spdy::SpdyFrame> |  | 
| 3303       stream1_body(ConstructSpdyBodyFrame(1, true)); |  | 
| 3304   scoped_ptr<spdy::SpdyFrame> |  | 
| 3305       stream2_rst(ConstructSpdyRstStream(2, spdy::PROTOCOL_ERROR)); |  | 
| 3306   MockWrite writes[] = { |  | 
| 3307     CreateMockWrite(*stream1_syn, 1), |  | 
| 3308     CreateMockWrite(*stream2_rst, 4), |  | 
| 3309   }; |  | 
| 3310 |  | 
| 3311   scoped_ptr<spdy::SpdyFrame> |  | 
| 3312       stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 3313   scoped_ptr<spdy::SpdyFrame> |  | 
| 3314       stream2_syn(ConstructSpdyPush(NULL, 0, 2, 1)); |  | 
| 3315   MockRead reads[] = { |  | 
| 3316     CreateMockRead(*stream1_reply, 2), |  | 
| 3317     CreateMockRead(*stream2_syn, 3), |  | 
| 3318     CreateMockRead(*stream1_body, 4), |  | 
| 3319     MockRead(ASYNC, ERR_IO_PENDING, 5)  // Force a pause |  | 
| 3320   }; |  | 
| 3321 |  | 
| 3322   scoped_ptr<OrderedSocketData> data( |  | 
| 3323       new OrderedSocketData(reads, arraysize(reads), |  | 
| 3324                             writes, arraysize(writes))); |  | 
| 3325   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 3326                                      BoundNetLog(), GetParam()); |  | 
| 3327 |  | 
| 3328   helper.RunPreTestSetup(); |  | 
| 3329   helper.AddData(data.get()); |  | 
| 3330 |  | 
| 3331   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 3332 |  | 
| 3333   // Start the transaction with basic parameters. |  | 
| 3334   TestCompletionCallback callback; |  | 
| 3335   int rv = trans->Start( |  | 
| 3336       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 3337   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 3338   rv = callback.WaitForResult(); |  | 
| 3339   EXPECT_EQ(OK, rv); |  | 
| 3340   // Verify that we consumed all test data. |  | 
| 3341   EXPECT_TRUE(data->at_read_eof()) << "Read count: " |  | 
| 3342                                    << data->read_count() |  | 
| 3343                                    << " Read index: " |  | 
| 3344                                    << data->read_index(); |  | 
| 3345   EXPECT_TRUE(data->at_write_eof()) << "Write count: " |  | 
| 3346                                     << data->write_count() |  | 
| 3347                                     << " Write index: " |  | 
| 3348                                     << data->write_index(); |  | 
| 3349 |  | 
| 3350   // Verify the SYN_REPLY. |  | 
| 3351   HttpResponseInfo response = *trans->GetResponseInfo(); |  | 
| 3352   EXPECT_TRUE(response.headers != NULL); |  | 
| 3353   EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |  | 
| 3354 } |  | 
| 3355 |  | 
| 3356 // Verify that various SynReply headers parse correctly through the |  | 
| 3357 // HTTP layer. |  | 
| 3358 TEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) { |  | 
| 3359   struct SynReplyHeadersTests { |  | 
| 3360     int num_headers; |  | 
| 3361     const char* extra_headers[5]; |  | 
| 3362     const char* expected_headers; |  | 
| 3363   } test_cases[] = { |  | 
| 3364     // This uses a multi-valued cookie header. |  | 
| 3365     { 2, |  | 
| 3366       { "cookie", "val1", |  | 
| 3367         "cookie", "val2",  // will get appended separated by NULL |  | 
| 3368         NULL |  | 
| 3369       }, |  | 
| 3370       "cookie: val1\n" |  | 
| 3371       "cookie: val2\n" |  | 
| 3372       "hello: bye\n" |  | 
| 3373       "status: 200\n" |  | 
| 3374       "version: HTTP/1.1\n" |  | 
| 3375     }, |  | 
| 3376     // This is the minimalist set of headers. |  | 
| 3377     { 0, |  | 
| 3378       { NULL }, |  | 
| 3379       "hello: bye\n" |  | 
| 3380       "status: 200\n" |  | 
| 3381       "version: HTTP/1.1\n" |  | 
| 3382     }, |  | 
| 3383     // Headers with a comma separated list. |  | 
| 3384     { 1, |  | 
| 3385       { "cookie", "val1,val2", |  | 
| 3386         NULL |  | 
| 3387       }, |  | 
| 3388       "cookie: val1,val2\n" |  | 
| 3389       "hello: bye\n" |  | 
| 3390       "status: 200\n" |  | 
| 3391       "version: HTTP/1.1\n" |  | 
| 3392     } |  | 
| 3393   }; |  | 
| 3394 |  | 
| 3395   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { |  | 
| 3396     scoped_ptr<spdy::SpdyFrame> req( |  | 
| 3397         ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 3398     MockWrite writes[] = { CreateMockWrite(*req) }; |  | 
| 3399 |  | 
| 3400     scoped_ptr<spdy::SpdyFrame> resp( |  | 
| 3401         ConstructSpdyGetSynReply(test_cases[i].extra_headers, |  | 
| 3402                                  test_cases[i].num_headers, |  | 
| 3403                                  1)); |  | 
| 3404     scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 3405     MockRead reads[] = { |  | 
| 3406       CreateMockRead(*resp), |  | 
| 3407       CreateMockRead(*body), |  | 
| 3408       MockRead(ASYNC, 0, 0)  // EOF |  | 
| 3409     }; |  | 
| 3410 |  | 
| 3411     scoped_ptr<DelayedSocketData> data( |  | 
| 3412         new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 3413                               writes, arraysize(writes))); |  | 
| 3414     NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 3415                                        BoundNetLog(), GetParam()); |  | 
| 3416     helper.RunToCompletion(data.get()); |  | 
| 3417     TransactionHelperResult out = helper.output(); |  | 
| 3418 |  | 
| 3419     EXPECT_EQ(OK, out.rv); |  | 
| 3420     EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |  | 
| 3421     EXPECT_EQ("hello!", out.response_data); |  | 
| 3422 |  | 
| 3423     scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers; |  | 
| 3424     EXPECT_TRUE(headers.get() != NULL); |  | 
| 3425     void* iter = NULL; |  | 
| 3426     std::string name, value, lines; |  | 
| 3427     while (headers->EnumerateHeaderLines(&iter, &name, &value)) { |  | 
| 3428       lines.append(name); |  | 
| 3429       lines.append(": "); |  | 
| 3430       lines.append(value); |  | 
| 3431       lines.append("\n"); |  | 
| 3432     } |  | 
| 3433     EXPECT_EQ(std::string(test_cases[i].expected_headers), lines); |  | 
| 3434   } |  | 
| 3435 } |  | 
| 3436 |  | 
| 3437 // Verify that various SynReply headers parse vary fields correctly |  | 
| 3438 // through the HTTP layer, and the response matches the request. |  | 
| 3439 TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) { |  | 
| 3440   static const SpdyHeaderInfo syn_reply_info = { |  | 
| 3441     spdy::SYN_REPLY,                              // Syn Reply |  | 
| 3442     1,                                            // Stream ID |  | 
| 3443     0,                                            // Associated Stream ID |  | 
| 3444     net::ConvertRequestPriorityToSpdyPriority(LOWEST), |  | 
| 3445                                                   // Priority |  | 
| 3446     spdy::CONTROL_FLAG_NONE,                      // Control Flags |  | 
| 3447     false,                                        // Compressed |  | 
| 3448     spdy::INVALID,                                // Status |  | 
| 3449     NULL,                                         // Data |  | 
| 3450     0,                                            // Data Length |  | 
| 3451     spdy::DATA_FLAG_NONE                          // Data Flags |  | 
| 3452   }; |  | 
| 3453   // Modify the following data to change/add test cases: |  | 
| 3454   struct SynReplyTests { |  | 
| 3455     const SpdyHeaderInfo* syn_reply; |  | 
| 3456     bool vary_matches; |  | 
| 3457     int num_headers[2]; |  | 
| 3458     const char* extra_headers[2][16]; |  | 
| 3459   } test_cases[] = { |  | 
| 3460     // Test the case of a multi-valued cookie.  When the value is delimited |  | 
| 3461     // with NUL characters, it needs to be unfolded into multiple headers. |  | 
| 3462     { |  | 
| 3463       &syn_reply_info, |  | 
| 3464       true, |  | 
| 3465       { 1, 4 }, |  | 
| 3466       { { "cookie",   "val1,val2", |  | 
| 3467           NULL |  | 
| 3468         }, |  | 
| 3469         { "vary",     "cookie", |  | 
| 3470           "status",   "200", |  | 
| 3471           "url",      "/index.php", |  | 
| 3472           "version",  "HTTP/1.1", |  | 
| 3473           NULL |  | 
| 3474         } |  | 
| 3475       } |  | 
| 3476     }, {    // Multiple vary fields. |  | 
| 3477       &syn_reply_info, |  | 
| 3478       true, |  | 
| 3479       { 2, 5 }, |  | 
| 3480       { { "friend",   "barney", |  | 
| 3481           "enemy",    "snaggletooth", |  | 
| 3482           NULL |  | 
| 3483         }, |  | 
| 3484         { "vary",     "friend", |  | 
| 3485           "vary",     "enemy", |  | 
| 3486           "status",   "200", |  | 
| 3487           "url",      "/index.php", |  | 
| 3488           "version",  "HTTP/1.1", |  | 
| 3489           NULL |  | 
| 3490         } |  | 
| 3491       } |  | 
| 3492     }, {    // Test a '*' vary field. |  | 
| 3493       &syn_reply_info, |  | 
| 3494       false, |  | 
| 3495       { 1, 4 }, |  | 
| 3496       { { "cookie",   "val1,val2", |  | 
| 3497           NULL |  | 
| 3498         }, |  | 
| 3499         { "vary",     "*", |  | 
| 3500           "status",   "200", |  | 
| 3501           "url",      "/index.php", |  | 
| 3502           "version",  "HTTP/1.1", |  | 
| 3503           NULL |  | 
| 3504         } |  | 
| 3505       } |  | 
| 3506     }, {    // Multiple comma-separated vary fields. |  | 
| 3507       &syn_reply_info, |  | 
| 3508       true, |  | 
| 3509       { 2, 4 }, |  | 
| 3510       { { "friend",   "barney", |  | 
| 3511           "enemy",    "snaggletooth", |  | 
| 3512           NULL |  | 
| 3513         }, |  | 
| 3514         { "vary",     "friend,enemy", |  | 
| 3515           "status",   "200", |  | 
| 3516           "url",      "/index.php", |  | 
| 3517           "version",  "HTTP/1.1", |  | 
| 3518           NULL |  | 
| 3519         } |  | 
| 3520       } |  | 
| 3521     } |  | 
| 3522   }; |  | 
| 3523 |  | 
| 3524   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { |  | 
| 3525     // Construct the request. |  | 
| 3526     scoped_ptr<spdy::SpdyFrame> frame_req( |  | 
| 3527       ConstructSpdyGet(test_cases[i].extra_headers[0], |  | 
| 3528                        test_cases[i].num_headers[0], |  | 
| 3529                        false, 1, LOWEST)); |  | 
| 3530 |  | 
| 3531     MockWrite writes[] = { |  | 
| 3532       CreateMockWrite(*frame_req), |  | 
| 3533     }; |  | 
| 3534 |  | 
| 3535     // Construct the reply. |  | 
| 3536     scoped_ptr<spdy::SpdyFrame> frame_reply( |  | 
| 3537       ConstructSpdyPacket(*test_cases[i].syn_reply, |  | 
| 3538                           test_cases[i].extra_headers[1], |  | 
| 3539                           test_cases[i].num_headers[1], |  | 
| 3540                           NULL, |  | 
| 3541                           0)); |  | 
| 3542 |  | 
| 3543     scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 3544     MockRead reads[] = { |  | 
| 3545       CreateMockRead(*frame_reply), |  | 
| 3546       CreateMockRead(*body), |  | 
| 3547       MockRead(ASYNC, 0, 0)  // EOF |  | 
| 3548     }; |  | 
| 3549 |  | 
| 3550     // Attach the headers to the request. |  | 
| 3551     int header_count = test_cases[i].num_headers[0]; |  | 
| 3552 |  | 
| 3553     HttpRequestInfo request = CreateGetRequest(); |  | 
| 3554     for (int ct = 0; ct < header_count; ct++) { |  | 
| 3555       const char* header_key = test_cases[i].extra_headers[0][ct * 2]; |  | 
| 3556       const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1]; |  | 
| 3557       request.extra_headers.SetHeader(header_key, header_value); |  | 
| 3558     } |  | 
| 3559 |  | 
| 3560     scoped_ptr<DelayedSocketData> data( |  | 
| 3561         new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 3562                               writes, arraysize(writes))); |  | 
| 3563     NormalSpdyTransactionHelper helper(request, |  | 
| 3564                                        BoundNetLog(), GetParam()); |  | 
| 3565     helper.RunToCompletion(data.get()); |  | 
| 3566     TransactionHelperResult out = helper.output(); |  | 
| 3567 |  | 
| 3568     EXPECT_EQ(OK, out.rv) << i; |  | 
| 3569     EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i; |  | 
| 3570     EXPECT_EQ("hello!", out.response_data) << i; |  | 
| 3571 |  | 
| 3572     // Test the response information. |  | 
| 3573     EXPECT_TRUE(out.response_info.response_time > |  | 
| 3574                 out.response_info.request_time) << i; |  | 
| 3575     base::TimeDelta test_delay = out.response_info.response_time - |  | 
| 3576                                  out.response_info.request_time; |  | 
| 3577     base::TimeDelta min_expected_delay; |  | 
| 3578     min_expected_delay.FromMilliseconds(10); |  | 
| 3579     EXPECT_GT(test_delay.InMillisecondsF(), |  | 
| 3580               min_expected_delay.InMillisecondsF()) << i; |  | 
| 3581     EXPECT_EQ(out.response_info.vary_data.is_valid(), |  | 
| 3582               test_cases[i].vary_matches) << i; |  | 
| 3583 |  | 
| 3584     // Check the headers. |  | 
| 3585     scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers; |  | 
| 3586     ASSERT_TRUE(headers.get() != NULL) << i; |  | 
| 3587     void* iter = NULL; |  | 
| 3588     std::string name, value, lines; |  | 
| 3589     while (headers->EnumerateHeaderLines(&iter, &name, &value)) { |  | 
| 3590       lines.append(name); |  | 
| 3591       lines.append(": "); |  | 
| 3592       lines.append(value); |  | 
| 3593       lines.append("\n"); |  | 
| 3594     } |  | 
| 3595 |  | 
| 3596     // Construct the expected header reply string. |  | 
| 3597     char reply_buffer[256] = ""; |  | 
| 3598     ConstructSpdyReplyString(test_cases[i].extra_headers[1], |  | 
| 3599                              test_cases[i].num_headers[1], |  | 
| 3600                              reply_buffer, |  | 
| 3601                              256); |  | 
| 3602 |  | 
| 3603     EXPECT_EQ(std::string(reply_buffer), lines) << i; |  | 
| 3604   } |  | 
| 3605 } |  | 
| 3606 |  | 
| 3607 // Verify that we don't crash on invalid SynReply responses. |  | 
| 3608 TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) { |  | 
| 3609   const SpdyHeaderInfo kSynStartHeader = { |  | 
| 3610     spdy::SYN_REPLY,              // Kind = SynReply |  | 
| 3611     1,                            // Stream ID |  | 
| 3612     0,                            // Associated stream ID |  | 
| 3613     net::ConvertRequestPriorityToSpdyPriority(LOWEST), |  | 
| 3614                                   // Priority |  | 
| 3615     spdy::CONTROL_FLAG_NONE,      // Control Flags |  | 
| 3616     false,                        // Compressed |  | 
| 3617     spdy::INVALID,                // Status |  | 
| 3618     NULL,                         // Data |  | 
| 3619     0,                            // Length |  | 
| 3620     spdy::DATA_FLAG_NONE          // Data Flags |  | 
| 3621   }; |  | 
| 3622 |  | 
| 3623   struct InvalidSynReplyTests { |  | 
| 3624     int num_headers; |  | 
| 3625     const char* headers[10]; |  | 
| 3626   } test_cases[] = { |  | 
| 3627     // SYN_REPLY missing status header |  | 
| 3628     { 4, |  | 
| 3629       { "cookie", "val1", |  | 
| 3630         "cookie", "val2", |  | 
| 3631         "url", "/index.php", |  | 
| 3632         "version", "HTTP/1.1", |  | 
| 3633         NULL |  | 
| 3634       }, |  | 
| 3635     }, |  | 
| 3636     // SYN_REPLY missing version header |  | 
| 3637     { 2, |  | 
| 3638       { "status", "200", |  | 
| 3639         "url", "/index.php", |  | 
| 3640         NULL |  | 
| 3641       }, |  | 
| 3642     }, |  | 
| 3643     // SYN_REPLY with no headers |  | 
| 3644     { 0, { NULL }, }, |  | 
| 3645   }; |  | 
| 3646 |  | 
| 3647   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { |  | 
| 3648     scoped_ptr<spdy::SpdyFrame> req( |  | 
| 3649         ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 3650     MockWrite writes[] = { |  | 
| 3651       CreateMockWrite(*req), |  | 
| 3652     }; |  | 
| 3653 |  | 
| 3654     scoped_ptr<spdy::SpdyFrame> resp( |  | 
| 3655         ConstructSpdyPacket(kSynStartHeader, |  | 
| 3656                             NULL, 0, |  | 
| 3657                             test_cases[i].headers, |  | 
| 3658                             test_cases[i].num_headers)); |  | 
| 3659     scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 3660     MockRead reads[] = { |  | 
| 3661       CreateMockRead(*resp), |  | 
| 3662       CreateMockRead(*body), |  | 
| 3663       MockRead(ASYNC, 0, 0)  // EOF |  | 
| 3664     }; |  | 
| 3665 |  | 
| 3666     scoped_ptr<DelayedSocketData> data( |  | 
| 3667         new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 3668                               writes, arraysize(writes))); |  | 
| 3669     NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 3670                                        BoundNetLog(), GetParam()); |  | 
| 3671     helper.RunToCompletion(data.get()); |  | 
| 3672     TransactionHelperResult out = helper.output(); |  | 
| 3673     EXPECT_EQ(ERR_INCOMPLETE_SPDY_HEADERS, out.rv); |  | 
| 3674   } |  | 
| 3675 } |  | 
| 3676 |  | 
| 3677 // Verify that we don't crash on some corrupt frames. |  | 
| 3678 TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) { |  | 
| 3679   // This is the length field that's too short. |  | 
| 3680   scoped_ptr<spdy::SpdyFrame> syn_reply_wrong_length( |  | 
| 3681       ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 3682   syn_reply_wrong_length->set_length(syn_reply_wrong_length->length() - 4); |  | 
| 3683 |  | 
| 3684   struct SynReplyTests { |  | 
| 3685     const spdy::SpdyFrame* syn_reply; |  | 
| 3686   } test_cases[] = { |  | 
| 3687     { syn_reply_wrong_length.get(), }, |  | 
| 3688   }; |  | 
| 3689 |  | 
| 3690   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) { |  | 
| 3691     scoped_ptr<spdy::SpdyFrame> req( |  | 
| 3692         ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 3693     MockWrite writes[] = { |  | 
| 3694       CreateMockWrite(*req), |  | 
| 3695       MockWrite(ASYNC, 0, 0)  // EOF |  | 
| 3696     }; |  | 
| 3697 |  | 
| 3698     scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 3699     MockRead reads[] = { |  | 
| 3700       CreateMockRead(*test_cases[i].syn_reply), |  | 
| 3701       CreateMockRead(*body), |  | 
| 3702       MockRead(ASYNC, 0, 0)  // EOF |  | 
| 3703     }; |  | 
| 3704 |  | 
| 3705     scoped_ptr<DelayedSocketData> data( |  | 
| 3706         new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 3707                               writes, arraysize(writes))); |  | 
| 3708     NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 3709                                        BoundNetLog(), GetParam()); |  | 
| 3710     helper.RunToCompletion(data.get()); |  | 
| 3711     TransactionHelperResult out = helper.output(); |  | 
| 3712     EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); |  | 
| 3713   } |  | 
| 3714 } |  | 
| 3715 |  | 
| 3716 // Test that we shutdown correctly on write errors. |  | 
| 3717 TEST_P(SpdyNetworkTransactionTest, WriteError) { |  | 
| 3718   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 3719   MockWrite writes[] = { |  | 
| 3720     // We'll write 10 bytes successfully |  | 
| 3721     MockWrite(ASYNC, req->data(), 10), |  | 
| 3722     // Followed by ERROR! |  | 
| 3723     MockWrite(ASYNC, ERR_FAILED), |  | 
| 3724   }; |  | 
| 3725 |  | 
| 3726   scoped_ptr<DelayedSocketData> data( |  | 
| 3727       new DelayedSocketData(2, NULL, 0, |  | 
| 3728                             writes, arraysize(writes))); |  | 
| 3729   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 3730                                      BoundNetLog(), GetParam()); |  | 
| 3731   helper.RunToCompletion(data.get()); |  | 
| 3732   TransactionHelperResult out = helper.output(); |  | 
| 3733   EXPECT_EQ(ERR_FAILED, out.rv); |  | 
| 3734   data->Reset(); |  | 
| 3735 } |  | 
| 3736 |  | 
| 3737 // Test that partial writes work. |  | 
| 3738 TEST_P(SpdyNetworkTransactionTest, PartialWrite) { |  | 
| 3739   // Chop the SYN_STREAM frame into 5 chunks. |  | 
| 3740   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 3741   const int kChunks = 5; |  | 
| 3742   scoped_array<MockWrite> writes(ChopWriteFrame(*req.get(), kChunks)); |  | 
| 3743 |  | 
| 3744   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 3745   scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 3746   MockRead reads[] = { |  | 
| 3747     CreateMockRead(*resp), |  | 
| 3748     CreateMockRead(*body), |  | 
| 3749     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 3750   }; |  | 
| 3751 |  | 
| 3752   scoped_ptr<DelayedSocketData> data( |  | 
| 3753       new DelayedSocketData(kChunks, reads, arraysize(reads), |  | 
| 3754                             writes.get(), kChunks)); |  | 
| 3755   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 3756                                      BoundNetLog(), GetParam()); |  | 
| 3757   helper.RunToCompletion(data.get()); |  | 
| 3758   TransactionHelperResult out = helper.output(); |  | 
| 3759   EXPECT_EQ(OK, out.rv); |  | 
| 3760   EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |  | 
| 3761   EXPECT_EQ("hello!", out.response_data); |  | 
| 3762 } |  | 
| 3763 |  | 
| 3764 // In this test, we enable compression, but get a uncompressed SynReply from |  | 
| 3765 // the server.  Verify that teardown is all clean. |  | 
| 3766 TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) { |  | 
| 3767   // For this test, we turn on the normal compression. |  | 
| 3768   EnableCompression(true); |  | 
| 3769 |  | 
| 3770   scoped_ptr<spdy::SpdyFrame> compressed( |  | 
| 3771       ConstructSpdyGet(NULL, 0, true, 1, LOWEST)); |  | 
| 3772   scoped_ptr<spdy::SpdyFrame> rst( |  | 
| 3773       ConstructSpdyRstStream(1, spdy::PROTOCOL_ERROR)); |  | 
| 3774   MockWrite writes[] = { |  | 
| 3775     CreateMockWrite(*compressed), |  | 
| 3776   }; |  | 
| 3777 |  | 
| 3778   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 3779   scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 3780   MockRead reads[] = { |  | 
| 3781     CreateMockRead(*resp), |  | 
| 3782   }; |  | 
| 3783 |  | 
| 3784   scoped_ptr<DelayedSocketData> data( |  | 
| 3785       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 3786                             writes, arraysize(writes))); |  | 
| 3787   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 3788                                      BoundNetLog(), GetParam()); |  | 
| 3789   helper.RunToCompletion(data.get()); |  | 
| 3790   TransactionHelperResult out = helper.output(); |  | 
| 3791   EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); |  | 
| 3792   data->Reset(); |  | 
| 3793 |  | 
| 3794   EnableCompression(false); |  | 
| 3795 } |  | 
| 3796 |  | 
| 3797 // Test that the NetLog contains good data for a simple GET request. |  | 
| 3798 TEST_P(SpdyNetworkTransactionTest, NetLog) { |  | 
| 3799   static const char* const kExtraHeaders[] = { |  | 
| 3800     "user-agent",   "Chrome", |  | 
| 3801   }; |  | 
| 3802   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(kExtraHeaders, 1, false, 1, |  | 
| 3803                                                    LOWEST)); |  | 
| 3804   MockWrite writes[] = { CreateMockWrite(*req) }; |  | 
| 3805 |  | 
| 3806   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 3807   scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 3808   MockRead reads[] = { |  | 
| 3809     CreateMockRead(*resp), |  | 
| 3810     CreateMockRead(*body), |  | 
| 3811     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 3812   }; |  | 
| 3813 |  | 
| 3814   net::CapturingBoundNetLog log(net::CapturingNetLog::kUnbounded); |  | 
| 3815 |  | 
| 3816   scoped_ptr<DelayedSocketData> data( |  | 
| 3817       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 3818                             writes, arraysize(writes))); |  | 
| 3819   NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(), |  | 
| 3820                                      log.bound(), GetParam()); |  | 
| 3821   helper.RunToCompletion(data.get()); |  | 
| 3822   TransactionHelperResult out = helper.output(); |  | 
| 3823   EXPECT_EQ(OK, out.rv); |  | 
| 3824   EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |  | 
| 3825   EXPECT_EQ("hello!", out.response_data); |  | 
| 3826 |  | 
| 3827   // Check that the NetLog was filled reasonably. |  | 
| 3828   // This test is intentionally non-specific about the exact ordering of the |  | 
| 3829   // log; instead we just check to make sure that certain events exist, and that |  | 
| 3830   // they are in the right order. |  | 
| 3831   net::CapturingNetLog::EntryList entries; |  | 
| 3832   log.GetEntries(&entries); |  | 
| 3833 |  | 
| 3834   EXPECT_LT(0u, entries.size()); |  | 
| 3835   int pos = 0; |  | 
| 3836   pos = net::ExpectLogContainsSomewhere(entries, 0, |  | 
| 3837       net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, |  | 
| 3838       net::NetLog::PHASE_BEGIN); |  | 
| 3839   pos = net::ExpectLogContainsSomewhere(entries, pos + 1, |  | 
| 3840       net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST, |  | 
| 3841       net::NetLog::PHASE_END); |  | 
| 3842   pos = net::ExpectLogContainsSomewhere(entries, pos + 1, |  | 
| 3843       net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, |  | 
| 3844       net::NetLog::PHASE_BEGIN); |  | 
| 3845   pos = net::ExpectLogContainsSomewhere(entries, pos + 1, |  | 
| 3846       net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS, |  | 
| 3847       net::NetLog::PHASE_END); |  | 
| 3848   pos = net::ExpectLogContainsSomewhere(entries, pos + 1, |  | 
| 3849       net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, |  | 
| 3850       net::NetLog::PHASE_BEGIN); |  | 
| 3851   pos = net::ExpectLogContainsSomewhere(entries, pos + 1, |  | 
| 3852       net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY, |  | 
| 3853       net::NetLog::PHASE_END); |  | 
| 3854 |  | 
| 3855   // Check that we logged all the headers correctly |  | 
| 3856   pos = net::ExpectLogContainsSomewhere( |  | 
| 3857       entries, 0, |  | 
| 3858       net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM, |  | 
| 3859       net::NetLog::PHASE_NONE); |  | 
| 3860   CapturingNetLog::Entry entry = entries[pos]; |  | 
| 3861   NetLogSpdySynParameter* request_params = |  | 
| 3862       static_cast<NetLogSpdySynParameter*>(entry.extra_parameters.get()); |  | 
| 3863   spdy::SpdyHeaderBlock* headers = |  | 
| 3864       request_params->GetHeaders().get(); |  | 
| 3865 |  | 
| 3866   spdy::SpdyHeaderBlock expected; |  | 
| 3867   expected["host"] = "www.google.com"; |  | 
| 3868   expected["url"] = "/"; |  | 
| 3869   expected["scheme"] = "http"; |  | 
| 3870   expected["version"] = "HTTP/1.1"; |  | 
| 3871   expected["method"] = "GET"; |  | 
| 3872   expected["user-agent"] = "Chrome"; |  | 
| 3873   EXPECT_EQ(expected.size(), headers->size()); |  | 
| 3874   spdy::SpdyHeaderBlock::const_iterator end = expected.end(); |  | 
| 3875   for (spdy::SpdyHeaderBlock::const_iterator it = expected.begin(); |  | 
| 3876       it != end; |  | 
| 3877       ++it) { |  | 
| 3878     EXPECT_EQ(it->second, (*headers)[it->first]); |  | 
| 3879   } |  | 
| 3880 } |  | 
| 3881 |  | 
| 3882 // Since we buffer the IO from the stream to the renderer, this test verifies |  | 
| 3883 // that when we read out the maximum amount of data (e.g. we received 50 bytes |  | 
| 3884 // on the network, but issued a Read for only 5 of those bytes) that the data |  | 
| 3885 // flow still works correctly. |  | 
| 3886 TEST_P(SpdyNetworkTransactionTest, BufferFull) { |  | 
| 3887   SpdySession::set_use_flow_control(SpdySession::kDisableFlowControl); |  | 
| 3888 |  | 
| 3889   spdy::SpdyFramer framer; |  | 
| 3890 |  | 
| 3891   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 3892   MockWrite writes[] = { CreateMockWrite(*req) }; |  | 
| 3893 |  | 
| 3894   // 2 data frames in a single read. |  | 
| 3895   scoped_ptr<spdy::SpdyFrame> data_frame_1( |  | 
| 3896       framer.CreateDataFrame(1, "goodby", 6, spdy::DATA_FLAG_NONE)); |  | 
| 3897   scoped_ptr<spdy::SpdyFrame> data_frame_2( |  | 
| 3898       framer.CreateDataFrame(1, "e worl", 6, spdy::DATA_FLAG_NONE)); |  | 
| 3899   const spdy::SpdyFrame* data_frames[2] = { |  | 
| 3900     data_frame_1.get(), |  | 
| 3901     data_frame_2.get(), |  | 
| 3902   }; |  | 
| 3903   char combined_data_frames[100]; |  | 
| 3904   int combined_data_frames_len = |  | 
| 3905       CombineFrames(data_frames, arraysize(data_frames), |  | 
| 3906                     combined_data_frames, arraysize(combined_data_frames)); |  | 
| 3907   scoped_ptr<spdy::SpdyFrame> last_frame( |  | 
| 3908       framer.CreateDataFrame(1, "d", 1, spdy::DATA_FLAG_FIN)); |  | 
| 3909 |  | 
| 3910   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 3911   MockRead reads[] = { |  | 
| 3912     CreateMockRead(*resp), |  | 
| 3913     MockRead(ASYNC, ERR_IO_PENDING),  // Force a pause |  | 
| 3914     MockRead(ASYNC, combined_data_frames, combined_data_frames_len), |  | 
| 3915     MockRead(ASYNC, ERR_IO_PENDING),  // Force a pause |  | 
| 3916     CreateMockRead(*last_frame), |  | 
| 3917     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 3918   }; |  | 
| 3919 |  | 
| 3920   scoped_ptr<DelayedSocketData> data( |  | 
| 3921       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 3922                             writes, arraysize(writes))); |  | 
| 3923 |  | 
| 3924 |  | 
| 3925   TestCompletionCallback callback; |  | 
| 3926 |  | 
| 3927   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 3928                                      BoundNetLog(), GetParam()); |  | 
| 3929   helper.RunPreTestSetup(); |  | 
| 3930   helper.AddData(data.get()); |  | 
| 3931   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 3932   int rv = trans->Start( |  | 
| 3933       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 3934   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 3935 |  | 
| 3936   TransactionHelperResult out = helper.output(); |  | 
| 3937   out.rv = callback.WaitForResult(); |  | 
| 3938   EXPECT_EQ(out.rv, OK); |  | 
| 3939 |  | 
| 3940   const HttpResponseInfo* response = trans->GetResponseInfo(); |  | 
| 3941   EXPECT_TRUE(response->headers != NULL); |  | 
| 3942   EXPECT_TRUE(response->was_fetched_via_spdy); |  | 
| 3943   out.status_line = response->headers->GetStatusLine(); |  | 
| 3944   out.response_info = *response;  // Make a copy so we can verify. |  | 
| 3945 |  | 
| 3946   // Read Data |  | 
| 3947   TestCompletionCallback read_callback; |  | 
| 3948 |  | 
| 3949   std::string content; |  | 
| 3950   do { |  | 
| 3951     // Read small chunks at a time. |  | 
| 3952     const int kSmallReadSize = 3; |  | 
| 3953     scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize)); |  | 
| 3954     rv = trans->Read(buf, kSmallReadSize, read_callback.callback()); |  | 
| 3955     if (rv == net::ERR_IO_PENDING) { |  | 
| 3956       data->CompleteRead(); |  | 
| 3957       rv = read_callback.WaitForResult(); |  | 
| 3958     } |  | 
| 3959     if (rv > 0) { |  | 
| 3960       content.append(buf->data(), rv); |  | 
| 3961     } else if (rv < 0) { |  | 
| 3962       NOTREACHED(); |  | 
| 3963     } |  | 
| 3964   } while (rv > 0); |  | 
| 3965 |  | 
| 3966   out.response_data.swap(content); |  | 
| 3967 |  | 
| 3968   // Flush the MessageLoop while the SpdySessionDependencies (in particular, the |  | 
| 3969   // MockClientSocketFactory) are still alive. |  | 
| 3970   MessageLoop::current()->RunAllPending(); |  | 
| 3971 |  | 
| 3972   // Verify that we consumed all test data. |  | 
| 3973   helper.VerifyDataConsumed(); |  | 
| 3974 |  | 
| 3975   EXPECT_EQ(OK, out.rv); |  | 
| 3976   EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |  | 
| 3977   EXPECT_EQ("goodbye world", out.response_data); |  | 
| 3978 |  | 
| 3979   SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN); |  | 
| 3980 } |  | 
| 3981 |  | 
| 3982 // Verify that basic buffering works; when multiple data frames arrive |  | 
| 3983 // at the same time, ensure that we don't notify a read completion for |  | 
| 3984 // each data frame individually. |  | 
| 3985 TEST_P(SpdyNetworkTransactionTest, Buffering) { |  | 
| 3986   SpdySession::set_use_flow_control(SpdySession::kDisableFlowControl); |  | 
| 3987 |  | 
| 3988   spdy::SpdyFramer framer; |  | 
| 3989 |  | 
| 3990   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 3991   MockWrite writes[] = { CreateMockWrite(*req) }; |  | 
| 3992 |  | 
| 3993   // 4 data frames in a single read. |  | 
| 3994   scoped_ptr<spdy::SpdyFrame> data_frame( |  | 
| 3995       framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE)); |  | 
| 3996   scoped_ptr<spdy::SpdyFrame> data_frame_fin( |  | 
| 3997       framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN)); |  | 
| 3998   const spdy::SpdyFrame* data_frames[4] = { |  | 
| 3999     data_frame.get(), |  | 
| 4000     data_frame.get(), |  | 
| 4001     data_frame.get(), |  | 
| 4002     data_frame_fin.get() |  | 
| 4003   }; |  | 
| 4004   char combined_data_frames[100]; |  | 
| 4005   int combined_data_frames_len = |  | 
| 4006       CombineFrames(data_frames, arraysize(data_frames), |  | 
| 4007                     combined_data_frames, arraysize(combined_data_frames)); |  | 
| 4008 |  | 
| 4009   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 4010   MockRead reads[] = { |  | 
| 4011     CreateMockRead(*resp), |  | 
| 4012     MockRead(ASYNC, ERR_IO_PENDING),  // Force a pause |  | 
| 4013     MockRead(ASYNC, combined_data_frames, combined_data_frames_len), |  | 
| 4014     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 4015   }; |  | 
| 4016 |  | 
| 4017   scoped_ptr<DelayedSocketData> data( |  | 
| 4018       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 4019                             writes, arraysize(writes))); |  | 
| 4020 |  | 
| 4021   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 4022                                      BoundNetLog(), GetParam()); |  | 
| 4023   helper.RunPreTestSetup(); |  | 
| 4024   helper.AddData(data.get()); |  | 
| 4025   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 4026 |  | 
| 4027   TestCompletionCallback callback; |  | 
| 4028   int rv = trans->Start( |  | 
| 4029       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 4030   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 4031 |  | 
| 4032   TransactionHelperResult out = helper.output(); |  | 
| 4033   out.rv = callback.WaitForResult(); |  | 
| 4034   EXPECT_EQ(out.rv, OK); |  | 
| 4035 |  | 
| 4036   const HttpResponseInfo* response = trans->GetResponseInfo(); |  | 
| 4037   EXPECT_TRUE(response->headers != NULL); |  | 
| 4038   EXPECT_TRUE(response->was_fetched_via_spdy); |  | 
| 4039   out.status_line = response->headers->GetStatusLine(); |  | 
| 4040   out.response_info = *response;  // Make a copy so we can verify. |  | 
| 4041 |  | 
| 4042   // Read Data |  | 
| 4043   TestCompletionCallback read_callback; |  | 
| 4044 |  | 
| 4045   std::string content; |  | 
| 4046   int reads_completed = 0; |  | 
| 4047   do { |  | 
| 4048     // Read small chunks at a time. |  | 
| 4049     const int kSmallReadSize = 14; |  | 
| 4050     scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize)); |  | 
| 4051     rv = trans->Read(buf, kSmallReadSize, read_callback.callback()); |  | 
| 4052     if (rv == net::ERR_IO_PENDING) { |  | 
| 4053       data->CompleteRead(); |  | 
| 4054       rv = read_callback.WaitForResult(); |  | 
| 4055     } |  | 
| 4056     if (rv > 0) { |  | 
| 4057       EXPECT_EQ(kSmallReadSize, rv); |  | 
| 4058       content.append(buf->data(), rv); |  | 
| 4059     } else if (rv < 0) { |  | 
| 4060       FAIL() << "Unexpected read error: " << rv; |  | 
| 4061     } |  | 
| 4062     reads_completed++; |  | 
| 4063   } while (rv > 0); |  | 
| 4064 |  | 
| 4065   EXPECT_EQ(3, reads_completed);  // Reads are: 14 bytes, 14 bytes, 0 bytes. |  | 
| 4066 |  | 
| 4067   out.response_data.swap(content); |  | 
| 4068 |  | 
| 4069   // Flush the MessageLoop while the SpdySessionDependencies (in particular, the |  | 
| 4070   // MockClientSocketFactory) are still alive. |  | 
| 4071   MessageLoop::current()->RunAllPending(); |  | 
| 4072 |  | 
| 4073   // Verify that we consumed all test data. |  | 
| 4074   helper.VerifyDataConsumed(); |  | 
| 4075 |  | 
| 4076   EXPECT_EQ(OK, out.rv); |  | 
| 4077   EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |  | 
| 4078   EXPECT_EQ("messagemessagemessagemessage", out.response_data); |  | 
| 4079 |  | 
| 4080   SpdySession::set_use_flow_control(SpdySession::kFlowControlBasedOnNPN); |  | 
| 4081 } |  | 
| 4082 |  | 
| 4083 // Verify the case where we buffer data but read it after it has been buffered. |  | 
| 4084 TEST_P(SpdyNetworkTransactionTest, BufferedAll) { |  | 
| 4085   spdy::SpdyFramer framer; |  | 
| 4086 |  | 
| 4087   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 4088   MockWrite writes[] = { CreateMockWrite(*req) }; |  | 
| 4089 |  | 
| 4090   // 5 data frames in a single read. |  | 
| 4091   scoped_ptr<spdy::SpdyFrame> syn_reply( |  | 
| 4092       ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 4093   syn_reply->set_flags(spdy::CONTROL_FLAG_NONE);  // turn off FIN bit |  | 
| 4094   scoped_ptr<spdy::SpdyFrame> data_frame( |  | 
| 4095       framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE)); |  | 
| 4096   scoped_ptr<spdy::SpdyFrame> data_frame_fin( |  | 
| 4097       framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_FIN)); |  | 
| 4098   const spdy::SpdyFrame* frames[5] = { |  | 
| 4099     syn_reply.get(), |  | 
| 4100     data_frame.get(), |  | 
| 4101     data_frame.get(), |  | 
| 4102     data_frame.get(), |  | 
| 4103     data_frame_fin.get() |  | 
| 4104   }; |  | 
| 4105   char combined_frames[200]; |  | 
| 4106   int combined_frames_len = |  | 
| 4107       CombineFrames(frames, arraysize(frames), |  | 
| 4108                     combined_frames, arraysize(combined_frames)); |  | 
| 4109 |  | 
| 4110   MockRead reads[] = { |  | 
| 4111     MockRead(ASYNC, combined_frames, combined_frames_len), |  | 
| 4112     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 4113   }; |  | 
| 4114 |  | 
| 4115   scoped_ptr<DelayedSocketData> data( |  | 
| 4116       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 4117                             writes, arraysize(writes))); |  | 
| 4118 |  | 
| 4119   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 4120                                      BoundNetLog(), GetParam()); |  | 
| 4121   helper.RunPreTestSetup(); |  | 
| 4122   helper.AddData(data.get()); |  | 
| 4123   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 4124 |  | 
| 4125   TestCompletionCallback callback; |  | 
| 4126   int rv = trans->Start( |  | 
| 4127       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 4128   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 4129 |  | 
| 4130   TransactionHelperResult out = helper.output(); |  | 
| 4131   out.rv = callback.WaitForResult(); |  | 
| 4132   EXPECT_EQ(out.rv, OK); |  | 
| 4133 |  | 
| 4134   const HttpResponseInfo* response = trans->GetResponseInfo(); |  | 
| 4135   EXPECT_TRUE(response->headers != NULL); |  | 
| 4136   EXPECT_TRUE(response->was_fetched_via_spdy); |  | 
| 4137   out.status_line = response->headers->GetStatusLine(); |  | 
| 4138   out.response_info = *response;  // Make a copy so we can verify. |  | 
| 4139 |  | 
| 4140   // Read Data |  | 
| 4141   TestCompletionCallback read_callback; |  | 
| 4142 |  | 
| 4143   std::string content; |  | 
| 4144   int reads_completed = 0; |  | 
| 4145   do { |  | 
| 4146     // Read small chunks at a time. |  | 
| 4147     const int kSmallReadSize = 14; |  | 
| 4148     scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize)); |  | 
| 4149     rv = trans->Read(buf, kSmallReadSize, read_callback.callback()); |  | 
| 4150     if (rv > 0) { |  | 
| 4151       EXPECT_EQ(kSmallReadSize, rv); |  | 
| 4152       content.append(buf->data(), rv); |  | 
| 4153     } else if (rv < 0) { |  | 
| 4154       FAIL() << "Unexpected read error: " << rv; |  | 
| 4155     } |  | 
| 4156     reads_completed++; |  | 
| 4157   } while (rv > 0); |  | 
| 4158 |  | 
| 4159   EXPECT_EQ(3, reads_completed); |  | 
| 4160 |  | 
| 4161   out.response_data.swap(content); |  | 
| 4162 |  | 
| 4163   // Flush the MessageLoop while the SpdySessionDependencies (in particular, the |  | 
| 4164   // MockClientSocketFactory) are still alive. |  | 
| 4165   MessageLoop::current()->RunAllPending(); |  | 
| 4166 |  | 
| 4167   // Verify that we consumed all test data. |  | 
| 4168   helper.VerifyDataConsumed(); |  | 
| 4169 |  | 
| 4170   EXPECT_EQ(OK, out.rv); |  | 
| 4171   EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |  | 
| 4172   EXPECT_EQ("messagemessagemessagemessage", out.response_data); |  | 
| 4173 } |  | 
| 4174 |  | 
| 4175 // Verify the case where we buffer data and close the connection. |  | 
| 4176 TEST_P(SpdyNetworkTransactionTest, BufferedClosed) { |  | 
| 4177   spdy::SpdyFramer framer; |  | 
| 4178 |  | 
| 4179   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 4180   MockWrite writes[] = { CreateMockWrite(*req) }; |  | 
| 4181 |  | 
| 4182   // All data frames in a single read. |  | 
| 4183   // NOTE: We don't FIN the stream. |  | 
| 4184   scoped_ptr<spdy::SpdyFrame> data_frame( |  | 
| 4185       framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE)); |  | 
| 4186   const spdy::SpdyFrame* data_frames[4] = { |  | 
| 4187     data_frame.get(), |  | 
| 4188     data_frame.get(), |  | 
| 4189     data_frame.get(), |  | 
| 4190     data_frame.get() |  | 
| 4191   }; |  | 
| 4192   char combined_data_frames[100]; |  | 
| 4193   int combined_data_frames_len = |  | 
| 4194       CombineFrames(data_frames, arraysize(data_frames), |  | 
| 4195                     combined_data_frames, arraysize(combined_data_frames)); |  | 
| 4196   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 4197   MockRead reads[] = { |  | 
| 4198     CreateMockRead(*resp), |  | 
| 4199     MockRead(ASYNC, ERR_IO_PENDING),  // Force a wait |  | 
| 4200     MockRead(ASYNC, combined_data_frames, combined_data_frames_len), |  | 
| 4201     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 4202   }; |  | 
| 4203 |  | 
| 4204   scoped_ptr<DelayedSocketData> data( |  | 
| 4205       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 4206                             writes, arraysize(writes))); |  | 
| 4207 |  | 
| 4208   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 4209                                      BoundNetLog(), GetParam()); |  | 
| 4210   helper.RunPreTestSetup(); |  | 
| 4211   helper.AddData(data.get()); |  | 
| 4212   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 4213 |  | 
| 4214   TestCompletionCallback callback; |  | 
| 4215 |  | 
| 4216   int rv = trans->Start( |  | 
| 4217       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 4218   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 4219 |  | 
| 4220   TransactionHelperResult out = helper.output(); |  | 
| 4221   out.rv = callback.WaitForResult(); |  | 
| 4222   EXPECT_EQ(out.rv, OK); |  | 
| 4223 |  | 
| 4224   const HttpResponseInfo* response = trans->GetResponseInfo(); |  | 
| 4225   EXPECT_TRUE(response->headers != NULL); |  | 
| 4226   EXPECT_TRUE(response->was_fetched_via_spdy); |  | 
| 4227   out.status_line = response->headers->GetStatusLine(); |  | 
| 4228   out.response_info = *response;  // Make a copy so we can verify. |  | 
| 4229 |  | 
| 4230   // Read Data |  | 
| 4231   TestCompletionCallback read_callback; |  | 
| 4232 |  | 
| 4233   std::string content; |  | 
| 4234   int reads_completed = 0; |  | 
| 4235   do { |  | 
| 4236     // Read small chunks at a time. |  | 
| 4237     const int kSmallReadSize = 14; |  | 
| 4238     scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize)); |  | 
| 4239     rv = trans->Read(buf, kSmallReadSize, read_callback.callback()); |  | 
| 4240     if (rv == net::ERR_IO_PENDING) { |  | 
| 4241       data->CompleteRead(); |  | 
| 4242       rv = read_callback.WaitForResult(); |  | 
| 4243     } |  | 
| 4244     if (rv > 0) { |  | 
| 4245       content.append(buf->data(), rv); |  | 
| 4246     } else if (rv < 0) { |  | 
| 4247       // This test intentionally closes the connection, and will get an error. |  | 
| 4248       EXPECT_EQ(ERR_CONNECTION_CLOSED, rv); |  | 
| 4249       break; |  | 
| 4250     } |  | 
| 4251     reads_completed++; |  | 
| 4252   } while (rv > 0); |  | 
| 4253 |  | 
| 4254   EXPECT_EQ(0, reads_completed); |  | 
| 4255 |  | 
| 4256   out.response_data.swap(content); |  | 
| 4257 |  | 
| 4258   // Flush the MessageLoop while the SpdySessionDependencies (in particular, the |  | 
| 4259   // MockClientSocketFactory) are still alive. |  | 
| 4260   MessageLoop::current()->RunAllPending(); |  | 
| 4261 |  | 
| 4262   // Verify that we consumed all test data. |  | 
| 4263   helper.VerifyDataConsumed(); |  | 
| 4264 } |  | 
| 4265 |  | 
| 4266 // Verify the case where we buffer data and cancel the transaction. |  | 
| 4267 TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) { |  | 
| 4268   spdy::SpdyFramer framer; |  | 
| 4269 |  | 
| 4270   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 4271   MockWrite writes[] = { CreateMockWrite(*req) }; |  | 
| 4272 |  | 
| 4273   // NOTE: We don't FIN the stream. |  | 
| 4274   scoped_ptr<spdy::SpdyFrame> data_frame( |  | 
| 4275       framer.CreateDataFrame(1, "message", 7, spdy::DATA_FLAG_NONE)); |  | 
| 4276 |  | 
| 4277   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 4278   MockRead reads[] = { |  | 
| 4279     CreateMockRead(*resp), |  | 
| 4280     MockRead(ASYNC, ERR_IO_PENDING),  // Force a wait |  | 
| 4281     CreateMockRead(*data_frame), |  | 
| 4282     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 4283   }; |  | 
| 4284 |  | 
| 4285   scoped_ptr<DelayedSocketData> data( |  | 
| 4286       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 4287                             writes, arraysize(writes))); |  | 
| 4288 |  | 
| 4289   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 4290                                      BoundNetLog(), GetParam()); |  | 
| 4291   helper.RunPreTestSetup(); |  | 
| 4292   helper.AddData(data.get()); |  | 
| 4293   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 4294   TestCompletionCallback callback; |  | 
| 4295 |  | 
| 4296   int rv = trans->Start( |  | 
| 4297       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 4298   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 4299 |  | 
| 4300   TransactionHelperResult out = helper.output(); |  | 
| 4301   out.rv = callback.WaitForResult(); |  | 
| 4302   EXPECT_EQ(out.rv, OK); |  | 
| 4303 |  | 
| 4304   const HttpResponseInfo* response = trans->GetResponseInfo(); |  | 
| 4305   EXPECT_TRUE(response->headers != NULL); |  | 
| 4306   EXPECT_TRUE(response->was_fetched_via_spdy); |  | 
| 4307   out.status_line = response->headers->GetStatusLine(); |  | 
| 4308   out.response_info = *response;  // Make a copy so we can verify. |  | 
| 4309 |  | 
| 4310   // Read Data |  | 
| 4311   TestCompletionCallback read_callback; |  | 
| 4312 |  | 
| 4313   do { |  | 
| 4314     const int kReadSize = 256; |  | 
| 4315     scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize)); |  | 
| 4316     rv = trans->Read(buf, kReadSize, read_callback.callback()); |  | 
| 4317     if (rv == net::ERR_IO_PENDING) { |  | 
| 4318       // Complete the read now, which causes buffering to start. |  | 
| 4319       data->CompleteRead(); |  | 
| 4320       // Destroy the transaction, causing the stream to get cancelled |  | 
| 4321       // and orphaning the buffered IO task. |  | 
| 4322       helper.ResetTrans(); |  | 
| 4323       break; |  | 
| 4324     } |  | 
| 4325     // We shouldn't get here in this test. |  | 
| 4326     FAIL() << "Unexpected read: " << rv; |  | 
| 4327   } while (rv > 0); |  | 
| 4328 |  | 
| 4329   // Flush the MessageLoop; this will cause the buffered IO task |  | 
| 4330   // to run for the final time. |  | 
| 4331   MessageLoop::current()->RunAllPending(); |  | 
| 4332 |  | 
| 4333   // Verify that we consumed all test data. |  | 
| 4334   helper.VerifyDataConsumed(); |  | 
| 4335 } |  | 
| 4336 |  | 
| 4337 // Test that if the server requests persistence of settings, that we save |  | 
| 4338 // the settings in the SpdySettingsStorage. |  | 
| 4339 TEST_P(SpdyNetworkTransactionTest, SettingsSaved) { |  | 
| 4340   static const SpdyHeaderInfo kSynReplyInfo = { |  | 
| 4341     spdy::SYN_REPLY,                              // Syn Reply |  | 
| 4342     1,                                            // Stream ID |  | 
| 4343     0,                                            // Associated Stream ID |  | 
| 4344     net::ConvertRequestPriorityToSpdyPriority(LOWEST), |  | 
| 4345                                                   // Priority |  | 
| 4346     spdy::CONTROL_FLAG_NONE,                      // Control Flags |  | 
| 4347     false,                                        // Compressed |  | 
| 4348     spdy::INVALID,                                // Status |  | 
| 4349     NULL,                                         // Data |  | 
| 4350     0,                                            // Data Length |  | 
| 4351     spdy::DATA_FLAG_NONE                          // Data Flags |  | 
| 4352   }; |  | 
| 4353   static const char* const kExtraHeaders[] = { |  | 
| 4354     "status",   "200", |  | 
| 4355     "version",  "HTTP/1.1" |  | 
| 4356   }; |  | 
| 4357 |  | 
| 4358   BoundNetLog net_log; |  | 
| 4359   NormalSpdyTransactionHelper helper(CreateGetRequest(), net_log, GetParam()); |  | 
| 4360   helper.RunPreTestSetup(); |  | 
| 4361 |  | 
| 4362   // Verify that no settings exist initially. |  | 
| 4363   HostPortPair host_port_pair("www.google.com", helper.port()); |  | 
| 4364   SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); |  | 
| 4365   EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings( |  | 
| 4366       host_port_pair).empty()); |  | 
| 4367 |  | 
| 4368   // Construct the request. |  | 
| 4369   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 4370   MockWrite writes[] = { CreateMockWrite(*req) }; |  | 
| 4371 |  | 
| 4372   // Construct the reply. |  | 
| 4373   scoped_ptr<spdy::SpdyFrame> reply( |  | 
| 4374     ConstructSpdyPacket(kSynReplyInfo, |  | 
| 4375                         kExtraHeaders, |  | 
| 4376                         arraysize(kExtraHeaders) / 2, |  | 
| 4377                         NULL, |  | 
| 4378                         0)); |  | 
| 4379 |  | 
| 4380   unsigned int kSampleId1 = 0x1; |  | 
| 4381   unsigned int kSampleValue1 = 0x0a0a0a0a; |  | 
| 4382   unsigned int kSampleId2 = 0x2; |  | 
| 4383   unsigned int kSampleValue2 = 0x0b0b0b0b; |  | 
| 4384   unsigned int kSampleId3 = 0xababab; |  | 
| 4385   unsigned int kSampleValue3 = 0x0c0c0c0c; |  | 
| 4386   scoped_ptr<spdy::SpdyFrame> settings_frame; |  | 
| 4387   { |  | 
| 4388     // Construct the SETTINGS frame. |  | 
| 4389     spdy::SpdySettings settings; |  | 
| 4390     spdy::SettingsFlagsAndId setting(0); |  | 
| 4391     // First add a persisted setting |  | 
| 4392     setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST); |  | 
| 4393     setting.set_id(kSampleId1); |  | 
| 4394     settings.push_back(std::make_pair(setting, kSampleValue1)); |  | 
| 4395     // Next add a non-persisted setting |  | 
| 4396     setting.set_flags(0); |  | 
| 4397     setting.set_id(kSampleId2); |  | 
| 4398     settings.push_back(std::make_pair(setting, kSampleValue2)); |  | 
| 4399     // Next add another persisted setting |  | 
| 4400     setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST); |  | 
| 4401     setting.set_id(kSampleId3); |  | 
| 4402     settings.push_back(std::make_pair(setting, kSampleValue3)); |  | 
| 4403     settings_frame.reset(ConstructSpdySettings(settings)); |  | 
| 4404   } |  | 
| 4405 |  | 
| 4406   scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 4407   MockRead reads[] = { |  | 
| 4408     CreateMockRead(*reply), |  | 
| 4409     CreateMockRead(*body), |  | 
| 4410     CreateMockRead(*settings_frame), |  | 
| 4411     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 4412   }; |  | 
| 4413 |  | 
| 4414   scoped_ptr<DelayedSocketData> data( |  | 
| 4415       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 4416                             writes, arraysize(writes))); |  | 
| 4417   helper.AddData(data.get()); |  | 
| 4418   helper.RunDefaultTest(); |  | 
| 4419   helper.VerifyDataConsumed(); |  | 
| 4420   TransactionHelperResult out = helper.output(); |  | 
| 4421   EXPECT_EQ(OK, out.rv); |  | 
| 4422   EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |  | 
| 4423   EXPECT_EQ("hello!", out.response_data); |  | 
| 4424 |  | 
| 4425   { |  | 
| 4426     // Verify we had two persisted settings. |  | 
| 4427     spdy::SpdySettings saved_settings = |  | 
| 4428         spdy_session_pool->http_server_properties()->GetSpdySettings( |  | 
| 4429             host_port_pair); |  | 
| 4430     ASSERT_EQ(2u, saved_settings.size()); |  | 
| 4431 |  | 
| 4432     // Verify the first persisted setting. |  | 
| 4433     spdy::SpdySetting setting = saved_settings.front(); |  | 
| 4434     saved_settings.pop_front(); |  | 
| 4435     EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags()); |  | 
| 4436     EXPECT_EQ(kSampleId1, setting.first.id()); |  | 
| 4437     EXPECT_EQ(kSampleValue1, setting.second); |  | 
| 4438 |  | 
| 4439     // Verify the second persisted setting. |  | 
| 4440     setting = saved_settings.front(); |  | 
| 4441     saved_settings.pop_front(); |  | 
| 4442     EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags()); |  | 
| 4443     EXPECT_EQ(kSampleId3, setting.first.id()); |  | 
| 4444     EXPECT_EQ(kSampleValue3, setting.second); |  | 
| 4445   } |  | 
| 4446 } |  | 
| 4447 |  | 
| 4448 // Test that when there are settings saved that they are sent back to the |  | 
| 4449 // server upon session establishment. |  | 
| 4450 TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) { |  | 
| 4451   static const SpdyHeaderInfo kSynReplyInfo = { |  | 
| 4452     spdy::SYN_REPLY,                              // Syn Reply |  | 
| 4453     1,                                            // Stream ID |  | 
| 4454     0,                                            // Associated Stream ID |  | 
| 4455     net::ConvertRequestPriorityToSpdyPriority(LOWEST), |  | 
| 4456                                                   // Priority |  | 
| 4457     spdy::CONTROL_FLAG_NONE,                      // Control Flags |  | 
| 4458     false,                                        // Compressed |  | 
| 4459     spdy::INVALID,                                // Status |  | 
| 4460     NULL,                                         // Data |  | 
| 4461     0,                                            // Data Length |  | 
| 4462     spdy::DATA_FLAG_NONE                          // Data Flags |  | 
| 4463   }; |  | 
| 4464   static const char* kExtraHeaders[] = { |  | 
| 4465     "status",   "200", |  | 
| 4466     "version",  "HTTP/1.1" |  | 
| 4467   }; |  | 
| 4468 |  | 
| 4469   BoundNetLog net_log; |  | 
| 4470   NormalSpdyTransactionHelper helper(CreateGetRequest(), net_log, GetParam()); |  | 
| 4471   helper.RunPreTestSetup(); |  | 
| 4472 |  | 
| 4473   // Verify that no settings exist initially. |  | 
| 4474   HostPortPair host_port_pair("www.google.com", helper.port()); |  | 
| 4475   SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); |  | 
| 4476   EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings( |  | 
| 4477       host_port_pair).empty()); |  | 
| 4478 |  | 
| 4479   unsigned int kSampleId1 = 0x1; |  | 
| 4480   unsigned int kSampleValue1 = 0x0a0a0a0a; |  | 
| 4481   unsigned int kSampleId2 = 0xababab; |  | 
| 4482   unsigned int kSampleValue2 = 0x0c0c0c0c; |  | 
| 4483   // Manually insert settings into the SpdySettingsStorage here. |  | 
| 4484   { |  | 
| 4485     spdy::SpdySettings settings; |  | 
| 4486     spdy::SettingsFlagsAndId setting(0); |  | 
| 4487     // First add a persisted setting |  | 
| 4488     setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST); |  | 
| 4489     setting.set_id(kSampleId1); |  | 
| 4490     settings.push_back(std::make_pair(setting, kSampleValue1)); |  | 
| 4491     // Next add another persisted setting |  | 
| 4492     setting.set_flags(spdy::SETTINGS_FLAG_PLEASE_PERSIST); |  | 
| 4493     setting.set_id(kSampleId2); |  | 
| 4494     settings.push_back(std::make_pair(setting, kSampleValue2)); |  | 
| 4495 |  | 
| 4496     spdy_session_pool->http_server_properties()->SetSpdySettings( |  | 
| 4497         host_port_pair, settings); |  | 
| 4498   } |  | 
| 4499 |  | 
| 4500   EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings( |  | 
| 4501       host_port_pair).size()); |  | 
| 4502 |  | 
| 4503   // Construct the SETTINGS frame. |  | 
| 4504   const spdy::SpdySettings& settings = |  | 
| 4505       spdy_session_pool->http_server_properties()->GetSpdySettings( |  | 
| 4506           host_port_pair); |  | 
| 4507   scoped_ptr<spdy::SpdyFrame> settings_frame(ConstructSpdySettings(settings)); |  | 
| 4508 |  | 
| 4509   // Construct the request. |  | 
| 4510   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 4511 |  | 
| 4512   MockWrite writes[] = { |  | 
| 4513     CreateMockWrite(*settings_frame), |  | 
| 4514     CreateMockWrite(*req), |  | 
| 4515   }; |  | 
| 4516 |  | 
| 4517   // Construct the reply. |  | 
| 4518   scoped_ptr<spdy::SpdyFrame> reply( |  | 
| 4519     ConstructSpdyPacket(kSynReplyInfo, |  | 
| 4520                         kExtraHeaders, |  | 
| 4521                         arraysize(kExtraHeaders) / 2, |  | 
| 4522                         NULL, |  | 
| 4523                         0)); |  | 
| 4524 |  | 
| 4525   scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 4526   MockRead reads[] = { |  | 
| 4527     CreateMockRead(*reply), |  | 
| 4528     CreateMockRead(*body), |  | 
| 4529     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 4530   }; |  | 
| 4531 |  | 
| 4532   scoped_ptr<DelayedSocketData> data( |  | 
| 4533       new DelayedSocketData(2, reads, arraysize(reads), |  | 
| 4534                             writes, arraysize(writes))); |  | 
| 4535   helper.AddData(data.get()); |  | 
| 4536   helper.RunDefaultTest(); |  | 
| 4537   helper.VerifyDataConsumed(); |  | 
| 4538   TransactionHelperResult out = helper.output(); |  | 
| 4539   EXPECT_EQ(OK, out.rv); |  | 
| 4540   EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |  | 
| 4541   EXPECT_EQ("hello!", out.response_data); |  | 
| 4542 |  | 
| 4543   { |  | 
| 4544     // Verify we had two persisted settings. |  | 
| 4545     spdy::SpdySettings saved_settings = |  | 
| 4546         spdy_session_pool->http_server_properties()->GetSpdySettings( |  | 
| 4547             host_port_pair); |  | 
| 4548     ASSERT_EQ(2u, saved_settings.size()); |  | 
| 4549 |  | 
| 4550     // Verify the first persisted setting. |  | 
| 4551     spdy::SpdySetting setting = saved_settings.front(); |  | 
| 4552     saved_settings.pop_front(); |  | 
| 4553     EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags()); |  | 
| 4554     EXPECT_EQ(kSampleId1, setting.first.id()); |  | 
| 4555     EXPECT_EQ(kSampleValue1, setting.second); |  | 
| 4556 |  | 
| 4557     // Verify the second persisted setting. |  | 
| 4558     setting = saved_settings.front(); |  | 
| 4559     saved_settings.pop_front(); |  | 
| 4560     EXPECT_EQ(spdy::SETTINGS_FLAG_PERSISTED, setting.first.flags()); |  | 
| 4561     EXPECT_EQ(kSampleId2, setting.first.id()); |  | 
| 4562     EXPECT_EQ(kSampleValue2, setting.second); |  | 
| 4563   } |  | 
| 4564 } |  | 
| 4565 |  | 
| 4566 TEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) { |  | 
| 4567   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 4568   MockWrite writes[] = { CreateMockWrite(*req) }; |  | 
| 4569 |  | 
| 4570   scoped_ptr<spdy::SpdyFrame> go_away(ConstructSpdyGoAway()); |  | 
| 4571   MockRead reads[] = { |  | 
| 4572     CreateMockRead(*go_away), |  | 
| 4573     MockRead(ASYNC, 0, 0),  // EOF |  | 
| 4574   }; |  | 
| 4575 |  | 
| 4576   scoped_ptr<DelayedSocketData> data( |  | 
| 4577       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 4578                             writes, arraysize(writes))); |  | 
| 4579   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 4580                                      BoundNetLog(), GetParam()); |  | 
| 4581   helper.AddData(data.get()); |  | 
| 4582   helper.RunToCompletion(data.get()); |  | 
| 4583   TransactionHelperResult out = helper.output(); |  | 
| 4584   EXPECT_EQ(ERR_ABORTED, out.rv); |  | 
| 4585 } |  | 
| 4586 |  | 
| 4587 TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) { |  | 
| 4588   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 4589   MockWrite writes[] = { CreateMockWrite(*req) }; |  | 
| 4590 |  | 
| 4591   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 4592   MockRead reads[] = { |  | 
| 4593     CreateMockRead(*resp), |  | 
| 4594     MockRead(SYNCHRONOUS, 0, 0)  // EOF |  | 
| 4595   }; |  | 
| 4596 |  | 
| 4597   scoped_ptr<DelayedSocketData> data( |  | 
| 4598       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 4599                             writes, arraysize(writes))); |  | 
| 4600   BoundNetLog log; |  | 
| 4601   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 4602                                      log, GetParam()); |  | 
| 4603   helper.RunPreTestSetup(); |  | 
| 4604   helper.AddData(data.get()); |  | 
| 4605   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 4606 |  | 
| 4607   TestCompletionCallback callback; |  | 
| 4608   TransactionHelperResult out; |  | 
| 4609   out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log); |  | 
| 4610 |  | 
| 4611   EXPECT_EQ(out.rv, ERR_IO_PENDING); |  | 
| 4612   out.rv = callback.WaitForResult(); |  | 
| 4613   EXPECT_EQ(out.rv, OK); |  | 
| 4614 |  | 
| 4615   const HttpResponseInfo* response = trans->GetResponseInfo(); |  | 
| 4616   EXPECT_TRUE(response->headers != NULL); |  | 
| 4617   EXPECT_TRUE(response->was_fetched_via_spdy); |  | 
| 4618   out.rv = ReadTransaction(trans, &out.response_data); |  | 
| 4619   EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv); |  | 
| 4620 |  | 
| 4621   // Verify that we consumed all test data. |  | 
| 4622   helper.VerifyDataConsumed(); |  | 
| 4623 } |  | 
| 4624 |  | 
| 4625 // Test to make sure we can correctly connect through a proxy. |  | 
| 4626 TEST_P(SpdyNetworkTransactionTest, ProxyConnect) { |  | 
| 4627   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 4628                                      BoundNetLog(), GetParam()); |  | 
| 4629   helper.session_deps().reset(new SpdySessionDependencies( |  | 
| 4630       ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"))); |  | 
| 4631   helper.SetSession(make_scoped_refptr( |  | 
| 4632       SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get()))); |  | 
| 4633   helper.RunPreTestSetup(); |  | 
| 4634   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 4635 |  | 
| 4636   const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n" |  | 
| 4637                            "Host: www.google.com\r\n" |  | 
| 4638                            "Proxy-Connection: keep-alive\r\n\r\n"}; |  | 
| 4639   const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n" |  | 
| 4640                            "Host: www.google.com\r\n" |  | 
| 4641                            "Proxy-Connection: keep-alive\r\n\r\n"}; |  | 
| 4642   const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"}; |  | 
| 4643   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 4644   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 4645   scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 4646 |  | 
| 4647   MockWrite writes_SPDYNPN[] = { |  | 
| 4648     MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0), |  | 
| 4649     CreateMockWrite(*req, 2), |  | 
| 4650   }; |  | 
| 4651   MockRead reads_SPDYNPN[] = { |  | 
| 4652     MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1), |  | 
| 4653     CreateMockRead(*resp, 3), |  | 
| 4654     CreateMockRead(*body.get(), 4), |  | 
| 4655     MockRead(ASYNC, 0, 0, 5), |  | 
| 4656   }; |  | 
| 4657 |  | 
| 4658   MockWrite writes_SPDYSSL[] = { |  | 
| 4659     MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0), |  | 
| 4660     CreateMockWrite(*req, 2), |  | 
| 4661   }; |  | 
| 4662   MockRead reads_SPDYSSL[] = { |  | 
| 4663     MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1), |  | 
| 4664     CreateMockRead(*resp, 3), |  | 
| 4665     CreateMockRead(*body.get(), 4), |  | 
| 4666     MockRead(ASYNC, 0, 0, 5), |  | 
| 4667   }; |  | 
| 4668 |  | 
| 4669   MockWrite writes_SPDYNOSSL[] = { |  | 
| 4670     CreateMockWrite(*req, 0), |  | 
| 4671   }; |  | 
| 4672 |  | 
| 4673   MockRead reads_SPDYNOSSL[] = { |  | 
| 4674     CreateMockRead(*resp, 1), |  | 
| 4675     CreateMockRead(*body.get(), 2), |  | 
| 4676     MockRead(ASYNC, 0, 0, 3), |  | 
| 4677   }; |  | 
| 4678 |  | 
| 4679   scoped_ptr<OrderedSocketData> data; |  | 
| 4680   switch(GetParam()) { |  | 
| 4681     case SPDYNOSSL: |  | 
| 4682       data.reset(new OrderedSocketData(reads_SPDYNOSSL, |  | 
| 4683                                        arraysize(reads_SPDYNOSSL), |  | 
| 4684                                        writes_SPDYNOSSL, |  | 
| 4685                                        arraysize(writes_SPDYNOSSL))); |  | 
| 4686       break; |  | 
| 4687     case SPDYSSL: |  | 
| 4688       data.reset(new OrderedSocketData(reads_SPDYSSL, |  | 
| 4689                                        arraysize(reads_SPDYSSL), |  | 
| 4690                                        writes_SPDYSSL, |  | 
| 4691                                        arraysize(writes_SPDYSSL))); |  | 
| 4692       break; |  | 
| 4693     case SPDYNPN: |  | 
| 4694       data.reset(new OrderedSocketData(reads_SPDYNPN, |  | 
| 4695                                        arraysize(reads_SPDYNPN), |  | 
| 4696                                        writes_SPDYNPN, |  | 
| 4697                                        arraysize(writes_SPDYNPN))); |  | 
| 4698       break; |  | 
| 4699     default: |  | 
| 4700       NOTREACHED(); |  | 
| 4701   } |  | 
| 4702 |  | 
| 4703   helper.AddData(data.get()); |  | 
| 4704   TestCompletionCallback callback; |  | 
| 4705 |  | 
| 4706   int rv = trans->Start( |  | 
| 4707       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 4708   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 4709 |  | 
| 4710   rv = callback.WaitForResult(); |  | 
| 4711   EXPECT_EQ(0, rv); |  | 
| 4712 |  | 
| 4713   // Verify the SYN_REPLY. |  | 
| 4714   HttpResponseInfo response = *trans->GetResponseInfo(); |  | 
| 4715   EXPECT_TRUE(response.headers != NULL); |  | 
| 4716   EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |  | 
| 4717 |  | 
| 4718   std::string response_data; |  | 
| 4719   ASSERT_EQ(OK, ReadTransaction(trans, &response_data)); |  | 
| 4720   EXPECT_EQ("hello!", response_data); |  | 
| 4721   helper.VerifyDataConsumed(); |  | 
| 4722 } |  | 
| 4723 |  | 
| 4724 // Test to make sure we can correctly connect through a proxy to www.google.com, |  | 
| 4725 // if there already exists a direct spdy connection to www.google.com. See |  | 
| 4726 // http://crbug.com/49874 |  | 
| 4727 TEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) { |  | 
| 4728   // When setting up the first transaction, we store the SpdySessionPool so that |  | 
| 4729   // we can use the same pool in the second transaction. |  | 
| 4730   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 4731                                      BoundNetLog(), GetParam()); |  | 
| 4732 |  | 
| 4733   // Use a proxy service which returns a proxy fallback list from DIRECT to |  | 
| 4734   // myproxy:70. For this test there will be no fallback, so it is equivalent |  | 
| 4735   // to simply DIRECT. The reason for appending the second proxy is to verify |  | 
| 4736   // that the session pool key used does is just "DIRECT". |  | 
| 4737   helper.session_deps().reset(new SpdySessionDependencies( |  | 
| 4738       ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70"))); |  | 
| 4739   helper.SetSession(make_scoped_refptr( |  | 
| 4740       SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get()))); |  | 
| 4741 |  | 
| 4742   SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); |  | 
| 4743   helper.RunPreTestSetup(); |  | 
| 4744 |  | 
| 4745   // Construct and send a simple GET request. |  | 
| 4746   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 4747   MockWrite writes[] = { |  | 
| 4748     CreateMockWrite(*req, 1), |  | 
| 4749   }; |  | 
| 4750 |  | 
| 4751   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 4752   scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 4753   MockRead reads[] = { |  | 
| 4754     CreateMockRead(*resp, 2), |  | 
| 4755     CreateMockRead(*body, 3), |  | 
| 4756     MockRead(ASYNC, ERR_IO_PENDING, 4),  // Force a pause |  | 
| 4757     MockRead(ASYNC, 0, 5)  // EOF |  | 
| 4758   }; |  | 
| 4759   scoped_ptr<OrderedSocketData> data( |  | 
| 4760       new OrderedSocketData(reads, arraysize(reads), |  | 
| 4761                             writes, arraysize(writes))); |  | 
| 4762   helper.AddData(data.get()); |  | 
| 4763   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 4764 |  | 
| 4765   TestCompletionCallback callback; |  | 
| 4766   TransactionHelperResult out; |  | 
| 4767   out.rv = trans->Start( |  | 
| 4768       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 4769 |  | 
| 4770   EXPECT_EQ(out.rv, ERR_IO_PENDING); |  | 
| 4771   out.rv = callback.WaitForResult(); |  | 
| 4772   EXPECT_EQ(out.rv, OK); |  | 
| 4773 |  | 
| 4774   const HttpResponseInfo* response = trans->GetResponseInfo(); |  | 
| 4775   EXPECT_TRUE(response->headers != NULL); |  | 
| 4776   EXPECT_TRUE(response->was_fetched_via_spdy); |  | 
| 4777   out.rv = ReadTransaction(trans, &out.response_data); |  | 
| 4778   EXPECT_EQ(OK, out.rv); |  | 
| 4779   out.status_line = response->headers->GetStatusLine(); |  | 
| 4780   EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |  | 
| 4781   EXPECT_EQ("hello!", out.response_data); |  | 
| 4782 |  | 
| 4783   // Check that the SpdySession is still in the SpdySessionPool. |  | 
| 4784   HostPortPair host_port_pair("www.google.com", helper.port()); |  | 
| 4785   HostPortProxyPair session_pool_key_direct( |  | 
| 4786       host_port_pair, ProxyServer::Direct()); |  | 
| 4787   EXPECT_TRUE(spdy_session_pool->HasSession(session_pool_key_direct)); |  | 
| 4788   HostPortProxyPair session_pool_key_proxy( |  | 
| 4789       host_port_pair, |  | 
| 4790       ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP)); |  | 
| 4791   EXPECT_FALSE(spdy_session_pool->HasSession(session_pool_key_proxy)); |  | 
| 4792 |  | 
| 4793   // Set up data for the proxy connection. |  | 
| 4794   const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n" |  | 
| 4795                            "Host: www.google.com\r\n" |  | 
| 4796                            "Proxy-Connection: keep-alive\r\n\r\n"}; |  | 
| 4797   const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n" |  | 
| 4798                            "Host: www.google.com\r\n" |  | 
| 4799                            "Proxy-Connection: keep-alive\r\n\r\n"}; |  | 
| 4800   const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"}; |  | 
| 4801   scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet( |  | 
| 4802       "http://www.google.com/foo.dat", false, 1, LOWEST)); |  | 
| 4803   scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 4804   scoped_ptr<spdy::SpdyFrame> body2(ConstructSpdyBodyFrame(1, true)); |  | 
| 4805 |  | 
| 4806   MockWrite writes_SPDYNPN[] = { |  | 
| 4807     MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0), |  | 
| 4808     CreateMockWrite(*req2, 2), |  | 
| 4809   }; |  | 
| 4810   MockRead reads_SPDYNPN[] = { |  | 
| 4811     MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1), |  | 
| 4812     CreateMockRead(*resp2, 3), |  | 
| 4813     CreateMockRead(*body2, 4), |  | 
| 4814     MockRead(ASYNC, 0, 5)  // EOF |  | 
| 4815   }; |  | 
| 4816 |  | 
| 4817   MockWrite writes_SPDYNOSSL[] = { |  | 
| 4818     CreateMockWrite(*req2, 0), |  | 
| 4819   }; |  | 
| 4820   MockRead reads_SPDYNOSSL[] = { |  | 
| 4821     CreateMockRead(*resp2, 1), |  | 
| 4822     CreateMockRead(*body2, 2), |  | 
| 4823     MockRead(ASYNC, 0, 3)  // EOF |  | 
| 4824   }; |  | 
| 4825 |  | 
| 4826   MockWrite writes_SPDYSSL[] = { |  | 
| 4827     MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0), |  | 
| 4828     CreateMockWrite(*req2, 2), |  | 
| 4829   }; |  | 
| 4830   MockRead reads_SPDYSSL[] = { |  | 
| 4831     MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1), |  | 
| 4832     CreateMockRead(*resp2, 3), |  | 
| 4833     CreateMockRead(*body2, 4), |  | 
| 4834     MockRead(ASYNC, 0, 0, 5), |  | 
| 4835   }; |  | 
| 4836 |  | 
| 4837   scoped_ptr<OrderedSocketData> data_proxy; |  | 
| 4838   switch(GetParam()) { |  | 
| 4839     case SPDYNPN: |  | 
| 4840       data_proxy.reset(new OrderedSocketData(reads_SPDYNPN, |  | 
| 4841                                              arraysize(reads_SPDYNPN), |  | 
| 4842                                              writes_SPDYNPN, |  | 
| 4843                                              arraysize(writes_SPDYNPN))); |  | 
| 4844       break; |  | 
| 4845     case SPDYNOSSL: |  | 
| 4846       data_proxy.reset(new OrderedSocketData(reads_SPDYNOSSL, |  | 
| 4847                                              arraysize(reads_SPDYNOSSL), |  | 
| 4848                                              writes_SPDYNOSSL, |  | 
| 4849                                              arraysize(writes_SPDYNOSSL))); |  | 
| 4850       break; |  | 
| 4851     case SPDYSSL: |  | 
| 4852       data_proxy.reset(new OrderedSocketData(reads_SPDYSSL, |  | 
| 4853                                              arraysize(reads_SPDYSSL), |  | 
| 4854                                              writes_SPDYSSL, |  | 
| 4855                                              arraysize(writes_SPDYSSL))); |  | 
| 4856       break; |  | 
| 4857     default: |  | 
| 4858       NOTREACHED(); |  | 
| 4859   } |  | 
| 4860 |  | 
| 4861   // Create another request to www.google.com, but this time through a proxy. |  | 
| 4862   HttpRequestInfo request_proxy; |  | 
| 4863   request_proxy.method = "GET"; |  | 
| 4864   request_proxy.url = GURL("http://www.google.com/foo.dat"); |  | 
| 4865   request_proxy.load_flags = 0; |  | 
| 4866   scoped_ptr<SpdySessionDependencies> ssd_proxy(new SpdySessionDependencies()); |  | 
| 4867   // Ensure that this transaction uses the same SpdySessionPool. |  | 
| 4868   scoped_refptr<HttpNetworkSession> session_proxy( |  | 
| 4869       SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get())); |  | 
| 4870   NormalSpdyTransactionHelper helper_proxy(request_proxy, |  | 
| 4871                                            BoundNetLog(), GetParam()); |  | 
| 4872   HttpNetworkSessionPeer session_peer(session_proxy); |  | 
| 4873   scoped_ptr<net::ProxyService> proxy_service( |  | 
| 4874           ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); |  | 
| 4875   session_peer.SetProxyService(proxy_service.get()); |  | 
| 4876   helper_proxy.session_deps().swap(ssd_proxy); |  | 
| 4877   helper_proxy.SetSession(session_proxy); |  | 
| 4878   helper_proxy.RunPreTestSetup(); |  | 
| 4879   helper_proxy.AddData(data_proxy.get()); |  | 
| 4880 |  | 
| 4881   HttpNetworkTransaction* trans_proxy = helper_proxy.trans(); |  | 
| 4882   TestCompletionCallback callback_proxy; |  | 
| 4883   int rv = trans_proxy->Start( |  | 
| 4884       &request_proxy, callback_proxy.callback(), BoundNetLog()); |  | 
| 4885   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 4886   rv = callback_proxy.WaitForResult(); |  | 
| 4887   EXPECT_EQ(0, rv); |  | 
| 4888 |  | 
| 4889   HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo(); |  | 
| 4890   EXPECT_TRUE(response_proxy.headers != NULL); |  | 
| 4891   EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine()); |  | 
| 4892 |  | 
| 4893   std::string response_data; |  | 
| 4894   ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data)); |  | 
| 4895   EXPECT_EQ("hello!", response_data); |  | 
| 4896 |  | 
| 4897   data->CompleteRead(); |  | 
| 4898   helper_proxy.VerifyDataConsumed(); |  | 
| 4899 } |  | 
| 4900 |  | 
| 4901 // When we get a TCP-level RST, we need to retry a HttpNetworkTransaction |  | 
| 4902 // on a new connection, if the connection was previously known to be good. |  | 
| 4903 // This can happen when a server reboots without saying goodbye, or when |  | 
| 4904 // we're behind a NAT that masked the RST. |  | 
| 4905 TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) { |  | 
| 4906   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 4907   scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 4908   MockRead reads[] = { |  | 
| 4909     CreateMockRead(*resp), |  | 
| 4910     CreateMockRead(*body), |  | 
| 4911     MockRead(ASYNC, ERR_IO_PENDING), |  | 
| 4912     MockRead(ASYNC, ERR_CONNECTION_RESET), |  | 
| 4913   }; |  | 
| 4914 |  | 
| 4915   MockRead reads2[] = { |  | 
| 4916     CreateMockRead(*resp), |  | 
| 4917     CreateMockRead(*body), |  | 
| 4918     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 4919   }; |  | 
| 4920 |  | 
| 4921   // This test has a couple of variants. |  | 
| 4922   enum { |  | 
| 4923     // Induce the RST while waiting for our transaction to send. |  | 
| 4924     VARIANT_RST_DURING_SEND_COMPLETION, |  | 
| 4925     // Induce the RST while waiting for our transaction to read. |  | 
| 4926     // In this case, the send completed - everything copied into the SNDBUF. |  | 
| 4927     VARIANT_RST_DURING_READ_COMPLETION |  | 
| 4928   }; |  | 
| 4929 |  | 
| 4930   for (int variant = VARIANT_RST_DURING_SEND_COMPLETION; |  | 
| 4931        variant <= VARIANT_RST_DURING_READ_COMPLETION; |  | 
| 4932        ++variant) { |  | 
| 4933     scoped_ptr<DelayedSocketData> data1( |  | 
| 4934         new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 4935                               NULL, 0)); |  | 
| 4936 |  | 
| 4937     scoped_ptr<DelayedSocketData> data2( |  | 
| 4938         new DelayedSocketData(1, reads2, arraysize(reads2), |  | 
| 4939                                NULL, 0)); |  | 
| 4940 |  | 
| 4941     NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 4942                                        BoundNetLog(), GetParam()); |  | 
| 4943     helper.AddData(data1.get()); |  | 
| 4944     helper.AddData(data2.get()); |  | 
| 4945     helper.RunPreTestSetup(); |  | 
| 4946 |  | 
| 4947     for (int i = 0; i < 2; ++i) { |  | 
| 4948       scoped_ptr<HttpNetworkTransaction> trans( |  | 
| 4949           new HttpNetworkTransaction(helper.session())); |  | 
| 4950 |  | 
| 4951       TestCompletionCallback callback; |  | 
| 4952       int rv = trans->Start( |  | 
| 4953           &helper.request(), callback.callback(), BoundNetLog()); |  | 
| 4954       EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 4955       // On the second transaction, we trigger the RST. |  | 
| 4956       if (i == 1) { |  | 
| 4957         if (variant == VARIANT_RST_DURING_READ_COMPLETION) { |  | 
| 4958           // Writes to the socket complete asynchronously on SPDY by running |  | 
| 4959           // through the message loop.  Complete the write here. |  | 
| 4960           MessageLoop::current()->RunAllPending(); |  | 
| 4961         } |  | 
| 4962 |  | 
| 4963         // Now schedule the ERR_CONNECTION_RESET. |  | 
| 4964         EXPECT_EQ(3u, data1->read_index()); |  | 
| 4965         data1->CompleteRead(); |  | 
| 4966         EXPECT_EQ(4u, data1->read_index()); |  | 
| 4967       } |  | 
| 4968       rv = callback.WaitForResult(); |  | 
| 4969       EXPECT_EQ(OK, rv); |  | 
| 4970 |  | 
| 4971       const HttpResponseInfo* response = trans->GetResponseInfo(); |  | 
| 4972       ASSERT_TRUE(response != NULL); |  | 
| 4973       EXPECT_TRUE(response->headers != NULL); |  | 
| 4974       EXPECT_TRUE(response->was_fetched_via_spdy); |  | 
| 4975       std::string response_data; |  | 
| 4976       rv = ReadTransaction(trans.get(), &response_data); |  | 
| 4977       EXPECT_EQ(OK, rv); |  | 
| 4978       EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); |  | 
| 4979       EXPECT_EQ("hello!", response_data); |  | 
| 4980     } |  | 
| 4981 |  | 
| 4982     helper.VerifyDataConsumed(); |  | 
| 4983   } |  | 
| 4984 } |  | 
| 4985 |  | 
| 4986 // Test that turning SPDY on and off works properly. |  | 
| 4987 TEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) { |  | 
| 4988   net::HttpStreamFactory::set_spdy_enabled(true); |  | 
| 4989   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 4990   MockWrite spdy_writes[] = { CreateMockWrite(*req) }; |  | 
| 4991 |  | 
| 4992   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 4993   scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); |  | 
| 4994   MockRead spdy_reads[] = { |  | 
| 4995     CreateMockRead(*resp), |  | 
| 4996     CreateMockRead(*body), |  | 
| 4997     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 4998   }; |  | 
| 4999 |  | 
| 5000   scoped_ptr<DelayedSocketData> data( |  | 
| 5001       new DelayedSocketData(1, |  | 
| 5002                             spdy_reads, arraysize(spdy_reads), |  | 
| 5003                             spdy_writes, arraysize(spdy_writes))); |  | 
| 5004   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 5005                                      BoundNetLog(), GetParam()); |  | 
| 5006   helper.RunToCompletion(data.get()); |  | 
| 5007   TransactionHelperResult out = helper.output(); |  | 
| 5008   EXPECT_EQ(OK, out.rv); |  | 
| 5009   EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |  | 
| 5010   EXPECT_EQ("hello!", out.response_data); |  | 
| 5011 |  | 
| 5012   net::HttpStreamFactory::set_spdy_enabled(false); |  | 
| 5013   MockRead http_reads[] = { |  | 
| 5014     MockRead("HTTP/1.1 200 OK\r\n\r\n"), |  | 
| 5015     MockRead("hello from http"), |  | 
| 5016     MockRead(SYNCHRONOUS, OK), |  | 
| 5017   }; |  | 
| 5018   scoped_ptr<DelayedSocketData> data2( |  | 
| 5019       new DelayedSocketData(1, http_reads, arraysize(http_reads), |  | 
| 5020                             NULL, 0)); |  | 
| 5021   NormalSpdyTransactionHelper helper2(CreateGetRequest(), |  | 
| 5022                                      BoundNetLog(), GetParam()); |  | 
| 5023   helper2.SetSpdyDisabled(); |  | 
| 5024   helper2.RunToCompletion(data2.get()); |  | 
| 5025   TransactionHelperResult out2 = helper2.output(); |  | 
| 5026   EXPECT_EQ(OK, out2.rv); |  | 
| 5027   EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line); |  | 
| 5028   EXPECT_EQ("hello from http", out2.response_data); |  | 
| 5029 |  | 
| 5030   net::HttpStreamFactory::set_spdy_enabled(true); |  | 
| 5031 } |  | 
| 5032 |  | 
| 5033 // Tests that Basic authentication works over SPDY |  | 
| 5034 TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) { |  | 
| 5035   net::HttpStreamFactory::set_spdy_enabled(true); |  | 
| 5036 |  | 
| 5037   // The first request will be a bare GET, the second request will be a |  | 
| 5038   // GET with an Authorization header. |  | 
| 5039   scoped_ptr<spdy::SpdyFrame> req_get( |  | 
| 5040       ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 5041   const char* const kExtraAuthorizationHeaders[] = { |  | 
| 5042     "authorization", |  | 
| 5043     "Basic Zm9vOmJhcg==", |  | 
| 5044   }; |  | 
| 5045   scoped_ptr<spdy::SpdyFrame> req_get_authorization( |  | 
| 5046       ConstructSpdyGet( |  | 
| 5047           kExtraAuthorizationHeaders, |  | 
| 5048           arraysize(kExtraAuthorizationHeaders) / 2, |  | 
| 5049           false, 3, LOWEST)); |  | 
| 5050   MockWrite spdy_writes[] = { |  | 
| 5051     CreateMockWrite(*req_get, 1), |  | 
| 5052     CreateMockWrite(*req_get_authorization, 4), |  | 
| 5053   }; |  | 
| 5054 |  | 
| 5055   // The first response is a 401 authentication challenge, and the second |  | 
| 5056   // response will be a 200 response since the second request includes a valid |  | 
| 5057   // Authorization header. |  | 
| 5058   const char* const kExtraAuthenticationHeaders[] = { |  | 
| 5059     "www-authenticate", |  | 
| 5060     "Basic realm=\"MyRealm\"" |  | 
| 5061   }; |  | 
| 5062   scoped_ptr<spdy::SpdyFrame> resp_authentication( |  | 
| 5063       ConstructSpdySynReplyError( |  | 
| 5064           "401 Authentication Required", |  | 
| 5065           kExtraAuthenticationHeaders, |  | 
| 5066           arraysize(kExtraAuthenticationHeaders) / 2, |  | 
| 5067           1)); |  | 
| 5068   scoped_ptr<spdy::SpdyFrame> body_authentication( |  | 
| 5069       ConstructSpdyBodyFrame(1, true)); |  | 
| 5070   scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3)); |  | 
| 5071   scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true)); |  | 
| 5072   MockRead spdy_reads[] = { |  | 
| 5073     CreateMockRead(*resp_authentication, 2), |  | 
| 5074     CreateMockRead(*body_authentication, 3), |  | 
| 5075     CreateMockRead(*resp_data, 5), |  | 
| 5076     CreateMockRead(*body_data, 6), |  | 
| 5077     MockRead(ASYNC, 0, 7), |  | 
| 5078   }; |  | 
| 5079 |  | 
| 5080   scoped_ptr<OrderedSocketData> data( |  | 
| 5081       new OrderedSocketData(spdy_reads, arraysize(spdy_reads), |  | 
| 5082                             spdy_writes, arraysize(spdy_writes))); |  | 
| 5083   HttpRequestInfo request(CreateGetRequest()); |  | 
| 5084   BoundNetLog net_log; |  | 
| 5085   NormalSpdyTransactionHelper helper(request, net_log, GetParam()); |  | 
| 5086 |  | 
| 5087   helper.RunPreTestSetup(); |  | 
| 5088   helper.AddData(data.get()); |  | 
| 5089   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 5090   TestCompletionCallback callback; |  | 
| 5091   const int rv_start = trans->Start(&request, callback.callback(), net_log); |  | 
| 5092   EXPECT_EQ(ERR_IO_PENDING, rv_start); |  | 
| 5093   const int rv_start_complete = callback.WaitForResult(); |  | 
| 5094   EXPECT_EQ(OK, rv_start_complete); |  | 
| 5095 |  | 
| 5096   // Make sure the response has an auth challenge. |  | 
| 5097   const HttpResponseInfo* const response_start = trans->GetResponseInfo(); |  | 
| 5098   ASSERT_TRUE(response_start != NULL); |  | 
| 5099   ASSERT_TRUE(response_start->headers != NULL); |  | 
| 5100   EXPECT_EQ(401, response_start->headers->response_code()); |  | 
| 5101   EXPECT_TRUE(response_start->was_fetched_via_spdy); |  | 
| 5102   AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get(); |  | 
| 5103   ASSERT_TRUE(auth_challenge != NULL); |  | 
| 5104   EXPECT_FALSE(auth_challenge->is_proxy); |  | 
| 5105   EXPECT_EQ("basic", auth_challenge->scheme); |  | 
| 5106   EXPECT_EQ("MyRealm", auth_challenge->realm); |  | 
| 5107 |  | 
| 5108   // Restart with a username/password. |  | 
| 5109   AuthCredentials credentials(ASCIIToUTF16("foo"), ASCIIToUTF16("bar")); |  | 
| 5110   TestCompletionCallback callback_restart; |  | 
| 5111   const int rv_restart = trans->RestartWithAuth( |  | 
| 5112       credentials, callback_restart.callback()); |  | 
| 5113   EXPECT_EQ(ERR_IO_PENDING, rv_restart); |  | 
| 5114   const int rv_restart_complete = callback_restart.WaitForResult(); |  | 
| 5115   EXPECT_EQ(OK, rv_restart_complete); |  | 
| 5116   // TODO(cbentzel): This is actually the same response object as before, but |  | 
| 5117   // data has changed. |  | 
| 5118   const HttpResponseInfo* const response_restart = trans->GetResponseInfo(); |  | 
| 5119   ASSERT_TRUE(response_restart != NULL); |  | 
| 5120   ASSERT_TRUE(response_restart->headers != NULL); |  | 
| 5121   EXPECT_EQ(200, response_restart->headers->response_code()); |  | 
| 5122   EXPECT_TRUE(response_restart->auth_challenge.get() == NULL); |  | 
| 5123 } |  | 
| 5124 |  | 
| 5125 TEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) { |  | 
| 5126   static const unsigned char kPushBodyFrame[] = { |  | 
| 5127     0x00, 0x00, 0x00, 0x02,                                      // header, ID |  | 
| 5128     0x01, 0x00, 0x00, 0x06,                                      // FIN, length |  | 
| 5129     'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed" |  | 
| 5130   }; |  | 
| 5131   scoped_ptr<spdy::SpdyFrame> |  | 
| 5132       stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 5133   scoped_ptr<spdy::SpdyFrame> |  | 
| 5134       stream1_body(ConstructSpdyBodyFrame(1, true)); |  | 
| 5135   MockWrite writes[] = { |  | 
| 5136     CreateMockWrite(*stream1_syn, 1), |  | 
| 5137   }; |  | 
| 5138 |  | 
| 5139   static const char* const kInitialHeaders[] = { |  | 
| 5140     "url", |  | 
| 5141     "http://www.google.com/foo.dat", |  | 
| 5142   }; |  | 
| 5143   static const char* const kLateHeaders[] = { |  | 
| 5144     "hello", |  | 
| 5145     "bye", |  | 
| 5146     "status", |  | 
| 5147     "200", |  | 
| 5148     "version", |  | 
| 5149     "HTTP/1.1" |  | 
| 5150   }; |  | 
| 5151   scoped_ptr<spdy::SpdyFrame> |  | 
| 5152     stream2_syn(ConstructSpdyControlFrame(kInitialHeaders, |  | 
| 5153                                           arraysize(kInitialHeaders) / 2, |  | 
| 5154                                           false, |  | 
| 5155                                           2, |  | 
| 5156                                           LOWEST, |  | 
| 5157                                           spdy::SYN_STREAM, |  | 
| 5158                                           spdy::CONTROL_FLAG_NONE, |  | 
| 5159                                           NULL, |  | 
| 5160                                           0, |  | 
| 5161                                           1)); |  | 
| 5162   scoped_ptr<spdy::SpdyFrame> |  | 
| 5163       stream2_headers(ConstructSpdyControlFrame(kLateHeaders, |  | 
| 5164                                                 arraysize(kLateHeaders) / 2, |  | 
| 5165                                                 false, |  | 
| 5166                                                 2, |  | 
| 5167                                                 LOWEST, |  | 
| 5168                                                 spdy::HEADERS, |  | 
| 5169                                                 spdy::CONTROL_FLAG_NONE, |  | 
| 5170                                                 NULL, |  | 
| 5171                                                 0, |  | 
| 5172                                                 0)); |  | 
| 5173 |  | 
| 5174   scoped_ptr<spdy::SpdyFrame> |  | 
| 5175       stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 5176   MockRead reads[] = { |  | 
| 5177     CreateMockRead(*stream1_reply, 2), |  | 
| 5178     CreateMockRead(*stream2_syn, 3), |  | 
| 5179     CreateMockRead(*stream2_headers, 4), |  | 
| 5180     CreateMockRead(*stream1_body, 5, SYNCHRONOUS), |  | 
| 5181     MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), |  | 
| 5182              arraysize(kPushBodyFrame), 6), |  | 
| 5183     MockRead(ASYNC, ERR_IO_PENDING, 7),  // Force a pause |  | 
| 5184   }; |  | 
| 5185 |  | 
| 5186   HttpResponseInfo response; |  | 
| 5187   HttpResponseInfo response2; |  | 
| 5188   std::string expected_push_result("pushed"); |  | 
| 5189   scoped_ptr<OrderedSocketData> data(new OrderedSocketData( |  | 
| 5190       reads, |  | 
| 5191       arraysize(reads), |  | 
| 5192       writes, |  | 
| 5193       arraysize(writes))); |  | 
| 5194   RunServerPushTest(data.get(), |  | 
| 5195                     &response, |  | 
| 5196                     &response2, |  | 
| 5197                     expected_push_result); |  | 
| 5198 |  | 
| 5199   // Verify the SYN_REPLY. |  | 
| 5200   EXPECT_TRUE(response.headers != NULL); |  | 
| 5201   EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |  | 
| 5202 |  | 
| 5203   // Verify the pushed stream. |  | 
| 5204   EXPECT_TRUE(response2.headers != NULL); |  | 
| 5205   EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); |  | 
| 5206 } |  | 
| 5207 |  | 
| 5208 TEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) { |  | 
| 5209   // We push a stream and attempt to claim it before the headers come down. |  | 
| 5210   static const unsigned char kPushBodyFrame[] = { |  | 
| 5211     0x00, 0x00, 0x00, 0x02,                                      // header, ID |  | 
| 5212     0x01, 0x00, 0x00, 0x06,                                      // FIN, length |  | 
| 5213     'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed" |  | 
| 5214   }; |  | 
| 5215   scoped_ptr<spdy::SpdyFrame> |  | 
| 5216       stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 5217   scoped_ptr<spdy::SpdyFrame> |  | 
| 5218       stream1_body(ConstructSpdyBodyFrame(1, true)); |  | 
| 5219   MockWrite writes[] = { |  | 
| 5220     CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS), |  | 
| 5221   }; |  | 
| 5222 |  | 
| 5223   static const char* const kInitialHeaders[] = { |  | 
| 5224     "url", |  | 
| 5225     "http://www.google.com/foo.dat", |  | 
| 5226   }; |  | 
| 5227   static const char* const kLateHeaders[] = { |  | 
| 5228     "hello", |  | 
| 5229     "bye", |  | 
| 5230     "status", |  | 
| 5231     "200", |  | 
| 5232     "version", |  | 
| 5233     "HTTP/1.1" |  | 
| 5234   }; |  | 
| 5235   scoped_ptr<spdy::SpdyFrame> |  | 
| 5236       stream2_syn(ConstructSpdyControlFrame(kInitialHeaders, |  | 
| 5237                                             arraysize(kInitialHeaders) / 2, |  | 
| 5238                                             false, |  | 
| 5239                                             2, |  | 
| 5240                                             LOWEST, |  | 
| 5241                                             spdy::SYN_STREAM, |  | 
| 5242                                             spdy::CONTROL_FLAG_NONE, |  | 
| 5243                                             NULL, |  | 
| 5244                                             0, |  | 
| 5245                                             1)); |  | 
| 5246   scoped_ptr<spdy::SpdyFrame> |  | 
| 5247       stream2_headers(ConstructSpdyControlFrame(kLateHeaders, |  | 
| 5248                                                 arraysize(kLateHeaders) / 2, |  | 
| 5249                                                 false, |  | 
| 5250                                                 2, |  | 
| 5251                                                 LOWEST, |  | 
| 5252                                                 spdy::HEADERS, |  | 
| 5253                                                 spdy::CONTROL_FLAG_NONE, |  | 
| 5254                                                 NULL, |  | 
| 5255                                                 0, |  | 
| 5256                                                 0)); |  | 
| 5257 |  | 
| 5258   scoped_ptr<spdy::SpdyFrame> |  | 
| 5259       stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 5260   MockRead reads[] = { |  | 
| 5261     CreateMockRead(*stream1_reply, 1), |  | 
| 5262     CreateMockRead(*stream2_syn, 2), |  | 
| 5263     CreateMockRead(*stream1_body, 3), |  | 
| 5264     CreateMockRead(*stream2_headers, 4), |  | 
| 5265     MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), |  | 
| 5266              arraysize(kPushBodyFrame), 5), |  | 
| 5267     MockRead(ASYNC, 0, 5),  // EOF |  | 
| 5268   }; |  | 
| 5269 |  | 
| 5270   HttpResponseInfo response; |  | 
| 5271   HttpResponseInfo response2; |  | 
| 5272   std::string expected_push_result("pushed"); |  | 
| 5273   scoped_refptr<DeterministicSocketData> data(new DeterministicSocketData( |  | 
| 5274       reads, |  | 
| 5275       arraysize(reads), |  | 
| 5276       writes, |  | 
| 5277       arraysize(writes))); |  | 
| 5278 |  | 
| 5279   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 5280                                      BoundNetLog(), GetParam()); |  | 
| 5281   helper.SetDeterministic(); |  | 
| 5282   helper.AddDeterministicData(static_cast<DeterministicSocketData*>(data)); |  | 
| 5283   helper.RunPreTestSetup(); |  | 
| 5284 |  | 
| 5285   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 5286 |  | 
| 5287   // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM, |  | 
| 5288   // and the body of the primary stream, but before we've received the HEADERS |  | 
| 5289   // for the pushed stream. |  | 
| 5290   data->SetStop(3); |  | 
| 5291 |  | 
| 5292   // Start the transaction. |  | 
| 5293   TestCompletionCallback callback; |  | 
| 5294   int rv = trans->Start( |  | 
| 5295       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 5296   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 5297   data->Run(); |  | 
| 5298   rv = callback.WaitForResult(); |  | 
| 5299   EXPECT_EQ(0, rv); |  | 
| 5300 |  | 
| 5301   // Request the pushed path.  At this point, we've received the push, but the |  | 
| 5302   // headers are not yet complete. |  | 
| 5303   scoped_ptr<HttpNetworkTransaction> trans2( |  | 
| 5304       new HttpNetworkTransaction(helper.session())); |  | 
| 5305   rv = trans2->Start( |  | 
| 5306       &CreateGetPushRequest(), callback.callback(), BoundNetLog()); |  | 
| 5307   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 5308   data->RunFor(3); |  | 
| 5309   MessageLoop::current()->RunAllPending(); |  | 
| 5310 |  | 
| 5311   // Read the server push body. |  | 
| 5312   std::string result2; |  | 
| 5313   ReadResult(trans2.get(), data.get(), &result2); |  | 
| 5314   // Read the response body. |  | 
| 5315   std::string result; |  | 
| 5316   ReadResult(trans, data, &result); |  | 
| 5317 |  | 
| 5318   // Verify that we consumed all test data. |  | 
| 5319   EXPECT_TRUE(data->at_read_eof()); |  | 
| 5320   EXPECT_TRUE(data->at_write_eof()); |  | 
| 5321 |  | 
| 5322   // Verify that the received push data is same as the expected push data. |  | 
| 5323   EXPECT_EQ(result2.compare(expected_push_result), 0) |  | 
| 5324       << "Received data: " |  | 
| 5325       << result2 |  | 
| 5326       << "||||| Expected data: " |  | 
| 5327       << expected_push_result; |  | 
| 5328 |  | 
| 5329   // Verify the SYN_REPLY. |  | 
| 5330   // Copy the response info, because trans goes away. |  | 
| 5331   response = *trans->GetResponseInfo(); |  | 
| 5332   response2 = *trans2->GetResponseInfo(); |  | 
| 5333 |  | 
| 5334   VerifyStreamsClosed(helper); |  | 
| 5335 |  | 
| 5336   // Verify the SYN_REPLY. |  | 
| 5337   EXPECT_TRUE(response.headers != NULL); |  | 
| 5338   EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |  | 
| 5339 |  | 
| 5340   // Verify the pushed stream. |  | 
| 5341   EXPECT_TRUE(response2.headers != NULL); |  | 
| 5342   EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); |  | 
| 5343 } |  | 
| 5344 |  | 
| 5345 TEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) { |  | 
| 5346   // We push a stream and attempt to claim it before the headers come down. |  | 
| 5347   static const unsigned char kPushBodyFrame[] = { |  | 
| 5348     0x00, 0x00, 0x00, 0x02,                                      // header, ID |  | 
| 5349     0x01, 0x00, 0x00, 0x06,                                      // FIN, length |  | 
| 5350     'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed" |  | 
| 5351   }; |  | 
| 5352   scoped_ptr<spdy::SpdyFrame> |  | 
| 5353       stream1_syn(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 5354   scoped_ptr<spdy::SpdyFrame> |  | 
| 5355       stream1_body(ConstructSpdyBodyFrame(1, true)); |  | 
| 5356   MockWrite writes[] = { |  | 
| 5357     CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS), |  | 
| 5358   }; |  | 
| 5359 |  | 
| 5360   static const char* const kInitialHeaders[] = { |  | 
| 5361     "url", |  | 
| 5362     "http://www.google.com/foo.dat", |  | 
| 5363   }; |  | 
| 5364   static const char* const kMiddleHeaders[] = { |  | 
| 5365     "hello", |  | 
| 5366     "bye", |  | 
| 5367   }; |  | 
| 5368   static const char* const kLateHeaders[] = { |  | 
| 5369     "status", |  | 
| 5370     "200", |  | 
| 5371     "version", |  | 
| 5372     "HTTP/1.1" |  | 
| 5373   }; |  | 
| 5374   scoped_ptr<spdy::SpdyFrame> |  | 
| 5375       stream2_syn(ConstructSpdyControlFrame(kInitialHeaders, |  | 
| 5376                                             arraysize(kInitialHeaders) / 2, |  | 
| 5377                                             false, |  | 
| 5378                                             2, |  | 
| 5379                                             LOWEST, |  | 
| 5380                                             spdy::SYN_STREAM, |  | 
| 5381                                             spdy::CONTROL_FLAG_NONE, |  | 
| 5382                                             NULL, |  | 
| 5383                                             0, |  | 
| 5384                                             1)); |  | 
| 5385   scoped_ptr<spdy::SpdyFrame> |  | 
| 5386       stream2_headers1(ConstructSpdyControlFrame(kMiddleHeaders, |  | 
| 5387                                                  arraysize(kMiddleHeaders) / 2, |  | 
| 5388                                                  false, |  | 
| 5389                                                  2, |  | 
| 5390                                                  LOWEST, |  | 
| 5391                                                  spdy::HEADERS, |  | 
| 5392                                                  spdy::CONTROL_FLAG_NONE, |  | 
| 5393                                                  NULL, |  | 
| 5394                                                  0, |  | 
| 5395                                                  0)); |  | 
| 5396   scoped_ptr<spdy::SpdyFrame> |  | 
| 5397       stream2_headers2(ConstructSpdyControlFrame(kLateHeaders, |  | 
| 5398                                                  arraysize(kLateHeaders) / 2, |  | 
| 5399                                                  false, |  | 
| 5400                                                  2, |  | 
| 5401                                                  LOWEST, |  | 
| 5402                                                  spdy::HEADERS, |  | 
| 5403                                                  spdy::CONTROL_FLAG_NONE, |  | 
| 5404                                                  NULL, |  | 
| 5405                                                  0, |  | 
| 5406                                                  0)); |  | 
| 5407 |  | 
| 5408   scoped_ptr<spdy::SpdyFrame> |  | 
| 5409       stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 5410   MockRead reads[] = { |  | 
| 5411     CreateMockRead(*stream1_reply, 1), |  | 
| 5412     CreateMockRead(*stream2_syn, 2), |  | 
| 5413     CreateMockRead(*stream1_body, 3), |  | 
| 5414     CreateMockRead(*stream2_headers1, 4), |  | 
| 5415     CreateMockRead(*stream2_headers2, 5), |  | 
| 5416     MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), |  | 
| 5417              arraysize(kPushBodyFrame), 6), |  | 
| 5418     MockRead(ASYNC, 0, 6),  // EOF |  | 
| 5419   }; |  | 
| 5420 |  | 
| 5421   HttpResponseInfo response; |  | 
| 5422   HttpResponseInfo response2; |  | 
| 5423   std::string expected_push_result("pushed"); |  | 
| 5424   scoped_refptr<DeterministicSocketData> data(new DeterministicSocketData( |  | 
| 5425       reads, |  | 
| 5426       arraysize(reads), |  | 
| 5427       writes, |  | 
| 5428       arraysize(writes))); |  | 
| 5429 |  | 
| 5430   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 5431                                      BoundNetLog(), GetParam()); |  | 
| 5432   helper.SetDeterministic(); |  | 
| 5433   helper.AddDeterministicData(static_cast<DeterministicSocketData*>(data)); |  | 
| 5434   helper.RunPreTestSetup(); |  | 
| 5435 |  | 
| 5436   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 5437 |  | 
| 5438   // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM, |  | 
| 5439   // the first HEADERS frame, and the body of the primary stream, but before |  | 
| 5440   // we've received the final HEADERS for the pushed stream. |  | 
| 5441   data->SetStop(4); |  | 
| 5442 |  | 
| 5443   // Start the transaction. |  | 
| 5444   TestCompletionCallback callback; |  | 
| 5445   int rv = trans->Start( |  | 
| 5446       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 5447   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 5448   data->Run(); |  | 
| 5449   rv = callback.WaitForResult(); |  | 
| 5450   EXPECT_EQ(0, rv); |  | 
| 5451 |  | 
| 5452   // Request the pushed path.  At this point, we've received the push, but the |  | 
| 5453   // headers are not yet complete. |  | 
| 5454   scoped_ptr<HttpNetworkTransaction> trans2( |  | 
| 5455       new HttpNetworkTransaction(helper.session())); |  | 
| 5456   rv = trans2->Start( |  | 
| 5457       &CreateGetPushRequest(), callback.callback(), BoundNetLog()); |  | 
| 5458   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 5459   data->RunFor(3); |  | 
| 5460   MessageLoop::current()->RunAllPending(); |  | 
| 5461 |  | 
| 5462   // Read the server push body. |  | 
| 5463   std::string result2; |  | 
| 5464   ReadResult(trans2.get(), data, &result2); |  | 
| 5465   // Read the response body. |  | 
| 5466   std::string result; |  | 
| 5467   ReadResult(trans, data, &result); |  | 
| 5468 |  | 
| 5469   // Verify that we consumed all test data. |  | 
| 5470   EXPECT_TRUE(data->at_read_eof()); |  | 
| 5471   EXPECT_TRUE(data->at_write_eof()); |  | 
| 5472 |  | 
| 5473   // Verify that the received push data is same as the expected push data. |  | 
| 5474   EXPECT_EQ(result2.compare(expected_push_result), 0) |  | 
| 5475       << "Received data: " |  | 
| 5476       << result2 |  | 
| 5477       << "||||| Expected data: " |  | 
| 5478       << expected_push_result; |  | 
| 5479 |  | 
| 5480   // Verify the SYN_REPLY. |  | 
| 5481   // Copy the response info, because trans goes away. |  | 
| 5482   response = *trans->GetResponseInfo(); |  | 
| 5483   response2 = *trans2->GetResponseInfo(); |  | 
| 5484 |  | 
| 5485   VerifyStreamsClosed(helper); |  | 
| 5486 |  | 
| 5487   // Verify the SYN_REPLY. |  | 
| 5488   EXPECT_TRUE(response.headers != NULL); |  | 
| 5489   EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |  | 
| 5490 |  | 
| 5491   // Verify the pushed stream. |  | 
| 5492   EXPECT_TRUE(response2.headers != NULL); |  | 
| 5493   EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine()); |  | 
| 5494 |  | 
| 5495   // Verify we got all the headers |  | 
| 5496   EXPECT_TRUE(response2.headers->HasHeaderValue( |  | 
| 5497       "url", |  | 
| 5498       "http://www.google.com/foo.dat")); |  | 
| 5499   EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye")); |  | 
| 5500   EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200")); |  | 
| 5501   EXPECT_TRUE(response2.headers->HasHeaderValue("version", "HTTP/1.1")); |  | 
| 5502 } |  | 
| 5503 |  | 
| 5504 TEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) { |  | 
| 5505   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 5506   MockWrite writes[] = { CreateMockWrite(*req) }; |  | 
| 5507 |  | 
| 5508   static const char* const kInitialHeaders[] = { |  | 
| 5509     "status", |  | 
| 5510     "200 OK", |  | 
| 5511     "version", |  | 
| 5512     "HTTP/1.1" |  | 
| 5513   }; |  | 
| 5514   static const char* const kLateHeaders[] = { |  | 
| 5515     "hello", |  | 
| 5516     "bye", |  | 
| 5517   }; |  | 
| 5518   scoped_ptr<spdy::SpdyFrame> |  | 
| 5519       stream1_reply(ConstructSpdyControlFrame(kInitialHeaders, |  | 
| 5520                                               arraysize(kInitialHeaders) / 2, |  | 
| 5521                                               false, |  | 
| 5522                                               1, |  | 
| 5523                                               LOWEST, |  | 
| 5524                                               spdy::SYN_REPLY, |  | 
| 5525                                               spdy::CONTROL_FLAG_NONE, |  | 
| 5526                                               NULL, |  | 
| 5527                                               0, |  | 
| 5528                                               0)); |  | 
| 5529   scoped_ptr<spdy::SpdyFrame> |  | 
| 5530       stream1_headers(ConstructSpdyControlFrame(kLateHeaders, |  | 
| 5531                                                 arraysize(kLateHeaders) / 2, |  | 
| 5532                                                 false, |  | 
| 5533                                                 1, |  | 
| 5534                                                 LOWEST, |  | 
| 5535                                                 spdy::HEADERS, |  | 
| 5536                                                 spdy::CONTROL_FLAG_NONE, |  | 
| 5537                                                 NULL, |  | 
| 5538                                                 0, |  | 
| 5539                                                 0)); |  | 
| 5540   scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, true)); |  | 
| 5541   MockRead reads[] = { |  | 
| 5542     CreateMockRead(*stream1_reply), |  | 
| 5543     CreateMockRead(*stream1_headers), |  | 
| 5544     CreateMockRead(*stream1_body), |  | 
| 5545     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 5546   }; |  | 
| 5547 |  | 
| 5548   scoped_ptr<DelayedSocketData> data( |  | 
| 5549       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 5550                             writes, arraysize(writes))); |  | 
| 5551   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 5552                                      BoundNetLog(), GetParam()); |  | 
| 5553   helper.RunToCompletion(data.get()); |  | 
| 5554   TransactionHelperResult out = helper.output(); |  | 
| 5555   EXPECT_EQ(OK, out.rv); |  | 
| 5556   EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |  | 
| 5557   EXPECT_EQ("hello!", out.response_data); |  | 
| 5558 } |  | 
| 5559 |  | 
| 5560 TEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) { |  | 
| 5561   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 5562   MockWrite writes[] = { CreateMockWrite(*req) }; |  | 
| 5563 |  | 
| 5564   static const char* const kInitialHeaders[] = { |  | 
| 5565     "status", |  | 
| 5566     "200 OK", |  | 
| 5567     "version", |  | 
| 5568     "HTTP/1.1" |  | 
| 5569   }; |  | 
| 5570   static const char* const kLateHeaders[] = { |  | 
| 5571     "hello", |  | 
| 5572     "bye", |  | 
| 5573   }; |  | 
| 5574   scoped_ptr<spdy::SpdyFrame> |  | 
| 5575       stream1_reply(ConstructSpdyControlFrame(kInitialHeaders, |  | 
| 5576                                               arraysize(kInitialHeaders) / 2, |  | 
| 5577                                               false, |  | 
| 5578                                               1, |  | 
| 5579                                               LOWEST, |  | 
| 5580                                               spdy::SYN_REPLY, |  | 
| 5581                                               spdy::CONTROL_FLAG_NONE, |  | 
| 5582                                               NULL, |  | 
| 5583                                               0, |  | 
| 5584                                               0)); |  | 
| 5585   scoped_ptr<spdy::SpdyFrame> |  | 
| 5586       stream1_headers(ConstructSpdyControlFrame(kLateHeaders, |  | 
| 5587                                                 arraysize(kLateHeaders) / 2, |  | 
| 5588                                                 false, |  | 
| 5589                                                 1, |  | 
| 5590                                                 LOWEST, |  | 
| 5591                                                 spdy::HEADERS, |  | 
| 5592                                                 spdy::CONTROL_FLAG_NONE, |  | 
| 5593                                                 NULL, |  | 
| 5594                                                 0, |  | 
| 5595                                                 0)); |  | 
| 5596   scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, false)); |  | 
| 5597   scoped_ptr<spdy::SpdyFrame> stream1_body2(ConstructSpdyBodyFrame(1, true)); |  | 
| 5598   MockRead reads[] = { |  | 
| 5599     CreateMockRead(*stream1_reply), |  | 
| 5600     CreateMockRead(*stream1_body), |  | 
| 5601     CreateMockRead(*stream1_headers), |  | 
| 5602     CreateMockRead(*stream1_body2), |  | 
| 5603     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 5604   }; |  | 
| 5605 |  | 
| 5606   scoped_ptr<DelayedSocketData> data( |  | 
| 5607       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 5608                             writes, arraysize(writes))); |  | 
| 5609   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 5610                                      BoundNetLog(), GetParam()); |  | 
| 5611   helper.RunToCompletion(data.get()); |  | 
| 5612   TransactionHelperResult out = helper.output(); |  | 
| 5613   EXPECT_EQ(OK, out.rv); |  | 
| 5614   EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |  | 
| 5615   EXPECT_EQ("hello!hello!", out.response_data); |  | 
| 5616 } |  | 
| 5617 |  | 
| 5618 TEST_P(SpdyNetworkTransactionTest, SynReplyWithDuplicateLateHeaders) { |  | 
| 5619   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 5620   MockWrite writes[] = { CreateMockWrite(*req) }; |  | 
| 5621 |  | 
| 5622   static const char* const kInitialHeaders[] = { |  | 
| 5623     "status", |  | 
| 5624     "200 OK", |  | 
| 5625     "version", |  | 
| 5626     "HTTP/1.1" |  | 
| 5627   }; |  | 
| 5628   static const char* const kLateHeaders[] = { |  | 
| 5629     "status", |  | 
| 5630     "500 Server Error", |  | 
| 5631   }; |  | 
| 5632   scoped_ptr<spdy::SpdyFrame> |  | 
| 5633       stream1_reply(ConstructSpdyControlFrame(kInitialHeaders, |  | 
| 5634                                               arraysize(kInitialHeaders) / 2, |  | 
| 5635                                               false, |  | 
| 5636                                               1, |  | 
| 5637                                               LOWEST, |  | 
| 5638                                               spdy::SYN_REPLY, |  | 
| 5639                                               spdy::CONTROL_FLAG_NONE, |  | 
| 5640                                               NULL, |  | 
| 5641                                               0, |  | 
| 5642                                               0)); |  | 
| 5643   scoped_ptr<spdy::SpdyFrame> |  | 
| 5644       stream1_headers(ConstructSpdyControlFrame(kLateHeaders, |  | 
| 5645                                                 arraysize(kLateHeaders) / 2, |  | 
| 5646                                                 false, |  | 
| 5647                                                 1, |  | 
| 5648                                                 LOWEST, |  | 
| 5649                                                 spdy::HEADERS, |  | 
| 5650                                                 spdy::CONTROL_FLAG_NONE, |  | 
| 5651                                                 NULL, |  | 
| 5652                                                 0, |  | 
| 5653                                                 0)); |  | 
| 5654   scoped_ptr<spdy::SpdyFrame> stream1_body(ConstructSpdyBodyFrame(1, false)); |  | 
| 5655   scoped_ptr<spdy::SpdyFrame> stream1_body2(ConstructSpdyBodyFrame(1, true)); |  | 
| 5656   MockRead reads[] = { |  | 
| 5657     CreateMockRead(*stream1_reply), |  | 
| 5658     CreateMockRead(*stream1_body), |  | 
| 5659     CreateMockRead(*stream1_headers), |  | 
| 5660     CreateMockRead(*stream1_body2), |  | 
| 5661     MockRead(ASYNC, 0, 0)  // EOF |  | 
| 5662   }; |  | 
| 5663 |  | 
| 5664   scoped_ptr<DelayedSocketData> data( |  | 
| 5665       new DelayedSocketData(1, reads, arraysize(reads), |  | 
| 5666                             writes, arraysize(writes))); |  | 
| 5667   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 5668                                      BoundNetLog(), GetParam()); |  | 
| 5669   helper.RunToCompletion(data.get()); |  | 
| 5670   TransactionHelperResult out = helper.output(); |  | 
| 5671   EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv); |  | 
| 5672 } |  | 
| 5673 |  | 
| 5674 TEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) { |  | 
| 5675   // In this test we want to verify that we can't accidentally push content |  | 
| 5676   // which can't be pushed by this content server. |  | 
| 5677   // This test assumes that: |  | 
| 5678   //   - if we're requesting http://www.foo.com/barbaz |  | 
| 5679   //   - the browser has made a connection to "www.foo.com". |  | 
| 5680 |  | 
| 5681   // A list of the URL to fetch, followed by the URL being pushed. |  | 
| 5682   static const char* const kTestCases[] = { |  | 
| 5683     "http://www.google.com/foo.html", |  | 
| 5684     "http://www.google.com:81/foo.js",     // Bad port |  | 
| 5685 |  | 
| 5686     "http://www.google.com/foo.html", |  | 
| 5687     "https://www.google.com/foo.js",       // Bad protocol |  | 
| 5688 |  | 
| 5689     "http://www.google.com/foo.html", |  | 
| 5690     "ftp://www.google.com/foo.js",         // Invalid Protocol |  | 
| 5691 |  | 
| 5692     "http://www.google.com/foo.html", |  | 
| 5693     "http://blat.www.google.com/foo.js",   // Cross subdomain |  | 
| 5694 |  | 
| 5695     "http://www.google.com/foo.html", |  | 
| 5696     "http://www.foo.com/foo.js",           // Cross domain |  | 
| 5697   }; |  | 
| 5698 |  | 
| 5699 |  | 
| 5700   static const unsigned char kPushBodyFrame[] = { |  | 
| 5701     0x00, 0x00, 0x00, 0x02,                                      // header, ID |  | 
| 5702     0x01, 0x00, 0x00, 0x06,                                      // FIN, length |  | 
| 5703     'p', 'u', 's', 'h', 'e', 'd'                                 // "pushed" |  | 
| 5704   }; |  | 
| 5705 |  | 
| 5706   for (size_t index = 0; index < arraysize(kTestCases); index += 2) { |  | 
| 5707     const char* url_to_fetch = kTestCases[index]; |  | 
| 5708     const char* url_to_push = kTestCases[index + 1]; |  | 
| 5709 |  | 
| 5710     scoped_ptr<spdy::SpdyFrame> |  | 
| 5711         stream1_syn(ConstructSpdyGet(url_to_fetch, false, 1, LOWEST)); |  | 
| 5712     scoped_ptr<spdy::SpdyFrame> |  | 
| 5713         stream1_body(ConstructSpdyBodyFrame(1, true)); |  | 
| 5714     scoped_ptr<spdy::SpdyFrame> push_rst( |  | 
| 5715         ConstructSpdyRstStream(2, spdy::REFUSED_STREAM)); |  | 
| 5716     MockWrite writes[] = { |  | 
| 5717       CreateMockWrite(*stream1_syn, 1), |  | 
| 5718       CreateMockWrite(*push_rst, 4), |  | 
| 5719     }; |  | 
| 5720 |  | 
| 5721     scoped_ptr<spdy::SpdyFrame> |  | 
| 5722         stream1_reply(ConstructSpdyGetSynReply(NULL, 0, 1)); |  | 
| 5723     scoped_ptr<spdy::SpdyFrame> |  | 
| 5724         stream2_syn(ConstructSpdyPush(NULL, |  | 
| 5725                                       0, |  | 
| 5726                                       2, |  | 
| 5727                                       1, |  | 
| 5728                                       url_to_push)); |  | 
| 5729     scoped_ptr<spdy::SpdyFrame> rst( |  | 
| 5730         ConstructSpdyRstStream(2, spdy::CANCEL)); |  | 
| 5731 |  | 
| 5732     MockRead reads[] = { |  | 
| 5733       CreateMockRead(*stream1_reply, 2), |  | 
| 5734       CreateMockRead(*stream2_syn, 3), |  | 
| 5735       CreateMockRead(*stream1_body, 5, SYNCHRONOUS), |  | 
| 5736       MockRead(ASYNC, reinterpret_cast<const char*>(kPushBodyFrame), |  | 
| 5737                arraysize(kPushBodyFrame), 6), |  | 
| 5738       MockRead(ASYNC, ERR_IO_PENDING, 7),  // Force a pause |  | 
| 5739     }; |  | 
| 5740 |  | 
| 5741     HttpResponseInfo response; |  | 
| 5742     scoped_ptr<OrderedSocketData> data(new OrderedSocketData( |  | 
| 5743         reads, |  | 
| 5744         arraysize(reads), |  | 
| 5745         writes, |  | 
| 5746         arraysize(writes))); |  | 
| 5747 |  | 
| 5748     HttpRequestInfo request; |  | 
| 5749     request.method = "GET"; |  | 
| 5750     request.url = GURL(url_to_fetch); |  | 
| 5751     request.load_flags = 0; |  | 
| 5752     NormalSpdyTransactionHelper helper(request, |  | 
| 5753                                        BoundNetLog(), GetParam()); |  | 
| 5754     helper.RunPreTestSetup(); |  | 
| 5755     helper.AddData(data.get()); |  | 
| 5756 |  | 
| 5757     HttpNetworkTransaction* trans = helper.trans(); |  | 
| 5758 |  | 
| 5759     // Start the transaction with basic parameters. |  | 
| 5760     TestCompletionCallback callback; |  | 
| 5761 |  | 
| 5762     int rv = trans->Start(&request, callback.callback(), BoundNetLog()); |  | 
| 5763     EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 5764     rv = callback.WaitForResult(); |  | 
| 5765 |  | 
| 5766     // Read the response body. |  | 
| 5767     std::string result; |  | 
| 5768     ReadResult(trans, data.get(), &result); |  | 
| 5769 |  | 
| 5770     // Verify that we consumed all test data. |  | 
| 5771     EXPECT_TRUE(data->at_read_eof()); |  | 
| 5772     EXPECT_TRUE(data->at_write_eof()); |  | 
| 5773 |  | 
| 5774     // Verify the SYN_REPLY. |  | 
| 5775     // Copy the response info, because trans goes away. |  | 
| 5776     response = *trans->GetResponseInfo(); |  | 
| 5777 |  | 
| 5778     VerifyStreamsClosed(helper); |  | 
| 5779 |  | 
| 5780     // Verify the SYN_REPLY. |  | 
| 5781     EXPECT_TRUE(response.headers != NULL); |  | 
| 5782     EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |  | 
| 5783   } |  | 
| 5784 } |  | 
| 5785 |  | 
| 5786 TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) { |  | 
| 5787   // Construct the request. |  | 
| 5788   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |  | 
| 5789   scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST)); |  | 
| 5790   MockWrite writes[] = { |  | 
| 5791     CreateMockWrite(*req, 1), |  | 
| 5792     CreateMockWrite(*req2, 3), |  | 
| 5793   }; |  | 
| 5794 |  | 
| 5795   scoped_ptr<spdy::SpdyFrame> refused( |  | 
| 5796       ConstructSpdyRstStream(1, spdy::REFUSED_STREAM)); |  | 
| 5797   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 3)); |  | 
| 5798   scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(3, true)); |  | 
| 5799   MockRead reads[] = { |  | 
| 5800     CreateMockRead(*refused, 2), |  | 
| 5801     CreateMockRead(*resp, 4), |  | 
| 5802     CreateMockRead(*body, 5), |  | 
| 5803     MockRead(ASYNC, 0, 6)  // EOF |  | 
| 5804   }; |  | 
| 5805 |  | 
| 5806   scoped_ptr<OrderedSocketData> data( |  | 
| 5807       new OrderedSocketData(reads, arraysize(reads), |  | 
| 5808                             writes, arraysize(writes))); |  | 
| 5809   NormalSpdyTransactionHelper helper(CreateGetRequest(), |  | 
| 5810                                      BoundNetLog(), GetParam()); |  | 
| 5811 |  | 
| 5812   helper.RunPreTestSetup(); |  | 
| 5813   helper.AddData(data.get()); |  | 
| 5814 |  | 
| 5815   HttpNetworkTransaction* trans = helper.trans(); |  | 
| 5816 |  | 
| 5817   // Start the transaction with basic parameters. |  | 
| 5818   TestCompletionCallback callback; |  | 
| 5819   int rv = trans->Start( |  | 
| 5820       &CreateGetRequest(), callback.callback(), BoundNetLog()); |  | 
| 5821   EXPECT_EQ(ERR_IO_PENDING, rv); |  | 
| 5822   rv = callback.WaitForResult(); |  | 
| 5823   EXPECT_EQ(OK, rv); |  | 
| 5824 |  | 
| 5825   // Verify that we consumed all test data. |  | 
| 5826   EXPECT_TRUE(data->at_read_eof()) << "Read count: " |  | 
| 5827                                    << data->read_count() |  | 
| 5828                                    << " Read index: " |  | 
| 5829                                    << data->read_index(); |  | 
| 5830   EXPECT_TRUE(data->at_write_eof()) << "Write count: " |  | 
| 5831                                     << data->write_count() |  | 
| 5832                                     << " Write index: " |  | 
| 5833                                     << data->write_index(); |  | 
| 5834 |  | 
| 5835   // Verify the SYN_REPLY. |  | 
| 5836   HttpResponseInfo response = *trans->GetResponseInfo(); |  | 
| 5837   EXPECT_TRUE(response.headers != NULL); |  | 
| 5838   EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine()); |  | 
| 5839 } |  | 
| 5840 |  | 
| 5841 }  // namespace net |  | 
| OLD | NEW | 
|---|