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