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