spdy_network_transaction_unittest.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/scoped_temp_dir.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h"
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/run_loop.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/stl_util.h"
1523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/strings/string_piece.h"
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/test/test_file_util.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/auth.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log_unittest.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/request_priority.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_bytes_element_reader.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/upload_data_stream.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_file_element_reader.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_session_peer.h"
247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "net/http/http_network_transaction.h"
257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "net/http/http_server_properties.h"
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/http/http_transaction_test_util.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_pool_base.h"
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/socket/next_proto.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/buffered_spdy_framer.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_http_stream.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_http_utils.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session_pool.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_test_util_common.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_test_utils.h"
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/ssl/ssl_connection_status_flags.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_test_util.h"
3823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/platform_test.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using testing::Each;
4823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using testing::Eq;
4923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kRequestUrl[] = "http://www.google.com/";
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)enum SpdyNetworkTransactionTestSSLType {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SPDYNPN,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SPDYNOSSL,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SPDYSSL,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)struct SpdyNetworkTransactionTestParams {
597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SpdyNetworkTransactionTestParams()
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      : protocol(kProtoSPDY3),
617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        ssl_type(SPDYNPN) {}
627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SpdyNetworkTransactionTestParams(
647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      NextProto protocol,
657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      SpdyNetworkTransactionTestSSLType ssl_type)
667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      : protocol(protocol),
677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        ssl_type(ssl_type) {}
687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  NextProto protocol;
707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SpdyNetworkTransactionTestSSLType ssl_type;
717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)};
727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void UpdateSpdySessionDependencies(
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SpdyNetworkTransactionTestParams test_params,
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SpdySessionDependencies* session_deps) {
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  switch (test_params.ssl_type) {
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SPDYNPN:
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      session_deps->http_server_properties.SetAlternateProtocol(
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          HostPortPair("www.google.com", 80), 443,
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          AlternateProtocolFromNextProto(test_params.protocol), 1);
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      session_deps->use_alternate_protocols = true;
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      session_deps->next_protos = SpdyNextProtos();
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SPDYNOSSL:
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      session_deps->force_spdy_over_ssl = false;
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      session_deps->force_spdy_always = true;
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case SPDYSSL:
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      session_deps->force_spdy_over_ssl = true;
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      session_deps->force_spdy_always = true;
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    default:
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      NOTREACHED();
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)SpdySessionDependencies* CreateSpdySessionDependencies(
987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SpdyNetworkTransactionTestParams test_params) {
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SpdySessionDependencies* session_deps =
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new SpdySessionDependencies(test_params.protocol);
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UpdateSpdySessionDependencies(test_params, session_deps);
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return session_deps;
1037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)SpdySessionDependencies* CreateSpdySessionDependencies(
1067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SpdyNetworkTransactionTestParams test_params,
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ProxyService* proxy_service) {
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SpdySessionDependencies* session_deps =
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new SpdySessionDependencies(test_params.protocol, proxy_service);
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UpdateSpdySessionDependencies(test_params, session_deps);
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return session_deps;
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}  // namespace
1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)class SpdyNetworkTransactionTest
1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : public ::testing::TestWithParam<SpdyNetworkTransactionTestParams> {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol) {
120b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  virtual ~SpdyNetworkTransactionTest() {
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // UploadDataStream posts deletion tasks back to the message loop on
1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // destruction.
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    upload_data_stream_.reset();
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::RunLoop().RunUntilIdle();
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    google_get_request_initialized_ = false;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    google_post_request_initialized_ = false;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    google_chunked_post_request_initialized_ = false;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct TransactionHelperResult {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string status_line;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string response_data;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpResponseInfo response_info;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A helper class that handles all the initial npn/ssl setup.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class NormalSpdyTransactionHelper {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NormalSpdyTransactionHelper(const HttpRequestInfo& request,
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                RequestPriority priority,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const BoundNetLog& log,
1497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                SpdyNetworkTransactionTestParams test_params,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                SpdySessionDependencies* session_deps)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : request_(request),
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          priority_(priority),
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_deps_(session_deps == NULL ?
1547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        CreateSpdySessionDependencies(test_params) :
1557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        session_deps),
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_(SpdySessionDependencies::SpdyCreateSession(
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       session_deps_.get())),
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          log_(log),
1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          test_params_(test_params),
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          deterministic_(false),
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          spdy_enabled_(true) {
1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      switch (test_params_.ssl_type) {
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case SPDYNOSSL:
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case SPDYSSL:
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          port_ = 80;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case SPDYNPN:
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          port_ = 443;
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        default:
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          NOTREACHED();
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~NormalSpdyTransactionHelper() {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Any test which doesn't close the socket by sending it an EOF will
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // have a valid session left open, which leaks the entire session pool.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is just fine - in fact, some of our tests intentionally do this
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // so that we can check consistency of the SpdySessionPool as the test
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // finishes.  If we had put an EOF on the socket, the SpdySession would
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // have closed and we wouldn't be able to check the consistency.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Forcefully close existing sessions here.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session()->spdy_session_pool()->CloseAllSessions();
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void SetDeterministic() {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_deps_.get());
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      deterministic_ = true;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void SetSpdyDisabled() {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      spdy_enabled_ = false;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      port_ = 80;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void RunPreTestSetup() {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!session_deps_.get())
2007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        session_deps_.reset(CreateSpdySessionDependencies(test_params_));
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (!session_.get()) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        session_ = SpdySessionDependencies::SpdyCreateSession(
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            session_deps_.get());
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We're now ready to use SSL-npn SPDY.
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start the transaction, read some data, finish.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void RunDefaultTest() {
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!StartDefaultTest())
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FinishDefaultTest();
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool StartDefaultTest() {
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      output_.rv = trans_->Start(&request_, callback_.callback(), log_);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We expect an IO Pending or some sort of error.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_LT(output_.rv, 0);
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return output_.rv == ERR_IO_PENDING;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void FinishDefaultTest() {
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      output_.rv = callback_.WaitForResult();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (output_.rv != OK) {
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        session_->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Verify responses.
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const HttpResponseInfo* response = trans_->GetResponseInfo();
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(response != NULL);
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ASSERT_TRUE(response->headers.get() != NULL);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (HttpStreamFactory::spdy_enabled()) {
239558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        EXPECT_EQ(
240558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch            HttpResponseInfo::ConnectionInfoFromNextProto(
241558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                test_params_.protocol),
242558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch            response->connection_info);
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  response->connection_info);
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (test_params_.ssl_type == SPDYNPN && spdy_enabled_) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_TRUE(response->was_npn_negotiated);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_TRUE(!response->was_npn_negotiated);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If SPDY is not enabled, a HTTP request should not be diverted
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // over a SSL session.
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!spdy_enabled_) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(request_.url.SchemeIs("https"),
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  response->was_npn_negotiated);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_EQ("127.0.0.1", response->socket_address.host());
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_EQ(port_, response->socket_address.port());
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output_.status_line = response->headers->GetStatusLine();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output_.response_info = *response;  // Make a copy so we can verify.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Most tests will want to call this function. In particular, the MockReads
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // should end with an empty read, and that read needs to be processed to
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // ensure proper deletion of the spdy_session_pool.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void VerifyDataConsumed() {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (DataVector::iterator it = data_vector_.begin();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          it != data_vector_.end(); ++it) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_TRUE((*it)->at_read_eof()) << "Read count: "
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          << (*it)->read_count()
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          << " Read index: "
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          << (*it)->read_index();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           << (*it)->write_count()
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           << " Write index: "
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           << (*it)->write_index();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Occasionally a test will expect to error out before certain reads are
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // processed. In that case we want to explicitly ensure that the reads were
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // not processed.
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void VerifyDataNotConsumed() {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (DataVector::iterator it = data_vector_.begin();
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          it != data_vector_.end(); ++it) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: "
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           << (*it)->read_count()
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           << " Read index: "
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           << (*it)->read_index();
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            << (*it)->write_count()
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            << " Write index: "
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            << (*it)->write_index();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void RunToCompletion(StaticSocketDataProvider* data) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RunPreTestSetup();
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddData(data);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RunDefaultTest();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VerifyDataConsumed();
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    void RunToCompletionWithSSLData(
307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        StaticSocketDataProvider* data,
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        scoped_ptr<SSLSocketDataProvider> ssl_provider) {
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      RunPreTestSetup();
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      RunDefaultTest();
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      VerifyDataConsumed();
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void AddData(StaticSocketDataProvider* data) {
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scoped_ptr<SSLSocketDataProvider> ssl_provider(
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          new SSLSocketDataProvider(ASYNC, OK));
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      AddDataWithSSLSocketDataProvider(data, ssl_provider.Pass());
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    void AddDataWithSSLSocketDataProvider(
322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        StaticSocketDataProvider* data,
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        scoped_ptr<SSLSocketDataProvider> ssl_provider) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(!deterministic_);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_vector_.push_back(data);
3267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (test_params_.ssl_type == SPDYNPN)
3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        ssl_provider->SetNextProto(test_params_.protocol);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (test_params_.ssl_type == SPDYNPN ||
330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          test_params_.ssl_type == SPDYSSL) {
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        session_deps_->socket_factory->AddSSLSocketDataProvider(
332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            ssl_provider.get());
333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ssl_vector_.push_back(ssl_provider.release());
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_deps_->socket_factory->AddSocketDataProvider(data);
3377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (test_params_.ssl_type == SPDYNPN) {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        StaticSocketDataProvider* hanging_non_alternate_protocol_socket =
3407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            new StaticSocketDataProvider(NULL, 0, NULL, 0);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hanging_non_alternate_protocol_socket->set_connect_data(
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            never_finishing_connect);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        session_deps_->socket_factory->AddSocketDataProvider(
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            hanging_non_alternate_protocol_socket);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        alternate_vector_.push_back(hanging_non_alternate_protocol_socket);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void AddDeterministicData(DeterministicSocketData* data) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(deterministic_);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_vector_.push_back(data);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SSLSocketDataProvider* ssl_provider =
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new SSLSocketDataProvider(ASYNC, OK);
3547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (test_params_.ssl_type == SPDYNPN)
3557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        ssl_provider->SetNextProto(test_params_.protocol);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_vector_.push_back(ssl_provider);
3587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (test_params_.ssl_type == SPDYNPN ||
3597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          test_params_.ssl_type == SPDYSSL) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        session_deps_->deterministic_socket_factory->
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            AddSSLSocketDataProvider(ssl_provider);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
3647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (test_params_.ssl_type == SPDYNPN) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DeterministicSocketData* hanging_non_alternate_protocol_socket =
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            new DeterministicSocketData(NULL, 0, NULL, 0);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hanging_non_alternate_protocol_socket->set_connect_data(
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            never_finishing_connect);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        session_deps_->deterministic_socket_factory->AddSocketDataProvider(
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            hanging_non_alternate_protocol_socket);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        alternate_deterministic_vector_.push_back(
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            hanging_non_alternate_protocol_socket);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_ = session;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpNetworkTransaction* trans() { return trans_.get(); }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void ResetTrans() { trans_.reset(); }
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionHelperResult& output() { return output_; }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HttpRequestInfo& request() const { return request_; }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<HttpNetworkSession>& session() const {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return session_;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdySessionDependencies>& session_deps() {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return session_deps_;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int port() const { return port_; }
3917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SpdyNetworkTransactionTestParams test_params() const {
3927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return test_params_;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef std::vector<StaticSocketDataProvider*> DataVector;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef ScopedVector<SSLSocketDataProvider> SSLVector;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef ScopedVector<StaticSocketDataProvider> AlternateVector;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef ScopedVector<DeterministicSocketData> AlternateDeterministicVector;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo request_;
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RequestPriority priority_;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdySessionDependencies> session_deps_;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<HttpNetworkSession> session_;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionHelperResult output_;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<StaticSocketDataProvider> first_transaction_;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSLVector ssl_vector_;
407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    TestCompletionCallback callback_;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpNetworkTransaction> trans_;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpNetworkTransaction> trans_http_;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DataVector data_vector_;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AlternateVector alternate_vector_;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AlternateDeterministicVector alternate_deterministic_vector_;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BoundNetLog& log_;
4147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SpdyNetworkTransactionTestParams test_params_;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int port_;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool deterministic_;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool spdy_enabled_;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             int expected_status);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ConnectStatusHelper(const MockRead& status);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpRequestInfo& CreateGetPushRequest() {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    google_get_push_request_.method = "GET";
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    google_get_push_request_.url = GURL("http://www.google.com/foo.dat");
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    google_get_push_request_.load_flags = 0;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return google_get_push_request_;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpRequestInfo& CreateGetRequest() {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!google_get_request_initialized_) {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_.method = "GET";
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_.url = GURL(kDefaultURL);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_.load_flags = 0;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_initialized_ = true;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return google_get_request_;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpRequestInfo& CreateGetRequestWithUserAgent() {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!google_get_request_initialized_) {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_.method = "GET";
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_.url = GURL(kDefaultURL);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_.load_flags = 0;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_initialized_ = true;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return google_get_request_;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpRequestInfo& CreatePostRequest() {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!google_post_request_initialized_) {
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ScopedVector<UploadElementReader> element_readers;
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      element_readers.push_back(
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new UploadBytesElementReader(kUploadData, kUploadDataSize));
45868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      upload_data_stream_.reset(
45968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          new UploadDataStream(element_readers.Pass(), 0));
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_.method = "POST";
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_.url = GURL(kDefaultURL);
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      google_post_request_.upload_data_stream = upload_data_stream_.get();
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_initialized_ = true;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return google_post_request_;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpRequestInfo& CreateFilePostRequest() {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!google_post_request_initialized_) {
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath file_path;
472a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK_EQ(static_cast<int>(kUploadDataSize),
474a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               base::WriteFile(file_path, kUploadData, kUploadDataSize));
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ScopedVector<UploadElementReader> element_readers;
4777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      element_readers.push_back(
4787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          new UploadFileElementReader(base::MessageLoopProxy::current().get(),
4797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      file_path,
4807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      0,
4817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      kUploadDataSize,
4827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      base::Time()));
48368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      upload_data_stream_.reset(
48468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          new UploadDataStream(element_readers.Pass(), 0));
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_.method = "POST";
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_.url = GURL(kDefaultURL);
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      google_post_request_.upload_data_stream = upload_data_stream_.get();
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_initialized_ = true;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return google_post_request_;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
494f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const HttpRequestInfo& CreateUnreadableFilePostRequest() {
495f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (google_post_request_initialized_)
496f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return google_post_request_;
497f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
498f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::FilePath file_path;
499a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
500f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    CHECK_EQ(static_cast<int>(kUploadDataSize),
501a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)             base::WriteFile(file_path, kUploadData, kUploadDataSize));
5026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    CHECK(base::MakeFileUnreadable(file_path));
503f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
504f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ScopedVector<UploadElementReader> element_readers;
505f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    element_readers.push_back(
506f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        new UploadFileElementReader(base::MessageLoopProxy::current().get(),
507f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                    file_path,
508f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                    0,
509f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                    kUploadDataSize,
510f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                    base::Time()));
511f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    upload_data_stream_.reset(
512f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        new UploadDataStream(element_readers.Pass(), 0));
513f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
514f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    google_post_request_.method = "POST";
515f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    google_post_request_.url = GURL(kDefaultURL);
516f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    google_post_request_.upload_data_stream = upload_data_stream_.get();
517f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    google_post_request_initialized_ = true;
518f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return google_post_request_;
519f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
520f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpRequestInfo& CreateComplexPostRequest() {
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!google_post_request_initialized_) {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int kFileRangeOffset = 1;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int kFileRangeLength = 3;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath file_path;
528a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK_EQ(static_cast<int>(kUploadDataSize),
530a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               base::WriteFile(file_path, kUploadData, kUploadDataSize));
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ScopedVector<UploadElementReader> element_readers;
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      element_readers.push_back(
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new UploadBytesElementReader(kUploadData, kFileRangeOffset));
5357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      element_readers.push_back(
5367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          new UploadFileElementReader(base::MessageLoopProxy::current().get(),
5377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      file_path,
5387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      kFileRangeOffset,
5397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      kFileRangeLength,
5407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      base::Time()));
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      element_readers.push_back(new UploadBytesElementReader(
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kUploadData + kFileRangeOffset + kFileRangeLength,
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
54468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      upload_data_stream_.reset(
54568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          new UploadDataStream(element_readers.Pass(), 0));
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_.method = "POST";
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_.url = GURL(kDefaultURL);
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      google_post_request_.upload_data_stream = upload_data_stream_.get();
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_initialized_ = true;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return google_post_request_;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpRequestInfo& CreateChunkedPostRequest() {
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!google_chunked_post_request_initialized_) {
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      upload_data_stream_.reset(
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new UploadDataStream(UploadDataStream::CHUNKED, 0));
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_chunked_post_request_.method = "POST";
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_chunked_post_request_.url = GURL(kDefaultURL);
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      google_chunked_post_request_.upload_data_stream =
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          upload_data_stream_.get();
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_chunked_post_request_initialized_ = true;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return google_chunked_post_request_;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read the result of a particular transaction, knowing that we've got
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // multiple transactions in the read pipeline; so as we read, we may have
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to skip over data destined for other transactions while we consume
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the data for |trans|.
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ReadResult(HttpNetworkTransaction* trans,
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 StaticSocketDataProvider* data,
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 std::string* result) {
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kSize = 3000;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int bytes_read = 0;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestCompletionCallback callback;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (true) {
581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      int rv = trans->Read(buf.get(), kSize, callback.callback());
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rv == ERR_IO_PENDING) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Multiple transactions may be in the data set.  Keep pulling off
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // reads until we complete our callback.
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (!callback.have_result()) {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          data->CompleteRead();
5873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          base::RunLoop().RunUntilIdle();
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = callback.WaitForResult();
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (rv <= 0) {
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result->append(buf->data(), rv);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytes_read += rv;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return bytes_read;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This lengthy block is reaching into the pool to dig out the active
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // session.  Once we have the session, we verify that the streams are
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // all closed and not leaked at this point.
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url = helper.request().url;
6047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    int port = helper.test_params().ssl_type == SPDYNPN ? 443 : 80;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HostPortPair host_port_pair(url.host(), port);
60690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
607e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                       PRIVACY_MODE_DISABLED);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BoundNetLog log;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<HttpNetworkSession>& session = helper.session();
610ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    base::WeakPtr<SpdySession> spdy_session =
6117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        session->spdy_session_pool()->FindAvailableSession(key, log);
6127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ASSERT_TRUE(spdy_session != NULL);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, spdy_session->num_active_streams());
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunServerPushTest(OrderedSocketData* data,
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         HttpResponseInfo* response,
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         HttpResponseInfo* push_response,
620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         const std::string& expected) {
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       BoundNetLog(), GetParam(), NULL);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.RunPreTestSetup();
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.AddData(data);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpNetworkTransaction* trans = helper.trans();
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start the transaction with basic parameters.
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestCompletionCallback callback;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = trans->Start(
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &CreateGetRequest(), callback.callback(), BoundNetLog());
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERR_IO_PENDING, rv);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = callback.WaitForResult();
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Request the pushed path.
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpNetworkTransaction> trans2(
637868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = trans2->Start(
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &CreateGetPushRequest(), callback.callback(), BoundNetLog());
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERR_IO_PENDING, rv);
6413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::RunLoop().RunUntilIdle();
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // The data for the pushed path may be coming in more than 1 frame. Compile
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the results into a single string.
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read the server push body.
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string result2;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReadResult(trans2.get(), data, &result2);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read the response body.
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string result;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReadResult(trans, data, &result);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify that we consumed all test data.
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(data->at_read_eof());
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(data->at_write_eof());
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify that the received push data is same as the expected push data.
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            << result2
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            << "||||| Expected data: "
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            << expected;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify the SYN_REPLY.
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Copy the response info, because trans goes away.
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *response = *trans->GetResponseInfo();
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *push_response = *trans2->GetResponseInfo();
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VerifyStreamsClosed(helper);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int result) {
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper->ResetTrans();
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void StartTransactionCallback(
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<HttpNetworkSession>& session,
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int result) {
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpNetworkTransaction> trans(
680868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestCompletionCallback callback;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo request;
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request.method = "GET";
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request.url = GURL("http://www.google.com/");
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request.load_flags = 0;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERR_IO_PENDING, rv);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.WaitForResult();
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
691b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  SpdyTestUtil spdy_util_;
692b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<UploadDataStream> upload_data_stream_;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool google_get_request_initialized_;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool google_post_request_initialized_;
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool google_chunked_post_request_initialized_;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo google_get_request_;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo google_post_request_;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo google_chunked_post_request_;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo google_get_push_request_;
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ScopedTempDir temp_dir_;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All tests are run with three different connection types: SPDY after NPN
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// negotiation, SPDY without SSL, and SPDY with SSL.
7087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)//
7097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// TODO(akalin): Use ::testing::Combine() when we are able to use
7107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// <tr1/tuple>.
7117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(
7127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    Spdy,
7137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SpdyNetworkTransactionTest,
7147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ::testing::Values(
7154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNOSSL),
7164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYSSL),
7174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNPN),
7187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNOSSL),
7197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYSSL),
7207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNPN),
7217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNOSSL),
7227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYSSL),
7237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN),
724a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYNOSSL),
725a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYSSL),
726a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYNPN)));
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify HttpNetworkTransaction constructor.
7297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, Constructor) {
730c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdySessionDependencies> session_deps(
7317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      CreateSpdySessionDependencies(GetParam()));
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<HttpNetworkSession> session(
733c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<HttpTransaction> trans(
735868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, Get) {
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the request.
74090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
74190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req) };
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
7457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
7648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       p = RequestPriority(p + 1)) {
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Construct the request.
76790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_ptr<SpdyFrame> req(
76890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true));
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite writes[] = { CreateMockWrite(*req) };
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpdyPriority spdy_prio = 0;
7727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio));
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this repeats the RequestPriority-->SpdyPriority mapping from
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // sure it's being done right.
7767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (spdy_util_.spdy_version() < SPDY3) {
7777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      switch(p) {
7787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case HIGHEST:
7797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(0, spdy_prio);
7807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
7817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case MEDIUM:
7827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(1, spdy_prio);
7837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
7847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case LOW:
7857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case LOWEST:
7867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(2, spdy_prio);
7877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
7887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case IDLE:
7897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(3, spdy_prio);
7907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
7917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        default:
7927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          FAIL();
7937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
7947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    } else {
7957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      switch(p) {
7967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case HIGHEST:
7977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(0, spdy_prio);
7987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
7997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case MEDIUM:
8007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(1, spdy_prio);
8017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
8027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case LOW:
8037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(2, spdy_prio);
8047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
8057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case LOWEST:
8067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(3, spdy_prio);
8077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
8087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case IDLE:
8097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(4, spdy_prio);
8107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
8117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        default:
8127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          FAIL();
8137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead reads[] = {
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*resp),
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*body),
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockRead(ASYNC, 0, 0)  // EOF
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelayedSocketData data(1, reads, arraysize(reads),
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              writes, arraysize(writes));
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo http_req = CreateGetRequest();
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(),
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       GetParam(), NULL);
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.RunToCompletion(&data);
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionHelperResult out = helper.output();
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, out.rv);
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("hello!", out.response_data);
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start three gets simultaniously; making sure that multiplexed
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// streams work properly.
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This can't use the TransactionHelper method, since it only
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// handles a single transaction, and finishes them as soon
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as it launches them.
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(gavinp): create a working generalized TransactionHelper that
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can allow multiple streams in flight.
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
84990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
85090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
8537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
85690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
8577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
8587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
8597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
86190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req3(
86290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
8637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
8647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
8657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req2),
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req3),
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp, 1),
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp2, 4),
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body2),
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp3, 7),
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body3),
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody),
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody2),
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody3),
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0),  // EOF
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog log;
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out;
8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We require placeholder data because three get requests are sent out, so
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there needs to be three sets of SSL connection data.
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans1(
901868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans2(
903868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans3(
905868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback3;
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq1 = CreateGetRequest();
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq2 = CreateGetRequest();
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq3 = CreateGetRequest();
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback1.WaitForResult();
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback3.WaitForResult();
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
928868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response1->headers.get() != NULL);
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response1->was_fetched_via_spdy);
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response1->headers->GetStatusLine();
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response1;
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  trans2->GetResponseInfo();
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans1.get(), &out.response_data);
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
94590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
94690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
9497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
95290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
9537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
9547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
9557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req2),
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp, 1),
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp2, 4),
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body2),
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody),
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody2),
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0),  // EOF
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_placeholder.set_connect_data(never_finishing_connect);
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog log;
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out;
9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We require placeholder data because two get requests are sent out, so
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there needs to be two sets of SSL connection data.
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans1(
988868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans2(
990868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq1 = CreateGetRequest();
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq2 = CreateGetRequest();
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback1.WaitForResult();
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback2.WaitForResult();
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1009868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response1->headers.get() != NULL);
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response1->was_fetched_via_spdy);
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response1->headers->GetStatusLine();
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response1;
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans1.get(), &out.response_data);
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1019868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response2->headers.get() != NULL);
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response2->was_fetched_via_spdy);
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response2->headers->GetStatusLine();
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response2;
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans2.get(), &out.response_data);
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
103290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
103390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
10367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
103890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
103990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
10407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
10427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req2),
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp, 1),
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp2, 4),
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body2),
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody),
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody2),
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0),  // EOF
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData preconnect_data(reads, arraysize(reads),
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    writes, arraysize(writes));
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_placeholder.set_connect_data(never_finishing_connect);
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog log;
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out;
10672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&preconnect_data);
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We require placeholder data because 3 connections are attempted (first is
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the preconnect, 2nd and 3rd are the never finished connections.
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans1(
1077868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans2(
1079868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq = CreateGetRequest();
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Preconnect the first.
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLConfig preconnect_ssl_config;
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpStreamFactory* http_stream_factory =
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      helper.session()->http_stream_factory();
1091cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  helper.session()->GetNextProtos(&preconnect_ssl_config.next_protos);
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  http_stream_factory->PreconnectStreams(
10942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1, httpreq, DEFAULT_PRIORITY,
10952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      preconnect_ssl_config, preconnect_ssl_config);
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans1->Start(&httpreq, callback1.callback(), log);
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans2->Start(&httpreq, callback2.callback(), log);
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback1.WaitForResult();
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback2.WaitForResult();
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response1->headers.get() != NULL);
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response1->was_fetched_via_spdy);
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response1->headers->GetStatusLine();
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response1;
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans1.get(), &out.response_data);
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response2->headers.get() != NULL);
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response2->was_fetched_via_spdy);
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response2->headers->GetStatusLine();
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response2;
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans2.get(), &out.response_data);
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Similar to ThreeGets above, however this test adds a SETTINGS
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// frame.  The SETTINGS frame is read during the IO loop waiting on
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the first transaction completion, and sets a maximum concurrent
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stream limit of 1.  This means that our IO loop exists after the
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// second transaction completes, so we can assert on read_index().
11357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the request.
113790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
113890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
11397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
11417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
114390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
114490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
11457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
11477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
114990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req3(
115090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
11517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
11527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
11537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsMap settings;
11562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const uint32 max_concurrent_streams = 1;
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
115990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
116090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(settings));
1161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
1165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*settings_ack, 2),
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req2),
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req3),
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*settings_frame, 1),
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody),
1175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp2, 8),
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body2),
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody2),
1178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp3, 13),
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body3),
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody3),
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0),  // EOF
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog log;
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out;
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
11922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       BoundNetLog(), GetParam(), NULL);
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.RunPreTestSetup();
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.AddData(&data);
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We require placeholder data because three get requests are sent out, so
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // there needs to be three sets of SSL connection data.
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.AddData(&data_placeholder);
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.AddData(&data_placeholder);
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpNetworkTransaction> trans1(
1201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpNetworkTransaction> trans2(
1203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpNetworkTransaction> trans3(
1205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestCompletionCallback callback1;
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestCompletionCallback callback2;
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestCompletionCallback callback3;
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo httpreq1 = CreateGetRequest();
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo httpreq2 = CreateGetRequest();
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo httpreq3 = CreateGetRequest();
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(out.rv, ERR_IO_PENDING);
12177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // Run transaction 1 through quickly to force a read of our SETTINGS
12187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // frame.
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = callback1.WaitForResult();
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(OK, out.rv);
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(out.rv, ERR_IO_PENDING);
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(out.rv, ERR_IO_PENDING);
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = callback2.WaitForResult();
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(OK, out.rv);
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(7U, data.read_index());  // i.e. the third trans was queued
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = callback3.WaitForResult();
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(OK, out.rv);
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HttpResponseInfo* response1 = trans1->GetResponseInfo();
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(response1 != NULL);
1235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_TRUE(response1->headers.get() != NULL);
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(response1->was_fetched_via_spdy);
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.status_line = response1->headers->GetStatusLine();
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.response_info = *response1;
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = ReadTransaction(trans1.get(), &out.response_data);
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, out.rv);
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("hello!hello!", out.response_data);
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HttpResponseInfo* response2 = trans2->GetResponseInfo();
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.status_line = response2->headers->GetStatusLine();
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.response_info = *response2;
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = ReadTransaction(trans2.get(), &out.response_data);
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, out.rv);
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("hello!hello!", out.response_data);
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HttpResponseInfo* response3 = trans3->GetResponseInfo();
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.status_line = response3->headers->GetStatusLine();
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.response_info = *response3;
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = ReadTransaction(trans3.get(), &out.response_data);
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, out.rv);
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("hello!hello!", out.response_data);
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.VerifyDataConsumed();
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a fourth transaction.  The third and fourth transactions have
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// different data ("hello!" vs "hello!hello!") and because of the
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// user specified priority, we expect to see them inverted in
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the response from the server.
12707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the request.
127290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
127390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
12747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
12767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
127890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
127990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
12807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
12827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> req4(
128590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true));
12867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
12877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true));
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
128990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req3(
129090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true));
12917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
12927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false));
12937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true));
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsMap settings;
12962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const uint32 max_concurrent_streams = 1;
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
129990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
130090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(settings));
1301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req),
1304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*settings_ack, 2),
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req2),
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req4),
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req3),
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*settings_frame, 1),
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody),
1314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp2, 8),
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body2),
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody2),
1317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp4, 14),
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody4),
1319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp3, 17),
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body3),
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody3),
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0),  // EOF
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog log;
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out;
13322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
13332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We require placeholder data because four get requests are sent out, so
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there needs to be four sets of SSL connection data.
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans1(
1342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans2(
1344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans3(
1346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans4(
1348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(HIGHEST, helper.session().get()));
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback3;
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback4;
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq1 = CreateGetRequest();
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq2 = CreateGetRequest();
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq3 = CreateGetRequest();
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq4 = CreateGetRequest();
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run transaction 1 through quickly to force a read of our SETTINGS frame.
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback1.WaitForResult();
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback2.WaitForResult();
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(data.read_index(), 7U);  // i.e. the third & fourth trans queued
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback3.WaitForResult();
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response1->headers.get() != NULL);
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response1->was_fetched_via_spdy);
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response1->headers->GetStatusLine();
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response1;
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans1.get(), &out.response_data);
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response2->headers->GetStatusLine();
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response2;
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans2.get(), &out.response_data);
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notice: response3 gets two hellos, response4 gets one
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // hello, so we know dequeuing priority was respected.
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response3 = trans3->GetResponseInfo();
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response3->headers->GetStatusLine();
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response3;
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans3.get(), &out.response_data);
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback4.WaitForResult();
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response4 = trans4->GetResponseInfo();
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response4->headers->GetStatusLine();
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response4;
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans4.get(), &out.response_data);
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Similar to ThreeGetsMaxConcurrrent above, however, this test
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deletes a session in the middle of the transaction to insure
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that we properly remove pendingcreatestream objects from
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the spdy_session
14257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the request.
142790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
142890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
14297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
14307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
14317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
143390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
143490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
14357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
14367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
14377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsMap settings;
14402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const uint32 max_concurrent_streams = 1;
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
144390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
144490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(settings));
1445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockWrite writes[] = {
1448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*req),
1449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*settings_ack, 2),
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req2),
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*settings_frame, 1),
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody),
1457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp2, 8),
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body2),
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody2),
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0),  // EOF
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog log;
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out;
14692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
14702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We require placeholder data because three get requests are sent out, so
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there needs to be three sets of SSL connection data.
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans1(
1478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans2(
1480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans3(
1482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback3;
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq1 = CreateGetRequest();
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq2 = CreateGetRequest();
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq3 = CreateGetRequest();
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(out.rv, ERR_IO_PENDING);
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run transaction 1 through quickly to force a read of our SETTINGS frame.
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback1.WaitForResult();
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(out.rv, ERR_IO_PENDING);
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete trans3.release();
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(out.rv, ERR_IO_PENDING);
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback2.WaitForResult();
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(8U, data.read_index());
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(response1 != NULL);
1510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response1->headers.get() != NULL);
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response1->was_fetched_via_spdy);
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response1->headers->GetStatusLine();
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response1;
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans1.get(), &out.response_data);
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(response2 != NULL);
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response2->headers->GetStatusLine();
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response2;
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans2.get(), &out.response_data);
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The KillerCallback will delete the transaction on error as part of the
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// callback.
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class KillerCallback : public TestCompletionCallbackBase {
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit KillerCallback(HttpNetworkTransaction* transaction)
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : transaction_(transaction),
1539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        callback_(base::Bind(&KillerCallback::OnComplete,
1540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             base::Unretained(this))) {
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~KillerCallback() {}
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const CompletionCallback& callback() const { return callback_; }
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnComplete(int result) {
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result < 0)
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete transaction_;
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetResult(result);
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* transaction_;
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback callback_;
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// closes the socket while we have a pending transaction waiting for
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a pending stream creation.  http://crbug.com/52901
15647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the request.
156690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
156790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
15687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
15697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
15707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
157290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
157390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
15747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsMap settings;
15772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const uint32 max_concurrent_streams = 1;
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
158090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
158190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(settings));
1582cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1584cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockWrite writes[] = {
1585cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*req),
1586cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockWrite(*settings_ack, 2),
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req2),
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*settings_frame, 1),
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fin_body),
1594cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CreateMockRead(*resp2, 8),
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_CONNECTION_RESET, 0),  // Abort!
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog log;
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out;
16042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
16052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We require placeholder data because three get requests are sent out, so
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there needs to be three sets of SSL connection data.
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
1612868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session().get());
1613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session().get());
16142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HttpNetworkTransaction* trans3(
1615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  KillerCallback callback3(trans3);
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq1 = CreateGetRequest();
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq2 = CreateGetRequest();
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq3 = CreateGetRequest();
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(out.rv, ERR_IO_PENDING);
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run transaction 1 through quickly to force a read of our SETTINGS frame.
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback1.WaitForResult();
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(out.rv, ERR_IO_PENDING);
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(out.rv, ERR_IO_PENDING);
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback3.WaitForResult();
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_ABORTED, out.rv);
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(6U, data.read_index());
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response1 = trans1.GetResponseInfo();
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(response1 != NULL);
1642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response1->headers.get() != NULL);
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response1->was_fetched_via_spdy);
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response1->headers->GetStatusLine();
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response1;
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(&trans1, &out.response_data);
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response2 = trans2.GetResponseInfo();
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(response2 != NULL);
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response2->headers->GetStatusLine();
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response2;
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(&trans2, &out.response_data);
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a simple PUT request works.
16607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, Put) {
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup the request
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo request;
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.method = "PUT";
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.url = GURL("http://www.google.com/");
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> put_headers(
16677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructPutHeaderBlock("http://www.google.com", 0));
1668116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> req(
1669116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdySyn(1, *put_headers, LOWEST, false, true));
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
167190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CreateMockWrite(*req),
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1674116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
16757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
16842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a simple HEAD request works.
16947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, Head) {
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup the request
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo request;
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.method = "HEAD";
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.url = GURL("http://www.google.com/");
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> head_headers(
17017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructHeadHeaderBlock("http://www.google.com", 0));
1702116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> req(
1703116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdySyn(1, *head_headers, LOWEST, false, true));
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
170590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CreateMockWrite(*req),
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1708116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
17097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
17182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a simple POST works.
17287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, Post) {
17292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
17307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
17317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
17327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*body),  // POST upload frame
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(2, reads, arraysize(reads),
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
17472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a POST with a file works.
17577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, FilePost) {
17582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
17597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
17607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
17617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*body),  // POST upload frame
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(2, reads, arraysize(reads),
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
17762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Test that a POST with a unreadable file fails.
1786f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, UnreadableFilePost) {
1787f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MockWrite writes[] = {
1788f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    MockWrite(ASYNC, 0, 0)  // EOF
1789f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
1790f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MockRead reads[] = {
1791f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
1792f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
1793f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1794f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
1795f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
1796f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     DEFAULT_PRIORITY,
1797f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
1798f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  helper.RunPreTestSetup();
1799f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  helper.AddData(&data);
1800f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  helper.RunDefaultTest();
1801f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1802f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
1803f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  helper.VerifyDataNotConsumed();
1804f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(ERR_ACCESS_DENIED, helper.output().rv);
1805f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1806f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a complex POST works.
18087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
18092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
18107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
18117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
18127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*body),  // POST upload frame
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(2, reads, arraysize(reads),
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
18282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     DEFAULT_PRIORITY,
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a chunked POST works.
18387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
18397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
18407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
18412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
18422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req),
18432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*body),
18442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
18452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
18472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
18482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp),
18492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*body),
18502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
18512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DelayedSocketData data(2, reads, arraysize(reads),
18542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         writes, arraysize(writes));
18552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
18562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     DEFAULT_PRIORITY,
18572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
18582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // These chunks get merged into a single frame when being sent.
18602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kFirstChunkSize = kUploadDataSize/2;
18612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.request().upload_data_stream->AppendChunk(
18622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kUploadData, kFirstChunkSize, false);
18632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.request().upload_data_stream->AppendChunk(
18642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
18652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.RunToCompletion(&data);
18672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TransactionHelperResult out = helper.output();
18682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, out.rv);
18692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
18702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kUploadData, out.response_data);
18712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
18722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Test that a chunked POST works with chunks appended after transaction starts.
18747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
18757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
18767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
18777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false));
18787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*chunk1),
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*chunk2),
18832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*chunk3),
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*chunk1),
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*chunk2),
18912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*chunk3),
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DelayedSocketData data(4, reads, arraysize(reads),
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
18982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     DEFAULT_PRIORITY,
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
19002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.request().upload_data_stream->AppendChunk(
19022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kUploadData, kUploadDataSize, false);
19032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.RunPreTestSetup();
19052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.AddData(&data);
19062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(helper.StartDefaultTest());
19072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
19092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.request().upload_data_stream->AppendChunk(
19102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kUploadData, kUploadDataSize, false);
19113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
19122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.request().upload_data_stream->AppendChunk(
19132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kUploadData, kUploadDataSize, true);
19142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.FinishDefaultTest();
19162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.VerifyDataConsumed();
19172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string expected_response;
19192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_response += kUploadData;
19202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_response += kUploadData;
19212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_response += kUploadData;
19222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
19262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected_response, out.response_data);
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a POST without any post data works.
19307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, NullPost) {
1931a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup the request
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo request;
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.method = "POST";
19352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request.url = GURL(kRequestUrl);
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create an empty UploadData.
19372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request.upload_data_stream = NULL;
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // When request.upload_data_stream is NULL for post, content-length is
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // expected to be 0.
1941116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyHeaderBlock> req_block(
1942116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructPostHeaderBlock(kRequestUrl, 0));
1943116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> req(
1944116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
1945a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
19517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a simple POST works.
19717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
1972a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
19732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create an empty UploadDataStream.
19742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedVector<UploadElementReader> element_readers;
197568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  UploadDataStream stream(element_readers.Pass(), 0);
19762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup the request
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo request;
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.method = "POST";
19807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  request.url = GURL(kRequestUrl);
19812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request.upload_data_stream = &stream;
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint64 kContentLength = 0;
1984a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1985116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyHeaderBlock> req_block(
1986116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructPostHeaderBlock(kRequestUrl, kContentLength));
1987116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> req(
1988116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdySyn(1, *req_block, LOWEST, false, true));
1989a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
19957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// While we're doing a post, the server sends the reply before upload completes.
20145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) {
20155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
20167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req, 0),
20195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CreateMockWrite(*body, 3),
20205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
20215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
20225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MockRead reads[] = {
20235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CreateMockRead(*resp, 1),
20245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CreateMockRead(*body, 2),
20255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MockRead(ASYNC, 0, 4)  // EOF
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Write the request headers, and read the complete response
20295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // while still waiting for chunked request data.
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
20325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
20335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     DEFAULT_PRIORITY,
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.SetDeterministic();
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddDeterministicData(&data);
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(helper.StartDefaultTest());
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Process the request headers, SYN_REPLY, and response body.
20425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The request body is still in flight.
20435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  data.RunFor(3);
20445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
20455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const HttpResponseInfo* response = helper.trans()->GetResponseInfo();
20465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
20475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
20485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Finish sending the request body.
20495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  helper.request().upload_data_stream->AppendChunk(
20505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      kUploadData, kUploadDataSize, true);
20515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  data.RunFor(2);
20525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
20535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string response_body;
20545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(OK, ReadTransaction(helper.trans(), &response_body));
20555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(kUploadData, response_body);
20565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  helper.VerifyDataConsumed();
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The client upon cancellation tries to send a RST_STREAM frame. The mock
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// socket causes the TCP write to return zero. This test checks that the client
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// tries to queue up the RST_STREAM frame again.
20627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
206390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
206490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> rst(
206690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(SYNCHRONOUS, 0, 0, 2),
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp.get(), 1, ASYNC),
20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0, 4)  // EOF
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
20812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.SetDeterministic();
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddDeterministicData(&data);
20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetStop(2);
20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.Run();
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.ResetTrans();
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetStop(20);
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.Run();
20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that the transaction doesn't crash when we don't have a reply.
21037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
21047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads), NULL, 0);
21112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
2115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that the transaction doesn't crash when we get two replies on the same
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stream ID. See http://crbug.com/45639.
21207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
212190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
212290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
21245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
2125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req),
2127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*rst),
2128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
21317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback.WaitForResult();
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, rv);
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response = trans->GetResponseInfo();
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(response != NULL);
2157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response->headers.get() != NULL);
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response->was_fetched_via_spdy);
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_data;
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = ReadTransaction(trans, &response_data);
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
2167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct the request.
2168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
2169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
2171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
2173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req),
2174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*rst),
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char* const headers[] = {
2178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "transfer-encoding", "chunked"
2179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(
2181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1));
2182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(
2183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp),
2186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body),
2187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(1, reads, arraysize(reads),
2191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
2192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
21932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
2194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunToCompletion(&data);
2195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out = helper.output();
2196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
21972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.session()->spdy_session_pool()->CloseAllSessions();
21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
2203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct the request.
220490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
220590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
2207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
2210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*rst),
22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char* const headers[] = {
2215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "transfer-encoding", "chunked"
2216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> push(
2218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2,
2219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   2, 1, "http://www.google.com/1"));
2220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
2223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*push),
2224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body),
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
22302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
2232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunToCompletion(&data);
2233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out = helper.output();
2234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, out.rv);
2235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello!", out.response_data);
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.session()->spdy_session_pool()->CloseAllSessions();
2239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
2240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
2243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct the request.
2244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
2245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req),
2248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp),
2253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // This following read isn't used by the test, except during the
2254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // RunUntilIdle() call at the end since the SpdySession survives the
2255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // HttpNetworkTransaction and still tries to continue Read()'ing.  Any
2256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // MockRead will do here.
2257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
2258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads),
2261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                writes, arraysize(writes));
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
2265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
2266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
2267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
2270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
2271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
2272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
2273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.ResetTrans();  // Cancel the transaction.
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // MockClientSocketFactory) are still alive.
22773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
2278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataNotConsumed();
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verify that the client sends a Rst Frame upon cancelling the stream.
2282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
2283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
2284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> rst(
2286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
2288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0, SYNCHRONOUS),
2289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*rst, 2, SYNCHRONOUS),
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1, ASYNC),
2295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 3)  // EOF
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(),
2303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     GetParam(), NULL);
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.SetDeterministic();
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddDeterministicData(&data);
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
2312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
2313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.SetStop(2);
2316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.Run();
2317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.ResetTrans();
2318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.SetStop(20);
2319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.Run();
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
2322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verify that the client can correctly deal with the user callback attempting
2325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// to start another transaction on a session that is closing down. See
2326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// http://crbug.com/47455
2327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
2328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
2329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
2331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes2[] = { CreateMockWrite(*req) };
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The indicated length of this frame is longer than its actual length. When
2334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // the session receives an empty frame after this one, it shuts down the
2335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // session, and calls the read callback with the incomplete data.
2336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const uint8 kGetBodyFrame2[] = {
2337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    0x00, 0x00, 0x00, 0x01,
2338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    0x01, 0x00, 0x00, 0x07,
2339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    'h', 'e', 'l', 'l', 'o', '!',
2340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 2),
2345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 3),  // Force a pause
2346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch             arraysize(kGetBodyFrame2), 4),
2348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 5),  // Force a pause
2349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 6),  // EOF
2350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads2[] = {
2352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 2),
2353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 3),  // EOF
23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
2357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
2358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data2(1, reads2, arraysize(reads2),
2359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          writes2, arraysize(writes2));
23602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
23622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
2364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
2365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data2);
23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction with basic parameters.
23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback.WaitForResult();
23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int kSize = 3000;
2375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = trans->Read(
2377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      buf.get(),
2378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSize,
2379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
2380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 helper.session()));
2381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // This forces an err_IO_pending, which sets the callback.
2382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.CompleteRead();
2383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // This finishes the read.
2384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.CompleteRead();
2385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
2386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verify that the client can correctly deal with the user callback deleting the
2389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// transaction. Failures will usually be valgrind errors. See
2390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// http://crbug.com/46925
2391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
2392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
2393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp.get(), 2),
2400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 3),  // Force a pause
2401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body.get(), 4),
2402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 5),  // EOF
24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
2406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
24072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
24092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
2411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction with basic parameters.
24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
2418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Setup a user callback which will delete the session, and clear out the
2421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // memory holding the stream object. Note that the callback deletes trans.
2422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int kSize = 3000;
2423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = trans->Read(
2425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      buf.get(),
2426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSize,
2427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
2428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 base::Unretained(&helper)));
2429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING, rv);
2430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.CompleteRead();
24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Finish running rest of tasks.
24333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Send a spdy request to www.google.com that gets redirected to www.foo.com.
2438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
2439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
2440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*headers)["user-agent"] = "";
24421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (*headers)["accept-encoding"] = "gzip, deflate";
2443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
2444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*headers2)["user-agent"] = "";
24461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (*headers2)["accept-encoding"] = "gzip, deflate";
24477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Setup writes/reads to www.google.com
2449116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> req(
2450116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
2451116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> req2(
2452116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
2453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
2454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 1),
2456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 2),
2459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 3)  // EOF
2460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Setup writes/reads to www.foo.com
2463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes2[] = {
2466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
2467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads2[] = {
2469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 2),
2470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body2, 3),
2471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 4)  // EOF
2472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
2474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
2475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data2(reads2, arraysize(reads2),
2476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          writes2, arraysize(writes2));
24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestDelegate d;
2480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  {
2481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SpdyURLRequestContext spdy_url_request_context(
2482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        GetParam().protocol,
2483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        false  /* force_spdy_over_ssl*/,
2484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        true  /* force_spdy_always */);
248503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    scoped_ptr<URLRequest> r(
248603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        spdy_url_request_context.CreateRequest(GURL("http://www.google.com/"),
248703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                               DEFAULT_PRIORITY,
248803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                               &d,
248903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                               NULL));
2490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    spdy_url_request_context.socket_factory().
2491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        AddSocketDataProvider(&data);
2492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    spdy_url_request_context.socket_factory().
2493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        AddSocketDataProvider(&data2);
24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    d.set_quit_on_redirect(true);
249603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    r->Start();
24973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::RunLoop().Run();
24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(1, d.received_redirect_count());
25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
250103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    r->FollowDeferredRedirect();
25023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::RunLoop().Run();
2503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(1, d.response_started_count());
2504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_FALSE(d.received_data_before_response());
250503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    EXPECT_EQ(net::URLRequestStatus::SUCCESS, r->status().status());
2506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string contents("hello!");
2507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(contents, d.data_received());
2508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof());
2510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
2511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data2.at_read_eof());
2512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data2.at_write_eof());
2513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Send a spdy request to www.google.com. Get a pushed stream that redirects to
2516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// www.foo.com.
2517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
2518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
2519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*headers)["user-agent"] = "";
25211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (*headers)["accept-encoding"] = "gzip, deflate";
25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Setup writes/reads to www.google.com
2524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
2525116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdySyn(1, *headers, LOWEST, false, true));
2526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rep(
2528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPush(NULL,
2529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        0,
2530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        2,
2531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        1,
2532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        "http://www.google.com/foo.dat",
2533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        "301 Moved Permanently",
2534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        "http://www.foo.com/index.php"));
2535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
2537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
2538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 1),
2540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*rst, 6),
2541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 2),
2544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*rep, 3),
2545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body, 4),
2546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 5),  // Force a pause
2547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 7)  // EOF
25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Setup writes/reads to www.foo.com
2551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
2552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*headers2)["user-agent"] = "";
25541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  (*headers2)["accept-encoding"] = "gzip, deflate";
2555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
2556116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdySyn(1, *headers2, LOWEST, false, true));
2557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes2[] = {
2560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
2561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads2[] = {
2563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 2),
2564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body2, 3),
2565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 5)  // EOF
2566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
2568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
2569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data2(reads2, arraysize(reads2),
2570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          writes2, arraysize(writes2));
25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestDelegate d;
2574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestDelegate d2;
2575cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SpdyURLRequestContext spdy_url_request_context(
2576cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      GetParam().protocol,
2577cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      false  /* force_spdy_over_ssl*/,
2578cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      true  /* force_spdy_always */);
2579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  {
258003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    scoped_ptr<URLRequest> r(
258103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        spdy_url_request_context.CreateRequest(GURL("http://www.google.com/"),
258203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                               DEFAULT_PRIORITY,
258303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                               &d,
258403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                               NULL));
2585eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    spdy_url_request_context.socket_factory().
2586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        AddSocketDataProvider(&data);
25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
258803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    r->Start();
25893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::RunLoop().Run();
25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(0, d.received_redirect_count());
2592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string contents("hello!");
2593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(contents, d.data_received());
25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
259503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    scoped_ptr<URLRequest> r2(
259603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        spdy_url_request_context.CreateRequest(
259703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            GURL("http://www.google.com/foo.dat"),
259803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            DEFAULT_PRIORITY,
259903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            &d2,
260003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            NULL));
2601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    spdy_url_request_context.socket_factory().
2602eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        AddSocketDataProvider(&data2);
26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    d2.set_quit_on_redirect(true);
260503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    r2->Start();
26063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::RunLoop().Run();
2607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(1, d2.received_redirect_count());
26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
260903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    r2->FollowDeferredRedirect();
26103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    base::RunLoop().Run();
2611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(1, d2.response_started_count());
2612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_FALSE(d2.received_data_before_response());
261303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2->status().status());
2614eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string contents2("hello!");
2615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(contents2, d2.data_received());
2616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.CompleteRead();
2618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data2.CompleteRead();
2619eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof());
2620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
2621eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data2.at_read_eof());
2622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data2.at_write_eof());
26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
2626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
262790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
2629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
2631eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2638eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
2640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
2642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
2643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
2644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
2645eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
2648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
2649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 5),
2651eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
2655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
2656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed");
2657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
2659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunServerPushTest(&data,
2660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response,
2661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response2,
2662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    expected_push_result);
26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
2665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
2666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
2669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
2670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
26727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
2674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
267590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
2677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
2679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2687eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
2688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
2690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
2691eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
2692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
2693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2695eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 2),
2696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 3),
2697eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 5),
2699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
2703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
2704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed");
2705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
2707eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunServerPushTest(&data,
2708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response,
2709eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response2,
2710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    expected_push_result);
27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2712eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
2713eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
2714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
2717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
2718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2719eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
27207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2721eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
2722eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
272390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2724eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = { CreateMockWrite(*stream1_syn, 1), };
27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2726eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2727eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2728eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2729eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2730eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2731eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
2732eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2733eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
2734eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
2735eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
2736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
2737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
2738eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2739eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2741eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
2742eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
2743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 4),
2744eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2745eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2748eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
2749eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
2750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed");
2751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
2752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
2753eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunServerPushTest(&data,
2754eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response,
2755eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response2,
2756eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    expected_push_result);
27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2758eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
2759eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
2760eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2762eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
2763eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
2764eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2767eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
2768eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
276990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
2771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
2773eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2778eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2779eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
2782eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
2784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_rst(
2785eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
2788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
2789eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_rst, 4),
2790eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
2795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
27962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
2798eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
2800eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
2801eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2804eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction with basic parameters.
28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
2809eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
2810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv);
28115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2812eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
2813eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof()) << "Read count: "
2814eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_count()
2815eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << " Read index: "
2816eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_index();
2817eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof()) << "Write count: "
2818eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_count()
2819eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << " Write index: "
2820eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_index();
28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2822eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
2823eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response = *trans->GetResponseInfo();
2824eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
2825eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2828eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verify that we don't leak streams and that we properly send a reset
2829eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// if the server pushes the same stream twice.
2830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
2831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
283290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2833eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
2834eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
2835eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream3_rst(
2836eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
2837eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2838eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
2839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream3_rst, 5),
28405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
28415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2842eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2843eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2844eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2845eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2846eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2847eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
2848eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2849eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
2850eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
2851eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
2852eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
2853eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
2854eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2855eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream3_syn(spdy_util_.ConstructSpdyPush(NULL,
2856eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2857eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    4,
2858eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2859eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
28605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2861eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
2862eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
2863eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream3_syn, 4),
2864eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 6, SYNCHRONOUS),
2865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 7),
2866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 8),  // Force a pause
28675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
28685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2869eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
2870eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
2871eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed");
28725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
28735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
2874eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunServerPushTest(&data,
2875eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response,
2876eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response2,
2877eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    expected_push_result);
28785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2879eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
2880eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
2881eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
28825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2883eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
2884eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
2885eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
28865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2888eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
2889eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
289090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
2892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
2893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2894eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
2895eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
28965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2897eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2898eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2899eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2900eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2901eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2902eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
2903eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2904eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
2905eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static const char kPushedData[] = "pushed my darling hello my baby";
2906eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body_base(
2907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
2908eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
2909eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const size_t kChunkSize = strlen(kPushedData) / 4;
2910eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body1(
2911eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body2(
2913eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2914eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body3(
2915eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    kChunkSize, false));
2917eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body4(
2918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2919eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    stream2_body_base->size() - 3 * kChunkSize, false));
29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2921eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
2922eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
2923eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body1, 4),
2924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body2, 5),
2925eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body3, 6),
2926eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body4, 7),
2927eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 8, SYNCHRONOUS),
2928eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 9),  // Force a pause
29295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
29305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2931eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
2932eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
2933eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed my darling hello my baby");
29345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
29355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
2936eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunServerPushTest(&data, &response, &response2, kPushedData);
29375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2938eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
2939eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
2940eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
29415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2942eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
2943eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
2944eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
29455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2947eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
2948eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
2949eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2950eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
2951eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
29525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
2953eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
29545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2955eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2956eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2957eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2958eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2959eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2960eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2961eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
2962eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2963eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
2964eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static const char kPushedData[] = "pushed my darling hello my baby";
2965eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body_base(
2966eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
2967eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
2968eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const size_t kChunkSize = strlen(kPushedData) / 4;
2969eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body1(
2970eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2971eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body2(
2972eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2973eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body3(
2974eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2975eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    kChunkSize, false));
2976eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body4(
2977eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2978eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    stream2_body_base->size() - 3 * kChunkSize, false));
29795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2980eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
2981eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
2982eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body1, 4),
2983eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body2, 5),
2984eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
2985eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body3, 7),
2986eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body4, 8),
2987eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS),
2988eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 10)  // Force a pause.
29895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
29905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2991eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
2992eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
29935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
29945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
2995eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunServerPushTest(&data, &response, &response2, kPushedData);
29965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2997eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
2998eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
2999eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
30005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3001eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
3002eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
3003eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
30045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3006eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
30075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (spdy_util_.spdy_version() == SPDY4) {
30086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // PUSH_PROMISE with stream id 0 is connection-level error.
30096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // TODO(baranovich): Test session going away.
30105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
30115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
30126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
3013eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
301490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3015eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
3016eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
3017eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_rst(
3018eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
30195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
3020eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
3021eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream2_rst, 4),
30225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
30235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame>
3025eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3026eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
3027eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3028eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
3029eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
3030eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
3031eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
30325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
3033eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
3034eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
3035eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 4),
3036eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 5)  // Force a pause
30375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
30385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
30405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
30412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
30425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
30435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3044eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
3045eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
30467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3047eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
30485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3049eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction with basic parameters.
3050eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
3051eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
3052eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
3053eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
3054eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
3055eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv);
30567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3057eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
3058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3059eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_count()
3060eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << " Read index: "
3061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_index();
3062eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_count()
3064eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << " Write index: "
3065eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_index();
30665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3067eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
3068eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response = *trans->GetResponseInfo();
3069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
3070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
30715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
3074eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
307590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
3077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
3078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_rst(
3079eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
30805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
3081eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
3082eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream2_rst, 4),
30835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
30845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame>
3086eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
30875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame>
3088eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3089eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
3090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
3091eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    9,
3092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
30935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
3094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
3095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
3096eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 4),
3097eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 5),  // Force a pause
30985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
30995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
31015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
31022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
31035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
31047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
3106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
31075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
31095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction with basic parameters.
3111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
3112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
3113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
3114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
3115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
3116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv);
31175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
3119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_count()
3121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << " Read index: "
3122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_index();
3123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_count()
3125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << " Write index: "
3126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_index();
31275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
3129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response = *trans->GetResponseInfo();
3130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
3131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
31325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
313590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> stream1_syn(
313690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
31377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> stream1_body(
31387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, true));
3139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_rst(
3140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
31415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
31425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*stream1_syn, 1),
3143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream2_rst, 4),
31445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
31455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame>
31477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> incomplete_headers(new SpdyHeaderBlock());
3149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*incomplete_headers)["hello"] = "bye";
3150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*incomplete_headers)[spdy_util_.GetStatusKey()] = "200 OK";
3151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*incomplete_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
31526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  scoped_ptr<SpdyFrame> stream2_syn(spdy_util_.ConstructInitialSpdyPushFrame(
31536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      incomplete_headers.Pass(), 2, 1));
31545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
31555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*stream1_reply, 2),
31565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*stream2_syn, 3),
3157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 4),
3158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 5)  // Force a pause
31595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
31605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
31625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
3163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
31657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
3167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
31685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
31705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction with basic parameters.
3172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
3173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
3174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
3175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
3176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
3177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv);
3178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
3179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_count()
3181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << " Read index: "
3182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_index();
3183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_count()
3185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << " Write index: "
3186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_index();
31875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the SYN_REPLY.
3189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response = *trans->GetResponseInfo();
3190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response.headers.get() != NULL);
31915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
31925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verify that various SynReply headers parse correctly through the
3195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// HTTP layer.
3196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
3197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  struct SynReplyHeadersTests {
3198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int num_headers;
3199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const char* extra_headers[5];
3200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SpdyHeaderBlock expected_headers;
3201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } test_cases[] = {
3202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // This uses a multi-valued cookie header.
3203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { 2,
3204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      { "cookie", "val1",
3205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        "cookie", "val2",  // will get appended separated by NULL
3206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        NULL
3207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      },
3208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    },
3209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // This is the minimalist set of headers.
3210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { 0,
3211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      { NULL },
3212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    },
3213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Headers with a comma separated list.
3214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { 1,
3215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      { "cookie", "val1,val2",
3216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        NULL
3217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      },
3218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
32195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
32205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[0].expected_headers["cookie"] = "val1";
32227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[0].expected_headers["cookie"] += '\0';
32237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[0].expected_headers["cookie"] += "val2";
32247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[0].expected_headers["hello"] = "bye";
32257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[0].expected_headers["status"] = "200";
32267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
32277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[1].expected_headers["hello"] = "bye";
32287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[1].expected_headers["status"] = "200";
32297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
32307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[2].expected_headers["cookie"] = "val1,val2";
32317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[2].expected_headers["hello"] = "bye";
32327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[2].expected_headers["status"] = "200";
3233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
3234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (spdy_util_.spdy_version() < SPDY4) {
3235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // SPDY4/HTTP2 eliminates use of the :version header.
3236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    test_cases[0].expected_headers["version"] = "HTTP/1.1";
3237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    test_cases[1].expected_headers["version"] = "HTTP/1.1";
3238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    test_cases[2].expected_headers["version"] = "HTTP/1.1";
3239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
32407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
32415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
32425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdyFrame> req(
324390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
32445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite writes[] = { CreateMockWrite(*req) };
32455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdyFrame> resp(
32477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
32485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 test_cases[i].num_headers,
32495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 1));
32507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
32515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead reads[] = {
32525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*resp),
32535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*body),
32545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockRead(ASYNC, 0, 0)  // EOF
32555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
32565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelayedSocketData data(1, reads, arraysize(reads),
32585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           writes, arraysize(writes));
32592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
32605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       BoundNetLog(), GetParam(), NULL);
32615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.RunToCompletion(&data);
32625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionHelperResult out = helper.output();
32635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, out.rv);
32655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
32665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("hello!", out.response_data);
32675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
32695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(headers.get() != NULL);
32705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* iter = NULL;
32717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    std::string name, value;
32727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SpdyHeaderBlock header_block;
32735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
32747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (header_block[name].empty()) {
32757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        header_block[name] = value;
32767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      } else {
32777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        header_block[name] += '\0';
32787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        header_block[name] += value;
32797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
32805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
32817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(test_cases[i].expected_headers, header_block);
32825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that various SynReply headers parse vary fields correctly
32865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// through the HTTP layer, and the response matches the request.
32877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
32885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Modify the following data to change/add test cases:
32895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct SynReplyTests {
32905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool vary_matches;
32915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_headers[2];
32925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* extra_headers[2][16];
32935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } test_cases[] = {
32945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Test the case of a multi-valued cookie.  When the value is delimited
32955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // with NUL characters, it needs to be unfolded into multiple headers.
32965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
32975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
32985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { 1, 4 },
32995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { { "cookie",   "val1,val2",
33005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        },
33027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        { "vary",     "cookie",
33037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetStatusKey(), "200",
33047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetPathKey(),      "/index.php",
33057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetVersionKey(), "HTTP/1.1",
33065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
33085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
33095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }, {    // Multiple vary fields.
33105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
33115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { 2, 5 },
33125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { { "friend",   "barney",
33135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "enemy",    "snaggletooth",
33145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        },
33167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        { "vary",     "friend",
33175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "vary",     "enemy",
33187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetStatusKey(), "200",
33197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetPathKey(),      "/index.php",
33207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetVersionKey(), "HTTP/1.1",
33215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
33235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
33245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }, {    // Test a '*' vary field.
33255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
33265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { 1, 4 },
33275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { { "cookie",   "val1,val2",
33285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        },
33307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        { "vary",     "*",
33317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetStatusKey(), "200",
33327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetPathKey(),      "/index.php",
33337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetVersionKey(), "HTTP/1.1",
33345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
33365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
33375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }, {    // Multiple comma-separated vary fields.
33385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
33395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { 2, 4 },
33405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { { "friend",   "barney",
33415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "enemy",    "snaggletooth",
33425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        },
33447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        { "vary",     "friend,enemy",
33457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetStatusKey(), "200",
33467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetPathKey(),      "/index.php",
33477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetVersionKey(), "HTTP/1.1",
33485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
33505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
33515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
33525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
33535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
33555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Construct the request.
33565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdyFrame> frame_req(
335790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
335890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    test_cases[i].num_headers[0],
335990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    false, 1, LOWEST, true));
33605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite writes[] = {
33625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockWrite(*frame_req),
33635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
33645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Construct the reply.
3366116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    SpdyHeaderBlock reply_headers;
3367116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    AppendToHeaderBlock(test_cases[i].extra_headers[1],
3368116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        test_cases[i].num_headers[1],
3369116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        &reply_headers);
33705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdyFrame> frame_reply(
3371116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        spdy_util_.ConstructSpdyReply(1, reply_headers));
33725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
33745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead reads[] = {
33755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*frame_reply),
33765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*body),
33775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockRead(ASYNC, 0, 0)  // EOF
33785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
33795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Attach the headers to the request.
33815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int header_count = test_cases[i].num_headers[0];
33825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo request = CreateGetRequest();
33845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int ct = 0; ct < header_count; ct++) {
33855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char* header_key = test_cases[i].extra_headers[0][ct * 2];
33865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
33875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request.extra_headers.SetHeader(header_key, header_value);
33885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
33895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelayedSocketData data(1, reads, arraysize(reads),
33915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           writes, arraysize(writes));
33922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
33935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       BoundNetLog(), GetParam(), NULL);
33945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.RunToCompletion(&data);
33955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionHelperResult out = helper.output();
33965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, out.rv) << i;
33985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
33995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("hello!", out.response_data) << i;
34005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Test the response information.
34025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(out.response_info.response_time >
34035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                out.response_info.request_time) << i;
34045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta test_delay = out.response_info.response_time -
34055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 out.response_info.request_time;
34065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta min_expected_delay;
34075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    min_expected_delay.FromMilliseconds(10);
34085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GT(test_delay.InMillisecondsF(),
34095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              min_expected_delay.InMillisecondsF()) << i;
34105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(out.response_info.vary_data.is_valid(),
34115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              test_cases[i].vary_matches) << i;
34125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check the headers.
34145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
34155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(headers.get() != NULL) << i;
34165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* iter = NULL;
34175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name, value, lines;
34185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
34195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lines.append(name);
34205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lines.append(": ");
34215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lines.append(value);
34225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lines.append("\n");
34235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
34245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Construct the expected header reply string.
3426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::string expected_reply =
3427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        spdy_util_.ConstructSpdyReplyString(reply_headers);
3428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_EQ(expected_reply, lines) << i;
34295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
34305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
34315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that we don't crash on invalid SynReply responses.
34337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
34345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct InvalidSynReplyTests {
34355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_headers;
34365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* headers[10];
34375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } test_cases[] = {
34385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SYN_REPLY missing status header
34395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { 4,
34405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { "cookie", "val1",
34415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "cookie", "val2",
34427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        spdy_util_.GetPathKey(), "/index.php",
34437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        spdy_util_.GetVersionKey(), "HTTP/1.1",
34445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NULL
34455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      },
34465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
34475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SYN_REPLY missing version header
34485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { 2,
34497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      { "status", "200",
34507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        spdy_util_.GetPathKey(), "/index.php",
34515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NULL
34525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      },
34535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
34545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SYN_REPLY with no headers
34555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { 0, { NULL }, },
34565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
34575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
34595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdyFrame> req(
346090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame> rst(
3462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
34635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite writes[] = {
34645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockWrite(*req),
3465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateMockWrite(*rst),
34665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
34675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3468116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Construct the reply.
3469116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    SpdyHeaderBlock reply_headers;
3470116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    AppendToHeaderBlock(
3471116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        test_cases[i].headers, test_cases[i].num_headers, &reply_headers);
3472116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, reply_headers));
34735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead reads[] = {
34745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*resp),
34755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockRead(ASYNC, 0, 0)  // EOF
34765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
34775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelayedSocketData data(1, reads, arraysize(reads),
34795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           writes, arraysize(writes));
34802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
34815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       BoundNetLog(), GetParam(), NULL);
34825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.RunToCompletion(&data);
34835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionHelperResult out = helper.output();
3484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
34855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
34865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
34875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that we don't crash on some corrupt frames.
348923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// TODO(jgraettinger): SPDY4 and up treats a header decompression failure as a
349023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// connection error. I'd like to backport this behavior to SPDY3 as well.
34917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
349223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (spdy_util_.spdy_version() >= SPDY4) {
349323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
349423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
34955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the length field that's too short.
34965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> syn_reply_wrong_length(
34977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
34987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t right_size =
3500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (spdy_util_.spdy_version() < SPDY4) ?
3501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize() :
3502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      syn_reply_wrong_length->size();
3503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t wrong_size = right_size - 4;
35042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  test::SetFrameLength(syn_reply_wrong_length.get(),
3505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       wrong_size,
35067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       spdy_util_.spdy_version());
35075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct SynReplyTests {
35095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SpdyFrame* syn_reply;
35105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } test_cases[] = {
35115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { syn_reply_wrong_length.get(), },
35125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
35135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
35155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdyFrame> req(
351690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3517ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    scoped_ptr<SpdyFrame> rst(
3518ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3519ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockWrite writes[] = {
3520ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateMockWrite(*req),
3521ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateMockWrite(*rst),
35225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
35235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
35255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead reads[] = {
35262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size),
35275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*body),
35285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockRead(ASYNC, 0, 0)  // EOF
35295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
35305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelayedSocketData data(1, reads, arraysize(reads),
35325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           writes, arraysize(writes));
35332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
35345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       BoundNetLog(), GetParam(), NULL);
35355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.RunToCompletion(&data);
35365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionHelperResult out = helper.output();
35375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
35385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
35395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
354123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// SPDY4 treats a header decompression failure as a connection-level error.
354223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionErrorSpdy4) {
354323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (spdy_util_.spdy_version() < SPDY4) {
354423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
354523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
354623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // This is the length field that's too short.
354723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_ptr<SpdyFrame> syn_reply_wrong_length(
354823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
354923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
355023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  size_t right_size =
35514ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize();
355223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  size_t wrong_size = right_size - 4;
355323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  test::SetFrameLength(syn_reply_wrong_length.get(),
355423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                       wrong_size,
355523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                       spdy_util_.spdy_version());
355623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
355723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
355823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3559f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3560f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3561f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
356223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
356323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
356423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  MockRead reads[] = {
35654ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    MockRead(ASYNC, syn_reply_wrong_length->data(),
35664ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch             syn_reply_wrong_length->size() - 4),
356723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  };
356823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
356923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
357023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                         writes, arraysize(writes));
357123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
357223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
357323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  helper.RunToCompletion(&data);
357423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  TransactionHelperResult out = helper.output();
3575f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3576f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
3577f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3578f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) {
3579f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (GetParam().protocol < kProtoSPDY4) {
3580f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Decompression failures are a stream error in SPDY3 and above.
3581f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
3582f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
3583f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> req(
3584f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3585f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3586f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3587f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3588f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3589f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Read HEADERS with corrupted payload.
3590f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3591f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  memset(resp->data() + 12, 0xff, resp->size() - 12);
3592f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockRead reads[] = {CreateMockRead(*resp)};
3593f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3594f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
3595f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  NormalSpdyTransactionHelper helper(
3596f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3597f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  helper.RunToCompletion(&data);
3598f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  TransactionHelperResult out = helper.output();
3599f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
3600f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
3601f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3602f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) {
3603f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> req(
3604f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3605f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3606f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      0, GOAWAY_PROTOCOL_ERROR, "Framer error: 1 (INVALID_CONTROL_FRAME)."));
3607f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*goaway)};
3608f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3609f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Read WINDOW_UPDATE with incorrectly-sized payload.
3610f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // TODO(jgraettinger): SpdyFramer signals this as an INVALID_CONTROL_FRAME,
3611f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // which is mapped to a protocol error, and not a frame size error.
3612f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> bad_window_update(
3613f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      spdy_util_.ConstructSpdyWindowUpdate(1, 1));
3614f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  test::SetFrameLength(bad_window_update.get(),
3615f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       bad_window_update->size() - 1,
3616f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       spdy_util_.spdy_version());
3617f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockRead reads[] = {CreateMockRead(*bad_window_update)};
3618f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3619f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
3620f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  NormalSpdyTransactionHelper helper(
3621f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
3622f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  helper.RunToCompletion(&data);
3623f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  TransactionHelperResult out = helper.output();
362423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
362523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
362623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
36275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that we shutdown correctly on write errors.
36287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, WriteError) {
362990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
363090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
36315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
3632f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // We'll write 10 bytes successfully
3633f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MockWrite(ASYNC, req->data(), 10, 0),
3634f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // Followed by ERROR!
3635f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MockWrite(ASYNC, ERR_FAILED, 1),
3636f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // Session drains and attempts to write a GOAWAY: Another ERROR!
3637f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MockWrite(ASYNC, ERR_FAILED, 2),
36385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
36395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  MockRead reads[] = {
3641f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      MockRead(ASYNC, 0, 3)  // EOF
36428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  };
36438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
36448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
36458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                               writes, arraysize(writes));
36468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
36472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
36485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
36498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  helper.SetDeterministic();
36508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  helper.RunPreTestSetup();
36518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  helper.AddDeterministicData(&data);
36528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  EXPECT_TRUE(helper.StartDefaultTest());
36538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  data.RunFor(2);
36548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  helper.FinishDefaultTest();
36558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
36568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  EXPECT_TRUE(!data.at_read_eof());
36575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
36585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_FAILED, out.rv);
36595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
36605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that partial writes work.
36627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
36635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Chop the SYN_STREAM frame into 5 chunks.
366490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
366590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
36665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kChunks = 5;
3667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
36685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
36707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
36715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
36725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
36735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
36745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
36755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
36765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(kChunks, reads, arraysize(reads),
36785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes.get(), kChunks);
36792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
36805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
36815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
36825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
36835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
36845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
36855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
36865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
36875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In this test, we enable compression, but get a uncompressed SynReply from
36895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the server.  Verify that teardown is all clean.
36907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
369123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (spdy_util_.spdy_version() >= SPDY4) {
369223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // HPACK doesn't use deflate compression.
369323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
369423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
36955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> compressed(
369690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
3697f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
3698f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      0, GOAWAY_COMPRESSION_ERROR, "Framer error: 5 (DECOMPRESS_FAILURE)."));
3699f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockWrite writes[] = {CreateMockWrite(*compressed), CreateMockWrite(*goaway)};
37005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
37027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
37035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
37045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
37055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
37065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
37085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
37097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SpdySessionDependencies* session_deps =
37107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      CreateSpdySessionDependencies(GetParam());
37112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps->enable_compression = true;
37122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
37132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), session_deps);
37145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
37155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
3716f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv);
37175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.Reset();
37185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
37195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that the NetLog contains good data for a simple GET request.
37217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, NetLog) {
37225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* const kExtraHeaders[] = {
37235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "user-agent",   "Chrome",
37245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
372590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
372690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
37275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req) };
37285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
37307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
37315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
37325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
37335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
37345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
37355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
37365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CapturingBoundNetLog log;
37385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
37405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
37415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
37422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     DEFAULT_PRIORITY,
37435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     log.bound(), GetParam(), NULL);
37445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
37455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
37465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
37475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
37485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
37495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that the NetLog was filled reasonably.
37515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This test is intentionally non-specific about the exact ordering of the
37525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // log; instead we just check to make sure that certain events exist, and that
37535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // they are in the right order.
37545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::CapturingNetLog::CapturedEntryList entries;
37555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  log.GetEntries(&entries);
37565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(0u, entries.size());
37585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pos = 0;
37595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos = net::ExpectLogContainsSomewhere(entries, 0,
37605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
37615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_BEGIN);
37625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
37635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
37645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_END);
37655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
37665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
37675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_BEGIN);
37685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
37695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
37705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_END);
37715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
37725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
37735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_BEGIN);
37745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
37755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
37765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_END);
37775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that we logged all the headers correctly
37795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos = net::ExpectLogContainsSomewhere(
37805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entries, 0,
37815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
37825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_NONE);
37835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::ListValue* header_list;
37855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(entries[pos].params.get());
37865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
37875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> expected;
37897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  expected.push_back(std::string(spdy_util_.GetHostKey()) + ": www.google.com");
37907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
37917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": http");
37927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
37935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back("user-agent: Chrome");
3794c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (spdy_util_.spdy_version() < SPDY4) {
3795c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // SPDY4/HTTP2 eliminates use of the :version header.
3796c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
3797c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
37985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(expected.size(), header_list->GetSize());
37995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<std::string>::const_iterator it = expected.begin();
38005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != expected.end();
38015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
38025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringValue header(*it);
38035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_NE(header_list->end(), header_list->Find(header)) <<
38045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Header not found: " << *it;
38055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
38065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
38075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Since we buffer the IO from the stream to the renderer, this test verifies
38095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that when we read out the maximum amount of data (e.g. we received 50 bytes
38105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on the network, but issued a Read for only 5 of those bytes) that the data
38115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// flow still works correctly.
38127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, BufferFull) {
38137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
38145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
381590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
381690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
38175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req) };
38185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 2 data frames in a single read.
38205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame_1(
38215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
38225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame_2(
38235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
38245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdyFrame* data_frames[2] = {
38255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame_1.get(),
38265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame_2.get(),
38275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
38285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char combined_data_frames[100];
38295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int combined_data_frames_len =
38305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CombineFrames(data_frames, arraysize(data_frames),
38315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    combined_data_frames, arraysize(combined_data_frames));
38325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> last_frame(
38335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
38345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
38365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
38375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
38385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING),  // Force a pause
38395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
38405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING),  // Force a pause
38415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*last_frame),
38425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
38435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
38445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
38465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
38475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
38495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
38515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
38525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
38535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
38545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
38555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
38565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
38575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
38585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
38605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback.WaitForResult();
38615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(out.rv, OK);
38625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response = trans->GetResponseInfo();
3864868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response->headers.get() != NULL);
38655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response->was_fetched_via_spdy);
38665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response->headers->GetStatusLine();
38675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response;  // Make a copy so we can verify.
38685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read Data
38705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback read_callback;
38715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string content;
38735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
38745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read small chunks at a time.
38755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kSmallReadSize = 3;
38765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3877868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
38785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == net::ERR_IO_PENDING) {
38795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.CompleteRead();
38805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = read_callback.WaitForResult();
38815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
38825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv > 0) {
38835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content.append(buf->data(), rv);
38845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (rv < 0) {
38855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
38865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
38875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv > 0);
38885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_data.swap(content);
38905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
38925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MockClientSocketFactory) are still alive.
38933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
38945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that we consumed all test data.
38965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
38975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
38995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
39005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("goodbye world", out.response_data);
39015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
39025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that basic buffering works; when multiple data frames arrive
39045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// at the same time, ensure that we don't notify a read completion for
39055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// each data frame individually.
39067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, Buffering) {
39077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
39085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
390990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
391090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
39115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req) };
39125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 4 data frames in a single read.
39145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame(
39155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
39165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame_fin(
39175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
39185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdyFrame* data_frames[4] = {
39195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get(),
39205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get(),
39215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get(),
39225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame_fin.get()
39235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
39245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char combined_data_frames[100];
39255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int combined_data_frames_len =
39265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CombineFrames(data_frames, arraysize(data_frames),
39275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    combined_data_frames, arraysize(combined_data_frames));
39285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
39305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
39315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
39325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING),  // Force a pause
39335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
39345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
39355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
39365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
39385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
39395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
39415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
39425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
39435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
39445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
39455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
39475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
39485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
39495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
39505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
39525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback.WaitForResult();
39535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(out.rv, OK);
39545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response = trans->GetResponseInfo();
3956868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response->headers.get() != NULL);
39575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response->was_fetched_via_spdy);
39585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response->headers->GetStatusLine();
39595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response;  // Make a copy so we can verify.
39605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read Data
39625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback read_callback;
39635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string content;
39655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reads_completed = 0;
39665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
39675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read small chunks at a time.
39685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kSmallReadSize = 14;
39695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3970868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
39715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == net::ERR_IO_PENDING) {
39725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.CompleteRead();
39735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = read_callback.WaitForResult();
39745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
39755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv > 0) {
39765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(kSmallReadSize, rv);
39775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content.append(buf->data(), rv);
39785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (rv < 0) {
39795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FAIL() << "Unexpected read error: " << rv;
39805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
39815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reads_completed++;
39825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv > 0);
39835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3, reads_completed);  // Reads are: 14 bytes, 14 bytes, 0 bytes.
39855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_data.swap(content);
39875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
39895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MockClientSocketFactory) are still alive.
39903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
39915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that we consumed all test data.
39935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
39945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
39965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
39975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("messagemessagemessagemessage", out.response_data);
39985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
39995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify the case where we buffer data but read it after it has been buffered.
40017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
40027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
40035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
400490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
400590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
40065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req) };
40075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 5 data frames in a single read.
4009116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
40105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame(
40115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
40125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame_fin(
40135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
4014116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const SpdyFrame* frames[5] = {reply.get(), data_frame.get(), data_frame.get(),
4015116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                data_frame.get(), data_frame_fin.get()};
40165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char combined_frames[200];
40175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int combined_frames_len =
40185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CombineFrames(frames, arraysize(frames),
40195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    combined_frames, arraysize(combined_frames));
40205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
40225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, combined_frames, combined_frames_len),
40235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
40245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
40255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
40275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
40285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
40305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
40315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
40325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
40335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
40345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
40365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
40375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
40385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
40395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
40415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback.WaitForResult();
40425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(out.rv, OK);
40435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response = trans->GetResponseInfo();
4045868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response->headers.get() != NULL);
40465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response->was_fetched_via_spdy);
40475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response->headers->GetStatusLine();
40485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response;  // Make a copy so we can verify.
40495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read Data
40515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback read_callback;
40525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string content;
40545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reads_completed = 0;
40555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
40565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read small chunks at a time.
40575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kSmallReadSize = 14;
40585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4059868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
40605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv > 0) {
40615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(kSmallReadSize, rv);
40625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content.append(buf->data(), rv);
40635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (rv < 0) {
40645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FAIL() << "Unexpected read error: " << rv;
40655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
40665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reads_completed++;
40675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv > 0);
40685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3, reads_completed);
40705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_data.swap(content);
40725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
40745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MockClientSocketFactory) are still alive.
40753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
40765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that we consumed all test data.
40785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
40795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
40815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
40825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("messagemessagemessagemessage", out.response_data);
40835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
40845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify the case where we buffer data and close the connection.
40867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
40877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
40885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
408990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
409090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
40915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req) };
40925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All data frames in a single read.
40945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: We don't FIN the stream.
40955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame(
40965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
40975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdyFrame* data_frames[4] = {
40985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get(),
40995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get(),
41005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get(),
41015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get()
41025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
41035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char combined_data_frames[100];
41045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int combined_data_frames_len =
41055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CombineFrames(data_frames, arraysize(data_frames),
41065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    combined_data_frames, arraysize(combined_data_frames));
41077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
41085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
41095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
41105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING),  // Force a wait
41115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
41125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
41135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
41145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
41165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
41175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
41195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
41205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
41215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
41225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
41235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
41255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
41275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
41285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
41295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
41315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback.WaitForResult();
41325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(out.rv, OK);
41335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response = trans->GetResponseInfo();
4135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response->headers.get() != NULL);
41365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response->was_fetched_via_spdy);
41375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response->headers->GetStatusLine();
41385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response;  // Make a copy so we can verify.
41395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read Data
41415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback read_callback;
41425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string content;
41445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reads_completed = 0;
41455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
41465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read small chunks at a time.
41475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kSmallReadSize = 14;
41485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
41505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == net::ERR_IO_PENDING) {
41515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.CompleteRead();
41525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = read_callback.WaitForResult();
41535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
41545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv > 0) {
41555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content.append(buf->data(), rv);
41565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (rv < 0) {
41575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This test intentionally closes the connection, and will get an error.
41585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
41595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
41605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
41615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reads_completed++;
41625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv > 0);
41635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, reads_completed);
41655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_data.swap(content);
41675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
41695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MockClientSocketFactory) are still alive.
41703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
41715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that we consumed all test data.
41735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
41745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
41755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify the case where we buffer data and cancel the transaction.
41777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
41787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
41795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
418090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
418190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> rst(
4183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
4184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockWrite writes[] = {CreateMockWrite(*req), CreateMockWrite(*rst)};
41855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: We don't FIN the stream.
41875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame(
41885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
41895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
41915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
41925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
41935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING),  // Force a wait
41945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*data_frame),
41955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
41965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
41975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
41995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
42005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
42025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
42035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
42045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
42055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
42065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
42075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
42095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
42105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
42115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
42135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback.WaitForResult();
42145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(out.rv, OK);
42155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response = trans->GetResponseInfo();
4217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response->headers.get() != NULL);
42185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response->was_fetched_via_spdy);
42195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response->headers->GetStatusLine();
42205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response;  // Make a copy so we can verify.
42215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read Data
42235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback read_callback;
42245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
422523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const int kReadSize = 256;
422623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
422723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
422823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ASSERT_EQ(net::ERR_IO_PENDING, rv) << "Unexpected read: " << rv;
422923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
423023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Complete the read now, which causes buffering to start.
423123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  data.CompleteRead();
423223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Destroy the transaction, causing the stream to get cancelled
423323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // and orphaning the buffered IO task.
423423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  helper.ResetTrans();
42355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flush the MessageLoop; this will cause the buffered IO task
42375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to run for the final time.
42383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
42395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that we consumed all test data.
42415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
42425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
42435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that if the server requests persistence of settings, that we save
42455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the settings in the HttpServerProperties.
42467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
4247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (spdy_util_.spdy_version() >= SPDY4) {
4248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // SPDY4 doesn't support settings persistence.
4249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
4250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
42515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const SpdyHeaderInfo kSynReplyInfo = {
42525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SYN_REPLY,                              // Syn Reply
42535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1,                                      // Stream ID
42545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                                      // Associated Stream ID
42557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ConvertRequestPriorityToSpdyPriority(
42567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        LOWEST, spdy_util_.spdy_version()),
42577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    kSpdyCredentialSlotUnused,
42585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CONTROL_FLAG_NONE,                      // Control Flags
42595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    false,                                  // Compressed
42602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RST_STREAM_INVALID,                     // Status
42615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NULL,                                   // Data
42625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                                      // Data Length
42635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DATA_FLAG_NONE                          // Data Flags
42645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
42655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog net_log;
42672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
42682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     net_log, GetParam(), NULL);
42695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
42705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that no settings exist initially.
42725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostPortPair host_port_pair("www.google.com", helper.port());
42735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
42745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
42755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_port_pair).empty());
42765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the request.
427890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
427990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
42805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req) };
42815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the reply.
42837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
42847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
42857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
42865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> reply(
42877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
42885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
42905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int kSampleValue1 = 0x0a0a0a0a;
42915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
42925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int kSampleValue2 = 0x0b0b0b0b;
42935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
42945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int kSampleValue3 = 0x0c0c0c0c;
42955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame;
42965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
42975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Construct the SETTINGS frame.
42985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SettingsMap settings;
42995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // First add a persisted setting.
43005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    settings[kSampleId1] =
43015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
43025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Next add a non-persisted setting.
43035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    settings[kSampleId2] =
43045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
43055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Next add another persisted setting.
43065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    settings[kSampleId3] =
43075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
430890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
43095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
43105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
43125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
43135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*reply),
43145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
4315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*settings_frame),
4316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
4317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(1, reads, arraysize(reads),
4320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
4321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
4322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunDefaultTest();
4323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
4324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out = helper.output();
4325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, out.rv);
4326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello!", out.response_data);
4328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  {
4330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Verify we had two persisted settings.
4331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const SettingsMap& settings_map =
4332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        spdy_session_pool->http_server_properties()->GetSpdySettings(
4333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            host_port_pair);
4334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ASSERT_EQ(2u, settings_map.size());
4335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Verify the first persisted setting.
4337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(it1 != settings_map.end());
4339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SettingsFlagsAndValue flags_and_value1 = it1->second;
4340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Verify the second persisted setting.
4344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SettingsMap::const_iterator it3 = settings_map.find(kSampleId3);
4345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(it3 != settings_map.end());
4346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SettingsFlagsAndValue flags_and_value3 = it3->second;
4347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first);
4348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(kSampleValue3, flags_and_value3.second);
4349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
4350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
4351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test that when there are settings saved that they are sent back to the
4353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// server upon session establishment.
4354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
4355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (spdy_util_.spdy_version() >= SPDY4) {
4356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // SPDY4 doesn't support settings persistence.
4357116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
4358116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
4359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static const SpdyHeaderInfo kSynReplyInfo = {
4360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SYN_REPLY,                              // Syn Reply
4361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    1,                                      // Stream ID
4362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    0,                                      // Associated Stream ID
4363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ConvertRequestPriorityToSpdyPriority(
4364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        LOWEST, spdy_util_.spdy_version()),
4365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    kSpdyCredentialSlotUnused,
4366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CONTROL_FLAG_NONE,                      // Control Flags
4367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    false,                                  // Compressed
4368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    RST_STREAM_INVALID,                     // Status
4369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    NULL,                                   // Data
4370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    0,                                      // Data Length
4371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DATA_FLAG_NONE                          // Data Flags
4372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  BoundNetLog net_log;
4375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     net_log, GetParam(), NULL);
4377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
4378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4379a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4380a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
4381a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  SpdySessionPoolPeer pool_peer(spdy_session_pool);
4382a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  pool_peer.SetEnableSendingInitialData(true);
4383a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
4384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that no settings exist initially.
4385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port_pair("www.google.com", helper.port());
4386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      host_port_pair).empty());
4388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
43894ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  const SpdySettingsIds kSampleId1 = SETTINGS_MAX_CONCURRENT_STREAMS;
4390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  unsigned int kSampleValue1 = 0x0a0a0a0a;
43914ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  const SpdySettingsIds kSampleId2 = SETTINGS_INITIAL_WINDOW_SIZE;
4392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  unsigned int kSampleValue2 = 0x0c0c0c0c;
4393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // First add a persisted setting.
4395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_session_pool->http_server_properties()->SetSpdySetting(
4396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      host_port_pair,
4397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSampleId1,
4398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SETTINGS_FLAG_PLEASE_PERSIST,
4399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSampleValue1);
4400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Next add another persisted setting.
4402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_session_pool->http_server_properties()->SetSpdySetting(
4403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      host_port_pair,
4404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSampleId2,
4405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SETTINGS_FLAG_PLEASE_PERSIST,
4406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSampleValue2);
4407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      host_port_pair).size());
4410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4411a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Construct the initial SETTINGS frame.
4412a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  SettingsMap initial_settings;
4413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
4414a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams);
4415a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<SpdyFrame> initial_settings_frame(
4416a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      spdy_util_.ConstructSpdySettings(initial_settings));
4417a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
4418a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Construct the initial window update.
4419a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<SpdyFrame> initial_window_update(
4420a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      spdy_util_.ConstructSpdyWindowUpdate(
4421a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          kSessionFlowControlStreamId,
4422a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize));
4423a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
4424a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Construct the persisted SETTINGS frame.
4425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const SettingsMap& settings =
4426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_session_pool->http_server_properties()->GetSpdySettings(
4427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          host_port_pair);
4428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> settings_frame(
4429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySettings(settings));
4430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct the request.
4432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
4433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::vector<MockWrite> writes;
4436a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (GetParam().protocol == kProtoSPDY4) {
4437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    writes.push_back(
4438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        MockWrite(ASYNC,
4439a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  kHttp2ConnectionHeaderPrefix,
4440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  kHttp2ConnectionHeaderPrefixSize));
4441a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
4442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  writes.push_back(CreateMockWrite(*initial_settings_frame));
4443a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (GetParam().protocol >= kProtoSPDY31) {
4444a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    writes.push_back(CreateMockWrite(*initial_window_update));
4445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4446a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  writes.push_back(CreateMockWrite(*settings_frame));
4447a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  writes.push_back(CreateMockWrite(*req));
4448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct the reply.
4450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> reply(
4454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
4458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*reply),
4459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body),
44605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
44615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
44625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(2, reads, arraysize(reads),
4464a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                         vector_as_array(&writes), writes.size());
44655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
44665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunDefaultTest();
44675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
44685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
44695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
44705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
44715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
44725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
44745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify we had two persisted settings.
44755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SettingsMap& settings_map =
44765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        spdy_session_pool->http_server_properties()->GetSpdySettings(
44775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            host_port_pair);
44785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(2u, settings_map.size());
44795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify the first persisted setting.
44815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
44825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(it1 != settings_map.end());
44835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SettingsFlagsAndValue flags_and_value1 = it1->second;
44845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
44855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kSampleValue1, flags_and_value1.second);
44865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify the second persisted setting.
4488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SettingsMap::const_iterator it2 = settings_map.find(kSampleId2);
4489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(it2 != settings_map.end());
4490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SettingsFlagsAndValue flags_and_value2 = it2->second;
4491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first);
4492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(kSampleValue2, flags_and_value2.second);
44935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
44945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
44955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
4497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
4498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
45007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
4502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
4503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*go_away),
45045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
45055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(1, reads, arraysize(reads),
4507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
45082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
4510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
4511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunToCompletion(&data);
4512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out = helper.output();
4513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_ABORTED, out.rv);
4514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
4515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
4517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
4518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
4520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
4523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp),
4524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, 0, 0)  // EOF
4525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(1, reads, arraysize(reads),
4528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
4529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  BoundNetLog log;
4530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     log, GetParam(), NULL);
4532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
4533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
4534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
4535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
4537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out;
4538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
4539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(out.rv, ERR_IO_PENDING);
4541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  out.rv = callback.WaitForResult();
4542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(out.rv, OK);
4543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
4545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response->headers.get() != NULL);
4546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
4547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  out.rv = ReadTransaction(trans, &out.response_data);
4548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
4551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
4552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
4553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test to make sure we can correctly connect through a proxy.
4555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
4556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
4558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.session_deps().reset(CreateSpdySessionDependencies(
4559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      GetParam(),
4560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.SetSession(make_scoped_refptr(
4562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
4564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
4565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Host: www.google.com\r\n"
4568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Proxy-Connection: keep-alive\r\n\r\n"};
4569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Host: www.google.com\r\n"
4571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Proxy-Connection: keep-alive\r\n\r\n"};
4572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
4574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes_SPDYNPN[] = {
4579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 2),
4581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads_SPDYNPN[] = {
4583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4584eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 3),
4585eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body.get(), 4),
4586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 5),
4587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes_SPDYSSL[] = {
4590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 2),
4592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads_SPDYSSL[] = {
4594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 3),
4596eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body.get(), 4),
4597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 5),
4598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes_SPDYNOSSL[] = {
4601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
4602eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads_SPDYNOSSL[] = {
4605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1),
4606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body.get(), 2),
4607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 3),
4608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<OrderedSocketData> data;
4611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch(GetParam().ssl_type) {
4612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SPDYNOSSL:
4613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      data.reset(new OrderedSocketData(reads_SPDYNOSSL,
4614eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       arraysize(reads_SPDYNOSSL),
4615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       writes_SPDYNOSSL,
4616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       arraysize(writes_SPDYNOSSL)));
4617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
4618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SPDYSSL:
4619eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      data.reset(new OrderedSocketData(reads_SPDYSSL,
4620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       arraysize(reads_SPDYSSL),
4621eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       writes_SPDYSSL,
4622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       arraysize(writes_SPDYSSL)));
4623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
4624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SPDYNPN:
4625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      data.reset(new OrderedSocketData(reads_SPDYNPN,
4626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       arraysize(reads_SPDYNPN),
4627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       writes_SPDYNPN,
4628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       arraysize(writes_SPDYNPN)));
4629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
4630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default:
4631eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      NOTREACHED();
4632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
4633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(data.get());
4635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
4636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
4638eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
4639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
4640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
4642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, rv);
4643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
4645eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response = *trans->GetResponseInfo();
4646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
4647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string response_data;
4650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4651eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello!", response_data);
4652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
4653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
4654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test to make sure we can correctly connect through a proxy to www.google.com,
4656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// if there already exists a direct spdy connection to www.google.com. See
4657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// http://crbug.com/49874
4658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
4659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // When setting up the first transaction, we store the SpdySessionPool so that
4660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // we can use the same pool in the second transaction.
4661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
4663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Use a proxy service which returns a proxy fallback list from DIRECT to
4665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // myproxy:70. For this test there will be no fallback, so it is equivalent
4666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // to simply DIRECT. The reason for appending the second proxy is to verify
4667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // that the session pool key used does is just "DIRECT".
4668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.session_deps().reset(CreateSpdySessionDependencies(
4669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      GetParam(),
4670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.SetSession(make_scoped_refptr(
4672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
46755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
46765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct and send a simple GET request.
4678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
4679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
4681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 1),
4682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
4687eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 2),
4688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body, 3),
4689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 4),  // Force a pause
4690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 5)  // EOF
4691eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
4693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
4694eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
4695eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
4696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4697eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
4698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out;
4699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  out.rv = trans->Start(
4700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
4701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(out.rv, ERR_IO_PENDING);
4703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  out.rv = callback.WaitForResult();
4704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(out.rv, OK);
4705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
4707eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response->headers.get() != NULL);
4708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
4709eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  out.rv = ReadTransaction(trans, &out.response_data);
4710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, out.rv);
4711eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  out.status_line = response->headers->GetStatusLine();
4712eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4713eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello!", out.response_data);
4714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4715eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Check that the SpdySession is still in the SpdySessionPool.
4716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port_pair("www.google.com", helper.port());
4717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey session_pool_key_direct(
4718e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      host_port_pair, ProxyServer::Direct(), PRIVACY_MODE_DISABLED);
47197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
4720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey session_pool_key_proxy(
4721eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      host_port_pair,
4722eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
4723e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      PRIVACY_MODE_DISABLED);
47247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
4725eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4726eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set up data for the proxy connection.
4727eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4728eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Host: www.google.com\r\n"
4729eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Proxy-Connection: keep-alive\r\n\r\n"};
4730eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4731eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Host: www.google.com\r\n"
4732eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Proxy-Connection: keep-alive\r\n\r\n"};
4733eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4734eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
4735eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "http://www.google.com/foo.dat", false, 1, LOWEST));
4736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
47385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4739eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes_SPDYNPN[] = {
4740eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4741eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 2),
4742eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads_SPDYNPN[] = {
4744eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4745eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 3),
4746eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body2, 4),
4747eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 5)  // EOF
4748eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
47495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes_SPDYNOSSL[] = {
4751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 0),
4752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4753eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads_SPDYNOSSL[] = {
4754eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 1),
4755eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body2, 2),
4756eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 3)  // EOF
4757eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
47585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4759eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes_SPDYSSL[] = {
4760eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4761eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 2),
4762eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4763eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads_SPDYSSL[] = {
4764eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4765eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 3),
4766eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body2, 4),
4767eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 5),
4768eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
47695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<OrderedSocketData> data_proxy;
4771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch(GetParam().ssl_type) {
4772eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SPDYNPN:
4773eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      data_proxy.reset(new OrderedSocketData(reads_SPDYNPN,
4774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             arraysize(reads_SPDYNPN),
4775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             writes_SPDYNPN,
4776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             arraysize(writes_SPDYNPN)));
4777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
4778eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SPDYNOSSL:
4779eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      data_proxy.reset(new OrderedSocketData(reads_SPDYNOSSL,
4780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             arraysize(reads_SPDYNOSSL),
4781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             writes_SPDYNOSSL,
4782eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             arraysize(writes_SPDYNOSSL)));
4783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
4784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SPDYSSL:
4785eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      data_proxy.reset(new OrderedSocketData(reads_SPDYSSL,
4786eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             arraysize(reads_SPDYSSL),
4787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             writes_SPDYSSL,
4788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             arraysize(writes_SPDYSSL)));
4789eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
4790eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default:
4791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      NOTREACHED();
4792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
47935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create another request to www.google.com, but this time through a proxy.
4795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo request_proxy;
4796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request_proxy.method = "GET";
4797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request_proxy.url = GURL("http://www.google.com/foo.dat");
4798eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request_proxy.load_flags = 0;
4799eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdySessionDependencies> ssd_proxy(
4800eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateSpdySessionDependencies(GetParam()));
4801eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure that this transaction uses the same SpdySessionPool.
4802eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<HttpNetworkSession> session_proxy(
4803eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
4804eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
4805eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           BoundNetLog(), GetParam(), NULL);
4806eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkSessionPeer session_peer(session_proxy);
4807eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<net::ProxyService> proxy_service(
4808eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
4809eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_peer.SetProxyService(proxy_service.get());
4810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper_proxy.session_deps().swap(ssd_proxy);
4811eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper_proxy.SetSession(session_proxy);
4812eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper_proxy.RunPreTestSetup();
4813eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper_proxy.AddData(data_proxy.get());
48145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
4816eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback_proxy;
4817eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans_proxy->Start(
4818eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &request_proxy, callback_proxy.callback(), BoundNetLog());
4819eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
4820eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback_proxy.WaitForResult();
4821eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, rv);
48225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4823eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
4824eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response_proxy.headers.get() != NULL);
4825eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
48265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4827eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string response_data;
4828eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
4829eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello!", response_data);
4830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.CompleteRead();
4832eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper_proxy.VerifyDataConsumed();
4833eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
48345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4836eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// on a new connection, if the connection was previously known to be good.
4837eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// This can happen when a server reboots without saying goodbye, or when
4838eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// we're behind a NAT that masked the RST.
4839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
4840eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
48417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
48425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
4843eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp),
4844eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body),
4845eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING),
4846eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_CONNECTION_RESET),
4847eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4848eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4849eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads2[] = {
4850eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp),
48515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
48525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
48535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
48545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // This test has a couple of variants.
4856eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  enum {
4857eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Induce the RST while waiting for our transaction to send.
4858eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    VARIANT_RST_DURING_SEND_COMPLETION,
4859eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Induce the RST while waiting for our transaction to read.
4860eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // In this case, the send completed - everything copied into the SNDBUF.
4861eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    VARIANT_RST_DURING_READ_COMPLETION
4862eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
48635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4864eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       variant <= VARIANT_RST_DURING_READ_COMPLETION;
4866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       ++variant) {
4867eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DelayedSocketData data1(1, reads, arraysize(reads), NULL, 0);
48685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4869eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DelayedSocketData data2(1, reads2, arraysize(reads2), NULL, 0);
48705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4871eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4872eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       BoundNetLog(), GetParam(), NULL);
4873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    helper.AddData(&data1);
4874eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    helper.AddData(&data2);
4875eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    helper.RunPreTestSetup();
48765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4877eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (int i = 0; i < 2; ++i) {
4878eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      scoped_ptr<HttpNetworkTransaction> trans(
4879eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
48807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4881eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      TestCompletionCallback callback;
4882eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      int rv = trans->Start(
4883eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          &helper.request(), callback.callback(), BoundNetLog());
4884eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_EQ(ERR_IO_PENDING, rv);
4885eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // On the second transaction, we trigger the RST.
4886eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (i == 1) {
4887eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4888eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          // Writes to the socket complete asynchronously on SPDY by running
4889eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          // through the message loop.  Complete the write here.
48903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          base::RunLoop().RunUntilIdle();
4891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
48925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Now schedule the ERR_CONNECTION_RESET.
4894eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        EXPECT_EQ(3u, data1.read_index());
4895eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        data1.CompleteRead();
4896eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        EXPECT_EQ(4u, data1.read_index());
4897eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
4898eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      rv = callback.WaitForResult();
4899eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_EQ(OK, rv);
49005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4901eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      const HttpResponseInfo* response = trans->GetResponseInfo();
4902eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ASSERT_TRUE(response != NULL);
4903eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_TRUE(response->headers.get() != NULL);
4904eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_TRUE(response->was_fetched_via_spdy);
4905eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      std::string response_data;
4906eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      rv = ReadTransaction(trans.get(), &response_data);
4907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_EQ(OK, rv);
4908eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4909eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_EQ("hello!", response_data);
4910eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
49115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    helper.VerifyDataConsumed();
4913eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
4914eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
49157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test that turning SPDY on and off works properly.
4917eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
4918cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  HttpStreamFactory::set_spdy_enabled(true);
491990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
492090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4921eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
49225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4925eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead spdy_reads[] = {
49265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
4927eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body),
4928eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
49295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
49305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4931eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(1, spdy_reads, arraysize(spdy_reads),
4932eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         spdy_writes, arraysize(spdy_writes));
49332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4934eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
4935eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunToCompletion(&data);
4936eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out = helper.output();
4937eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, out.rv);
4938eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4939eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello!", out.response_data);
49405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4941eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  net::HttpStreamFactory::set_spdy_enabled(false);
4942eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead http_reads[] = {
4943eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4944eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead("hello from http"),
4945eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, OK),
4946eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4947eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data2(1, http_reads, arraysize(http_reads), NULL, 0);
4948eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper2(CreateGetRequest(), DEFAULT_PRIORITY,
4949eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
4950eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper2.SetSpdyDisabled();
4951eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper2.RunToCompletion(&data2);
4952eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out2 = helper2.output();
4953eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, out2.rv);
4954eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
4955eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello from http", out2.response_data);
49565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4957eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  net::HttpStreamFactory::set_spdy_enabled(true);
49585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
49595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4960eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Tests that Basic authentication works over SPDY
4961eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
4962eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  net::HttpStreamFactory::set_spdy_enabled(true);
49635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4964eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The first request will be a bare GET, the second request will be a
4965eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // GET with an Authorization header.
4966eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req_get(
496790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4968eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char* const kExtraAuthorizationHeaders[] = {
4969eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "authorization", "Basic Zm9vOmJhcg=="
49705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4971eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req_get_authorization(
4972eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4973eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                  arraysize(kExtraAuthorizationHeaders) / 2,
4974eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                  false, 3, LOWEST, true));
4975eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite spdy_writes[] = {
4976eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req_get, 1),
4977eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req_get_authorization, 4),
49785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
49795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4980eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The first response is a 401 authentication challenge, and the second
4981eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // response will be a 200 response since the second request includes a valid
4982eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Authorization header.
4983eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char* const kExtraAuthenticationHeaders[] = {
4984eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "www-authenticate",
4985eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "Basic realm=\"MyRealm\""
49865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4987eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp_authentication(
4988eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySynReplyError(
4989eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          "401 Authentication Required",
4990eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kExtraAuthenticationHeaders,
4991eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          arraysize(kExtraAuthenticationHeaders) / 2,
4992eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1));
4993eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body_authentication(
4994eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
4995eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp_data(
4996eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4997eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
4998eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead spdy_reads[] = {
4999eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp_authentication, 2),
5000eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body_authentication, 3),
5001eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp_data, 5),
5002eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body_data, 6),
5003eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 7),
50045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
50055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5006eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(spdy_reads, arraysize(spdy_reads),
5007eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         spdy_writes, arraysize(spdy_writes));
5008eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo request(CreateGetRequest());
5009eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  BoundNetLog net_log;
5010eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5011eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     net_log, GetParam(), NULL);
50125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5013eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
5014eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
5015eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
50165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
5017eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int rv_start = trans->Start(&request, callback.callback(), net_log);
5018eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv_start);
5019eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int rv_start_complete = callback.WaitForResult();
5020eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv_start_complete);
50215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5022eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Make sure the response has an auth challenge.
5023eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const HttpResponseInfo* const response_start = trans->GetResponseInfo();
5024eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(response_start != NULL);
5025eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(response_start->headers.get() != NULL);
5026eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(401, response_start->headers->response_code());
5027eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response_start->was_fetched_via_spdy);
5028eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
5029eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(auth_challenge != NULL);
5030eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(auth_challenge->is_proxy);
5031eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("basic", auth_challenge->scheme);
5032eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("MyRealm", auth_challenge->realm);
50335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5034eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Restart with a username/password.
50355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AuthCredentials credentials(base::ASCIIToUTF16("foo"),
50365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              base::ASCIIToUTF16("bar"));
5037eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback_restart;
5038eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int rv_restart = trans->RestartWithAuth(
5039eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      credentials, callback_restart.callback());
5040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv_restart);
5041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int rv_restart_complete = callback_restart.WaitForResult();
5042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv_restart_complete);
5043eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(cbentzel): This is actually the same response object as before, but
5044eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // data has changed.
5045eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
5046eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(response_restart != NULL);
5047eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(response_restart->headers.get() != NULL);
5048eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(200, response_restart->headers->response_code());
5049eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
50505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
50515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5052eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
5053eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
505490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5055eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
5056eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
50575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
5058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
50595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
50605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5062eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_util_.AddUrlToHeaderBlock(
5063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "http://www.google.com/foo.dat", initial_headers.get());
5064eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_syn(
50656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5066eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5067eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5068eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)["hello"] = "bye";
5069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_headers(
5072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
5074eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           2,
5075eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
5076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           HEADERS,
5077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
5078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           0));
5079eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5080eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
5081eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5082eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
5083eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
5084eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
5085eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
50865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
5087eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
5088eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
5089eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_headers, 4),
5090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5091eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 5),
5092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 7),  // Force a pause
50935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
5096eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
5097eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed");
50985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
50995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
5100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunServerPushTest(&data,
5101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response,
5102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response2,
5103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    expected_push_result);
51045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
5106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
5107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
51085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
5110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
5111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
51135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
5115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // We push a stream and attempt to claim it before the headers come down.
5116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
5117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
5119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
5120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
5121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
51225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
51235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_util_.AddUrlToHeaderBlock(
5126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "http://www.google.com/foo.dat", initial_headers.get());
5127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_syn(
51286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
51295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)["hello"] = "bye";
5132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_headers(
5135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
5137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           2,
5138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
5139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           HEADERS,
5140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
5141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           0));
51425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
5144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
5146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
5147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
5148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
5149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
5150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 1),
5151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 2),
5152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 3),
5153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_headers, 4),
5154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 5),
5155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 6),  // EOF
5156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
51575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
5159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
5160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed");
5161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
5162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
51635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
5166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.SetDeterministic();
5167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddDeterministicData(&data);
5168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
51697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
51715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // and the body of the primary stream, but before we've received the HEADERS
5174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // for the pushed stream.
5175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.SetStop(3);
51765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction.
5178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
5179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
5180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
5181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.Run();
5183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
5184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, rv);
51855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Request the pushed path.  At this point, we've received the push, but the
5187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // headers are not yet complete.
5188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<HttpNetworkTransaction> trans2(
5189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = trans2->Start(
5191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(3);
51943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
51955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the server push body.
5197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string result2;
5198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ReadResult(trans2.get(), &data, &result2);
5199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the response body.
5200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string result;
5201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ReadResult(trans, &data, &result);
52025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that the received push data is same as the expected push data.
5204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(result2.compare(expected_push_result), 0)
5205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      << "Received data: "
5206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      << result2
5207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      << "||||| Expected data: "
5208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      << expected_push_result;
52095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
5211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Copy the response info, because trans goes away.
5212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  response = *trans->GetResponseInfo();
5213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  response2 = *trans2->GetResponseInfo();
52145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  VerifyStreamsClosed(helper);
52165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
5218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
5219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
52205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
5222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
5223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
52245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the final EOF (which will close the session)
5226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
52275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
5229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof());
5230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
5231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
52327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// TODO(baranovich): HTTP 2 does not allow multiple HEADERS frames
5234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
5235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // We push a stream and attempt to claim it before the headers come down.
5236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
523790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
5239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
5240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
5241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
52435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
52456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (spdy_util_.spdy_version() < SPDY4) {
52466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // In SPDY4 PUSH_PROMISE headers won't show up in the response headers.
52476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    (*initial_headers)["alpha"] = "beta";
52486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
5249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_util_.AddUrlToHeaderBlock(
5250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "http://www.google.com/foo.dat", initial_headers.get());
5251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_syn(
52526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
5253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*middle_headers)["hello"] = "bye";
5256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_headers1(
5257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
5259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           2,
5260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
5261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           HEADERS,
5262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
5263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           0));
5264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5267c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (spdy_util_.spdy_version() < SPDY4) {
5268c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // SPDY4/HTTP2 eliminates use of the :version header.
5269c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5270c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
5271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_headers2(
5272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
5274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           2,
5275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
5276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           HEADERS,
5277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
5278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           0));
5279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
5281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
5283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
5284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
5285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
5286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
5287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 1),
5288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 2),
5289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 3),
5290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_headers1, 4),
5291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_headers2, 5),
5292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 6),
5293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 7),  // EOF
52945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
52955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
5297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
5298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed");
5299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
5300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
5301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
53022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
53035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
5304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.SetDeterministic();
5305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddDeterministicData(&data);
5306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
53075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
53095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // the first HEADERS frame, and the body of the primary stream, but before
5312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // we've received the final HEADERS for the pushed stream.
5313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.SetStop(4);
53145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction.
5316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
5317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
5318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
5319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.Run();
5321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
5322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, rv);
53237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Request the pushed path.  At this point, we've received the push, but the
5325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // headers are not yet complete.
5326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<HttpNetworkTransaction> trans2(
5327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = trans2->Start(
5329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(3);
53323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
53335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the server push body.
5335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string result2;
5336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ReadResult(trans2.get(), &data, &result2);
5337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the response body.
5338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string result;
5339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ReadResult(trans, &data, &result);
5340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that the received push data is same as the expected push data.
5342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(expected_push_result, result2);
5343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
5345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Copy the response info, because trans goes away.
5346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  response = *trans->GetResponseInfo();
5347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  response2 = *trans2->GetResponseInfo();
53485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  VerifyStreamsClosed(helper);
53505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
5352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
5353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
53545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
5356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
5357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
53585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Verify we got all the headers from all header blocks.
53606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (spdy_util_.spdy_version() < SPDY4)
53616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    EXPECT_TRUE(response2.headers->HasHeaderValue("alpha", "beta"));
5362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
53645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the final EOF (which will close the session)
5366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
53675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
5369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof());
5370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
5371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
53727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
5374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // We push a stream and attempt to claim it before the headers come down.
537590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> stream1_syn(
537690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
53777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> stream1_body(
53787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, true));
53795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
5380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
53815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
53825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
53847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  spdy_util_.AddUrlToHeaderBlock(
53857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      "http://www.google.com/foo.dat", initial_headers.get());
5386a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  scoped_ptr<SpdyFrame> stream2_syn(
53876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      spdy_util_.ConstructInitialSpdyPushFrame(initial_headers.Pass(), 2, 1));
53887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*middle_headers)["hello"] = "bye";
5391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_headers1(
5392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5393a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           false,
5394a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           2,
5395a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           LOWEST,
5396a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           HEADERS,
5397a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           CONTROL_FLAG_NONE,
5398a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           0));
53995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame>
54017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
5403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
5404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
5405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
54065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
5407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 1),
5408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 2),
5409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 3),
5410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_headers1, 4),
5411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 5),
5412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 6),  // EOF
54135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
54145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
5416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
5417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
5420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.SetDeterministic();
5421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddDeterministicData(&data);
5422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
5423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
5425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // the first HEADERS frame, and the body of the primary stream, but before
5428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // we've received the final HEADERS for the pushed stream.
5429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.SetStop(4);
5430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction.
5432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
5433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
5434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
5435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.Run();
5437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
5438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, rv);
5439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Request the pushed path.  At this point, we've received the push, but the
5441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // headers are not yet complete.
5442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<HttpNetworkTransaction> trans2(
5443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = trans2->Start(
5445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
54483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
5449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the server push body.
5451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string result2;
5452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ReadResult(trans2.get(), &data, &result2);
5453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the response body.
5454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string result;
5455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ReadResult(trans, &data, &result);
5456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello!", result);
5457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we haven't received any push data.
5459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("", result2);
5460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
5462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Copy the response info, because trans goes away.
5463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response = *trans->GetResponseInfo();
5464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(trans2->GetResponseInfo() == NULL);
5465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  VerifyStreamsClosed(helper);
54675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the SYN_REPLY.
5469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response.headers.get() != NULL);
54705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
54715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the final EOF (which will close the session).
5473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
54745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
5476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof());
5477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
5478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
54797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
5481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
548290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
5484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
5486116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CreateMockWrite(*req), CreateMockWrite(*rst),
5487116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  };
5488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_reply(
5490116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)["hello"] = "bye";
5494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_headers(
5495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
5497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           1,
5498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
5499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           HEADERS,
5500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
5501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           0));
55027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> stream1_body(
55037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, true));
5504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
5505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply),
5506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_headers),
5507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body),
5508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
5509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
5510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(1, reads, arraysize(reads),
5512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
5513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
5515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunToCompletion(&data);
5516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out = helper.output();
5517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
5519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
5521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
5522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
5524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
55255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
5526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req),
5527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*rst),
55285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
55295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_reply(
5531116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
55327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
55337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
55347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  (*late_headers)["hello"] = "bye";
5535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_headers(
55367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5537a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           false,
5538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           1,
5539a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           LOWEST,
5540a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           HEADERS,
5541a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           CONTROL_FLAG_NONE,
5542a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           0));
5543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
5544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, false));
5545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body2(
5546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
55475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
5548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply),
5549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body),
5550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_headers),
5551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body2),
5552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
55535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
55545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(1, reads, arraysize(reads),
5556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
5557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
5559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunToCompletion(&data);
5560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out = helper.output();
5561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
5563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
5565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // In this test we want to verify that we can't accidentally push content
5566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // which can't be pushed by this content server.
5567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // This test assumes that:
5568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   - if we're requesting http://www.foo.com/barbaz
5569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   - the browser has made a connection to "www.foo.com".
5570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // A list of the URL to fetch, followed by the URL being pushed.
5572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static const char* const kTestCases[] = {
5573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://www.google.com/foo.html",
5574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://www.google.com:81/foo.js",     // Bad port
5575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://www.google.com/foo.html",
5577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "https://www.google.com/foo.js",       // Bad protocol
5578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://www.google.com/foo.html",
5580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "ftp://www.google.com/foo.js",         // Invalid Protocol
5581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://www.google.com/foo.html",
5583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://blat.www.google.com/foo.js",   // Cross subdomain
5584eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5585eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://www.google.com/foo.html",
5586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://www.foo.com/foo.js",           // Cross domain
5587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
5588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
5590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const char* url_to_fetch = kTestCases[index];
5591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const char* url_to_push = kTestCases[index + 1];
5592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame> stream1_syn(
5594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
5595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame> stream1_body(
5596eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        spdy_util_.ConstructSpdyBodyFrame(1, true));
5597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame> push_rst(
5598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
5599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite writes[] = {
5600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateMockWrite(*stream1_syn, 1),
5601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateMockWrite(*push_rst, 4),
5602eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    };
5603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame>
5605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame>
5607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
5608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                 0,
5609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                 2,
5610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                 1,
5611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                 url_to_push));
5612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const char kPushedData[] = "pushed";
5613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame> stream2_body(
5614eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        spdy_util_.ConstructSpdyBodyFrame(
5615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            2, kPushedData, strlen(kPushedData), true));
5616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame> rst(
5617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
5618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5619eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead reads[] = {
5620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateMockRead(*stream1_reply, 2),
5621eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateMockRead(*stream2_syn, 3),
5622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateMockRead(*stream2_body, 6),
5624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      MockRead(ASYNC, ERR_IO_PENDING, 7),  // Force a pause
5625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    };
5626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    HttpResponseInfo response;
5628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    OrderedSocketData data(reads, arraysize(reads),
5629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           writes, arraysize(writes));
5630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5631eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    HttpRequestInfo request;
5632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    request.method = "GET";
5633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    request.url = GURL(url_to_fetch);
5634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    request.load_flags = 0;
5635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Enable cross-origin push. Since we are not using a proxy, this should
5637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // not actually enable cross-origin SPDY push.
5638eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdySessionDependencies> session_deps(
5639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        CreateSpdySessionDependencies(GetParam()));
5640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
5641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       BoundNetLog(), GetParam(),
5643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       session_deps.release());
5644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    helper.RunPreTestSetup();
5645eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    helper.AddData(&data);
5646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    HttpNetworkTransaction* trans = helper.trans();
56485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Start the transaction with basic parameters.
5650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    TestCompletionCallback callback;
5651eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(ERR_IO_PENDING, rv);
5654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    rv = callback.WaitForResult();
5655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Read the response body.
5657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string result;
5658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ReadResult(trans, &data, &result);
5659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Verify that we consumed all test data.
5661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(data.at_read_eof());
5662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(data.at_write_eof());
5663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Verify the SYN_REPLY.
5665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Copy the response info, because trans goes away.
5666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    response = *trans->GetResponseInfo();
5667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    VerifyStreamsClosed(helper);
5669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Verify the SYN_REPLY.
5671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(response.headers.get() != NULL);
5672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
5674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
5675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
5677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct the request.
5678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
5679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
5681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
5682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
5683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 1),
5684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 3),
5685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
5686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5687eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> refused(
5688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
5689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true));
5691eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
5692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*refused, 2),
5693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 4),
5694eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body, 5),
5695eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 6)  // EOF
5696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
5697eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
5699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
57002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
57015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
5702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
57035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
5704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
57055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
57075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction with basic parameters.
57095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
57105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
57115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
57125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
57135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback.WaitForResult();
5714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv);
57155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
5717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof()) << "Read count: "
5718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_count()
5719eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << " Read index: "
5720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_index();
5721eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof()) << "Write count: "
5722eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_count()
5723eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << " Write index: "
5724eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_index();
57255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the SYN_REPLY.
5727eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response = *trans->GetResponseInfo();
5728868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response.headers.get() != NULL);
57295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
57305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
57315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5732eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) {
5733eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // This first request will start to establish the SpdySession.
5734eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Then we will start the second (MEDIUM priority) and then third
5735eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // (HIGHEST priority) request in such a way that the third will actually
5736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // start before the second, causing the second to be numbered differently
5737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // than the order they were created.
5738eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
573990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5740eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
5741eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true));
5742eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req3(
5743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true));
57445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
5745eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
5746eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 3),
5747eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req3, 4),
57485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
57495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
5752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5753eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
5754eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
5755eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
57565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
5757eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp1, 1),
5758eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body1, 2),
5759eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 5),
5760eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body2, 6),
5761eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp3, 7),
5762eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body3, 8),
5763eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 9)  // EOF
57645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
57655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
57675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
5768eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
57695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
57705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.SetDeterministic();
57715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
5772eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddDeterministicData(&data);
57735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the first transaction to set up the SpdySession
57755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
57765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
5777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo info1 = CreateGetRequest();
5778eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
57795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
57805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Run the message loop, but do not allow the write to complete.
5782eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // This leaves the SpdySession with a write pending, which prevents
5783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // SpdySession from attempting subsequent writes until this write completes.
57843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
5785eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5786eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Now, start both new transactions
5787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo info2 = CreateGetRequest();
5788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
57895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans2(
5790eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new HttpNetworkTransaction(MEDIUM, helper.session().get()));
5791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = trans2->Start(&info2, callback2.callback(), BoundNetLog());
57925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
57933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
57945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo info3 = CreateGetRequest();
5796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback3;
5797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<HttpNetworkTransaction> trans3(
5798eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new HttpNetworkTransaction(HIGHEST, helper.session().get()));
5799eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = trans3->Start(&info3, callback3.callback(), BoundNetLog());
5800eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
58013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
58025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5803eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // We now have two SYN_STREAM frames queued up which will be
5804eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // dequeued only once the first write completes, which we
5805eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // now allow to happen.
5806eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
5807eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, callback.WaitForResult());
58085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5809eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // And now we can allow everything else to run to completion.
5810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.SetStop(10);
5811eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.Run();
5812eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, callback2.WaitForResult());
5813eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, callback3.WaitForResult());
58145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
5816eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
58175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5818eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The tests below are only for SPDY/3 and above.
58195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5820eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test that sent data frames and received WINDOW_UPDATE frames change
5821eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// the send_window_size_ correctly.
58225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5823eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// WINDOW_UPDATE is different than most other frames in that it can arrive
5824eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// while the client is still sending the request body.  In order to enforce
5825eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// this scenario, we feed a couple of dummy frames and give a delay of 0 to
5826eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// socket data provider, so that initial read that is done as soon as the
5827eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// stream is created, succeeds and schedules another read.  This way reads
5828eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// and writes are interleaved; after doing a full frame write, SpdyStream
5829eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// will break out of DoLoop and will read and process a WINDOW_UPDATE.
5830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// since request has not been completely written, therefore we feed
5832eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// enough number of WINDOW_UPDATEs to finish the first read and cause a
5833eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// write, leading to a complete write of request body; after that we send
5834eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// a reply with a body, to cause a graceful shutdown.
58355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5836eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TODO(agayev): develop a socket data provider where both, reads and
5837eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// writes are ordered so that writing tests like these are easy and rewrite
5838eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// all these tests using it.  Right now we are working around the
5839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// limitations as described above and it's not deterministic, tests may
5840eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// fail under specific circumstances.
5841eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
5842eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol < kProtoSPDY3)
58437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
58447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5845eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static int kFrameCount = 2;
5846eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<std::string> content(
5847eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new std::string(kMaxSpdyFrameChunkSize, 'a'));
5848eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
5849eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
5850eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(
5851eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
5852eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content->c_str(), content->size(), false));
5853eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body_end(
5854eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
5855eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content->c_str(), content->size(), true));
5856eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
58575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
5858eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
5859eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body, 1),
5860eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body_end, 2),
58615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
58625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5863eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static const int32 kDeltaWindowSize = 0xff;
5864eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static const int kDeltaCount = 4;
5865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update(
5866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5867eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update_dummy(
5868eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
5869eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
58705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
5871eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update_dummy, 3),
5872eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update_dummy, 4),
5873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update_dummy, 5),
5874eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update, 6),     // Four updates, therefore window
5875eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update, 7),     // size should increase by
5876eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update, 8),     // kDeltaWindowSize * 4
5877eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update, 9),
5878eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 10),
5879eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body_end, 11),
5880eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 12)  // EOF
58815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
58825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
58845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
58855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5886eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<UploadElementReader> element_readers;
5887eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (int i = 0; i < kFrameCount; ++i) {
5888eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    element_readers.push_back(
5889eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        new UploadBytesElementReader(content->c_str(), content->size()));
5890eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
589168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  UploadDataStream upload_data_stream(element_readers.Pass(), 0);
5892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Setup the request
5894eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo request;
5895eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.method = "POST";
5896eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.url = GURL(kDefaultURL);
5897eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.upload_data_stream = &upload_data_stream;
5898eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5899eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
59005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
59015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.SetDeterministic();
59025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddDeterministicData(&data);
59035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
59045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
59065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
5908eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
59095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
59115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(11);
59135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5914eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
5915eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream != NULL);
5916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream->stream() != NULL);
5917eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize) +
5918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            kDeltaWindowSize * kDeltaCount -
5919eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            kMaxSpdyFrameChunkSize * kFrameCount,
5920eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream->stream()->send_window_size());
59215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.RunFor(1);
59235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
5925eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv);
5926eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5927eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
59285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
59295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5930eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test that received data frames and sent WINDOW_UPDATE frames change
5931eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// the recv_window_size_ correctly.
5932eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
5933eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol < kProtoSPDY3)
59347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
59357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
593623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Amount of body required to trigger a sent window update.
593723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const size_t kTargetSize = kSpdyStreamInitialWindowSize / 2 + 1;
5938eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
593990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
594090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5941eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> session_window_update(
594223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      spdy_util_.ConstructSpdyWindowUpdate(0, kTargetSize));
5943eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update(
594423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      spdy_util_.ConstructSpdyWindowUpdate(1, kTargetSize));
59455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5946eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<MockWrite> writes;
5947eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*req));
5948eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol >= kProtoSPDY31)
5949eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    writes.push_back(CreateMockWrite(*session_window_update));
5950eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*window_update));
59517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
595223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  std::vector<MockRead> reads;
5953eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(
5954eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
595523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  reads.push_back(CreateMockRead(*resp));
595623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
595723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ScopedVector<SpdyFrame> body_frames;
595823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const std::string body_data(4096, 'x');
595923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  for (size_t remaining = kTargetSize; remaining != 0;) {
596023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    size_t frame_size = std::min(remaining, body_data.size());
596123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    body_frames.push_back(spdy_util_.ConstructSpdyBodyFrame(
596223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        1, body_data.data(), frame_size, false));
596323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    reads.push_back(CreateMockRead(*body_frames.back()));
596423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    remaining -= frame_size;
596523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
596623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 0)); // Yield.
59675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
596823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DelayedSocketData data(1, vector_as_array(&reads), reads.size(),
5969eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         vector_as_array(&writes), writes.size());
5970eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
59712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
59725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
5973eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
5974eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
5975eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
5976eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5977eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
5978eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5979eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5980eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5981eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
5982eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv);
5983eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5984eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyHttpStream* stream =
5985eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      static_cast<SpdyHttpStream*>(trans->stream_.get());
5986eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream != NULL);
5987eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream->stream() != NULL);
5988eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
598923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // All data has been read, but not consumed. The window reflects this.
599023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize - kTargetSize),
599123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            stream->stream()->recv_window_size());
5992eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5993eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
5994eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(response != NULL);
5995eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(response->headers.get() != NULL);
5996eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5997eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
5998eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5999eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Issue a read which will cause a WINDOW_UPDATE to be sent and window
6000eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // size increased to default.
600123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kTargetSize));
600223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_EQ(static_cast<int>(kTargetSize),
600323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            trans->Read(buf.get(), kTargetSize, CompletionCallback()));
600423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize),
600523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            stream->stream()->recv_window_size());
600623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x')));
600723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
600823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Allow scheduled WINDOW_UPDATE frames to write.
60093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
6010eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
60115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
60125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6013eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test that WINDOW_UPDATE frame causing overflow is handled correctly.
6014eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
6015eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol < kProtoSPDY3)
60167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
60177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
6018eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Number of full frames we hope to write (but will not, used to
6019eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // set content-length header correctly)
6020eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static int kFrameCount = 3;
60215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6022eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<std::string> content(
6023eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new std::string(kMaxSpdyFrameChunkSize, 'a'));
6024eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6025eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
6026eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(
6027eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
6028eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content->c_str(), content->size(), false));
6029eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
6030eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
60317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
6032eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // We're not going to write a data frame with FIN, we'll receive a bad
6033eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
6034eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
6035eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
6036eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body, 2),
6037eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*rst, 3),
6038eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
6039eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static const int32 kDeltaWindowSize = 0x7fffffff;  // cause an overflow
6041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update(
6042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
60435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
6044eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update, 1),
6045eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 4)  // EOF
60465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
60475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6048eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
6049eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
6050eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6051eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<UploadElementReader> element_readers;
6052eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (int i = 0; i < kFrameCount; ++i) {
6053eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    element_readers.push_back(
6054eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        new UploadBytesElementReader(content->c_str(), content->size()));
6055eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
605668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  UploadDataStream upload_data_stream(element_readers.Pass(), 0);
6057eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Setup the request
6059eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo request;
6060eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.method = "POST";
6061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.url = GURL("http://www.google.com/");
6062eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.upload_data_stream = &upload_data_stream;
6063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6064eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
60655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
6066eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.SetDeterministic();
6067eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
6068eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddDeterministicData(&data);
6069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
6070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
6072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING, rv);
6074eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6075eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(5);
6076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(callback.have_result());
6077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
6078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
60795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
60805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6081eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test that after hitting a send window size of 0, the write process
6082eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// stalls and upon receiving WINDOW_UPDATE frame write resumes.
6083eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6084eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// This test constructs a POST request followed by enough data frames
6085eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// containing 'a' that would make the window size 0, followed by another
6086eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// data frame containing default content (which is "hello!") and this frame
6087eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// also contains a FIN flag.  DelayedSocketData is used to enforce all
6088eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// writes go through before a read could happen.  However, the last frame
6089eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// ("hello!")  is not supposed to go through since by the time its turn
6090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// arrives, window size is 0.  At this point MessageLoop::Run() called via
6091eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// callback would block.  Therefore we call MessageLoop::RunUntilIdle()
6092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// which returns after performing all possible writes.  We use DCHECKS to
6093eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// ensure that last data frame is still there and stream has stalled.
6094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// After that, next read is artifically enforced, which causes a
6095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// WINDOW_UPDATE to be read and I/O process resumes.
6096eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
6097eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol < kProtoSPDY3)
60987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
60997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
6100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Number of frames we need to send to zero out the window size: data
6101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // frames plus SYN_STREAM plus the last data frame; also we need another
6102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // data frame that we will send once the WINDOW_UPDATE is received,
6103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // therefore +3.
6104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
61055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Calculate last frame's size; 0 size data frame is legal.
6107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t last_frame_size =
6108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
61097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
6110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct content for a data frame of maximum size.
6111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string content(kMaxSpdyFrameChunkSize, 'a');
61125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      LOWEST, NULL, 0));
61165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Full frames.
6118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(
6119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
6120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content.c_str(), content.size(), false));
61217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
6122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Last frame to zero out the window size.
6123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(
6124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
6125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content.c_str(), last_frame_size, false));
61265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Data frame to be sent once WINDOW_UPDATE frame is received.
6128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
61295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Fill in mock writes.
6131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
6132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t i = 0;
6133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes[i] = CreateMockWrite(*req);
6134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (i = 1; i < num_writes - 2; i++)
6135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    writes[i] = CreateMockWrite(*body1);
6136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes[i++] = CreateMockWrite(*body2);
6137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes[i] = CreateMockWrite(*body3);
61385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct read frame, give enough space to upload the rest of the
6140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // data.
6141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> session_window_update(
6142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update(
6144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
6145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
6147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*session_window_update),
6148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*session_window_update),
6149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update),
6150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update),
6151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*reply),
6152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body2),
6153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body3),
6154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
6155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
61565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Skip the session window updates unless we're using SPDY/3.1 and
6158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // above.
6159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t read_offset = (GetParam().protocol >= kProtoSPDY31) ? 0 : 2;
6160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t num_reads = arraysize(reads) - read_offset;
61615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Force all writes to happen before any read, last write will not
6163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // actually queue a frame, due to window size being 0.
6164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(num_writes, reads + read_offset, num_reads,
6165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes.get(), num_writes);
61665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<UploadElementReader> element_readers;
6168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  upload_data_string.append(kUploadData, kUploadDataSize);
6170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  element_readers.push_back(new UploadBytesElementReader(
6171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      upload_data_string.c_str(), upload_data_string.size()));
617268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  UploadDataStream upload_data_stream(element_readers.Pass(), 0);
61735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo request;
6175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.method = "POST";
6176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.url = GURL("http://www.google.com/");
6177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.upload_data_stream = &upload_data_stream;
6178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
6180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
6181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
61825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
61845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
6186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
61885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
61893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  base::RunLoop().RunUntilIdle();  // Write as much as we can.
61905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream != NULL);
6193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream->stream() != NULL);
6194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, stream->stream()->send_window_size());
6195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // All the body data should have been read.
6196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(satorux): This is because of the weirdness in reading the request
6197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // body in OnSendBodyComplete(). See crbug.com/113107.
6198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(upload_data_stream.IsEOF());
6199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // But the body is not yet fully sent (kUploadData is not yet sent)
6200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // since we're send-stalled.
6201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
62025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.ForceNextRead();   // Read in WINDOW_UPDATE frame.
6204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
6205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
6206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
62075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test we correctly handle the case where the SETTINGS frame results in
6209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// unstalling the send window.
6210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
6211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol < kProtoSPDY3)
6212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
62135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Number of frames we need to send to zero out the window size: data
6215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // frames plus SYN_STREAM plus the last data frame; also we need another
6216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // data frame that we will send once the SETTING is received, therefore +3.
6217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
62185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Calculate last frame's size; 0 size data frame is legal.
6220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t last_frame_size =
6221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
62225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct content for a data frame of maximum size.
6224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string content(kMaxSpdyFrameChunkSize, 'a');
6225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      LOWEST, NULL, 0));
6229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Full frames.
6231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(
6232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
6233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content.c_str(), content.size(), false));
6234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Last frame to zero out the window size.
6236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(
6237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
6238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content.c_str(), last_frame_size, false));
62395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Data frame to be sent once SETTINGS frame is received.
6241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
62425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Fill in mock reads/writes.
6244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<MockRead> reads;
6245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<MockWrite> writes;
6246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t i = 0;
6247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*req, i++));
6248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  while (i < num_writes - 2)
6249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    writes.push_back(CreateMockWrite(*body1, i++));
6250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*body2, i++));
62515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct read frame for SETTINGS that gives enough space to upload the
6253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // rest of the data.
6254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SettingsMap settings;
6255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SettingsFlagsAndValue(
6257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize * 2);
6258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> settings_frame_large(
6259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySettings(settings));
62605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*settings_frame_large, i++));
62625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> session_window_update(
6264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol >= kProtoSPDY31)
6266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    reads.push_back(CreateMockRead(*session_window_update, i++));
62675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  writes.push_back(CreateMockWrite(*settings_ack, i++));
6270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*body3, i++));
62725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*reply, i++));
6275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*body2, i++));
6276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*body3, i++));
6277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(MockRead(ASYNC, 0, i++));  // EOF
62787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
6279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Force all writes to happen before any read, last write will not
6280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // actually queue a frame, due to window size being 0.
6281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               vector_as_array(&writes), writes.size());
62835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<UploadElementReader> element_readers;
6285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  upload_data_string.append(kUploadData, kUploadDataSize);
6287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  element_readers.push_back(new UploadBytesElementReader(
6288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      upload_data_string.c_str(), upload_data_string.size()));
628968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  UploadDataStream upload_data_stream(element_readers.Pass(), 0);
62905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo request;
6292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.method = "POST";
6293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.url = GURL("http://www.google.com/");
6294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.upload_data_stream = &upload_data_stream;
6295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
62965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
6297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.SetDeterministic();
62985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
6299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddDeterministicData(&data);
63005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
63025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
6304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
63055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
63065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(num_writes - 1);   // Write as much as we can.
63085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream != NULL);
6311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream->stream() != NULL);
6312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, stream->stream()->send_window_size());
6313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // All the body data should have been read.
6315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(satorux): This is because of the weirdness in reading the request
6316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // body in OnSendBodyComplete(). See crbug.com/113107.
6317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(upload_data_stream.IsEOF());
6318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // But the body is not yet fully sent (kUploadData is not yet sent)
6319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // since we're send-stalled.
6320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.RunFor(7);   // Read in SETTINGS frame to unstall.
6323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
6324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
6325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // If stream is NULL, that means it was unstalled and closed.
6326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream->stream() == NULL);
63275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
63285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test we correctly handle the case where the SETTINGS frame results in a
6330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// negative send window size.
6331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
6332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol < kProtoSPDY3)
63337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
63347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
6335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Number of frames we need to send to zero out the window size: data
6336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // frames plus SYN_STREAM plus the last data frame; also we need another
6337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // data frame that we will send once the SETTING is received, therefore +3.
6338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
63395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Calculate last frame's size; 0 size data frame is legal.
6341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t last_frame_size =
6342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
63435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct content for a data frame of maximum size.
6345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string content(kMaxSpdyFrameChunkSize, 'a');
6346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      LOWEST, NULL, 0));
6350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Full frames.
6352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(
6353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
6354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content.c_str(), content.size(), false));
6355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Last frame to zero out the window size.
6357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(
6358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
6359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content.c_str(), last_frame_size, false));
6360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Data frame to be sent once SETTINGS frame is received.
6362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Fill in mock reads/writes.
6365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<MockRead> reads;
6366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<MockWrite> writes;
6367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t i = 0;
6368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*req, i++));
6369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  while (i < num_writes - 2)
6370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    writes.push_back(CreateMockWrite(*body1, i++));
6371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*body2, i++));
6372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct read frame for SETTINGS that makes the send_window_size
6374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // negative.
6375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SettingsMap new_settings;
6376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SettingsFlagsAndValue(
6378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize / 2);
6379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> settings_frame_small(
6380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySettings(new_settings));
6381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // positive.
6383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> session_window_update_init_size(
6384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(0, kSpdyStreamInitialWindowSize));
6385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update_init_size(
6386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize));
6387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*settings_frame_small, i++));
6389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol >= kProtoSPDY3)
6391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
6392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*window_update_init_size, i++));
6394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_ack(spdy_util_.ConstructSpdySettingsAck());
6396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  writes.push_back(CreateMockWrite(*settings_ack, i++));
6397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*body3, i++));
6399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*reply, i++));
6402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*body2, i++));
6403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*body3, i++));
6404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(MockRead(ASYNC, 0, i++));  // EOF
6405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Force all writes to happen before any read, last write will not
6407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // actually queue a frame, due to window size being 0.
6408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               vector_as_array(&writes), writes.size());
6410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<UploadElementReader> element_readers;
6412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  upload_data_string.append(kUploadData, kUploadDataSize);
6414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  element_readers.push_back(new UploadBytesElementReader(
6415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      upload_data_string.c_str(), upload_data_string.size()));
641668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  UploadDataStream upload_data_stream(element_readers.Pass(), 0);
6417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo request;
6419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.method = "POST";
6420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.url = GURL("http://www.google.com/");
6421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.upload_data_stream = &upload_data_stream;
6422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
64235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
64245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.SetDeterministic();
64255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
64265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddDeterministicData(&data);
64275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
64285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
64295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
6431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
64325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
64335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(num_writes - 1);   // Write as much as we can.
64355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream != NULL);
6438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream->stream() != NULL);
6439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, stream->stream()->send_window_size());
64405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // All the body data should have been read.
6442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(satorux): This is because of the weirdness in reading the request
6443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // body in OnSendBodyComplete(). See crbug.com/113107.
6444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(upload_data_stream.IsEOF());
6445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // But the body is not yet fully sent (kUploadData is not yet sent)
6446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // since we're send-stalled.
6447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
64485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read in WINDOW_UPDATE or SETTINGS frame.
6450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 9 : 8);
6451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
64525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
64535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
64545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
64551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_P(SpdyNetworkTransactionTest, GoAwayOnOddPushStreamId) {
64561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (spdy_util_.spdy_version() < SPDY3)
64571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
64581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
64591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<SpdyHeaderBlock> push_headers(new SpdyHeaderBlock);
64601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spdy_util_.AddUrlToHeaderBlock("http://www.google.com/a.dat",
64611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 push_headers.get());
64621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<SpdyFrame> push(
64631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      spdy_util_.ConstructInitialSpdyPushFrame(push_headers.Pass(), 3, 1));
64641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MockRead reads[] = {CreateMockRead(*push, 1)};
64651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
64661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<SpdyFrame> req(
64671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
64681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
64691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      0, GOAWAY_PROTOCOL_ERROR, "Odd push stream id."));
64701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MockWrite writes[] = {
64711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 2),
64721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  };
64731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
64741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
64751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  NormalSpdyTransactionHelper helper(
64761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
64771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  helper.RunToCompletion(&data);
64781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TransactionHelperResult out = helper.output();
64791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
64801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
64811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
64821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_P(SpdyNetworkTransactionTest,
64831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       GoAwayOnPushStreamIdLesserOrEqualThanLastAccepted) {
64841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (spdy_util_.spdy_version() < SPDY3)
64851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
64861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
64871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<SpdyFrame> push_a(spdy_util_.ConstructSpdyPush(
64881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      NULL, 0, 4, 1, "http://www.google.com/a.dat"));
64891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<SpdyHeaderBlock> push_b_headers(new SpdyHeaderBlock);
64901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  spdy_util_.AddUrlToHeaderBlock("http://www.google.com/b.dat",
64911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 push_b_headers.get());
64921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<SpdyFrame> push_b(
64931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      spdy_util_.ConstructInitialSpdyPushFrame(push_b_headers.Pass(), 2, 1));
64941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MockRead reads[] = {
64951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      CreateMockRead(*push_a, 1), CreateMockRead(*push_b, 2),
64961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  };
64971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
64981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<SpdyFrame> req(
64991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
65001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<SpdyFrame> goaway(spdy_util_.ConstructSpdyGoAway(
65011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      4,
65021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GOAWAY_PROTOCOL_ERROR,
65031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      "New push stream id must be greater than the last accepted."));
65041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MockWrite writes[] = {
65051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      CreateMockWrite(*req, 0), CreateMockWrite(*goaway, 3),
65061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  };
65071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
65081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
65091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  NormalSpdyTransactionHelper helper(
65101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      CreateGetRequest(), DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
65111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  helper.RunToCompletion(&data);
65121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TransactionHelperResult out = helper.output();
65131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
65141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
65151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6516cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class SpdyNetworkTransactionNoTLSUsageCheckTest
6517cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : public SpdyNetworkTransactionTest {
6518cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) protected:
6519cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void RunNoTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6520cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Construct the request.
6521cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyGet(
6522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        "https://www.google.com/", false, 1, LOWEST));
6523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MockWrite writes[] = {CreateMockWrite(*req)};
6524cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6525cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6526cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6527cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MockRead reads[] = {
6528cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        CreateMockRead(*resp), CreateMockRead(*body),
6529cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        MockRead(ASYNC, 0, 0)  // EOF
6530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    };
6531cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6532cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DelayedSocketData data(
6533cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        1, reads, arraysize(reads), writes, arraysize(writes));
6534cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    HttpRequestInfo request;
6535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    request.method = "GET";
6536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    request.url = GURL("https://www.google.com/");
6537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    NormalSpdyTransactionHelper helper(
6538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    TransactionHelperResult out = helper.output();
6541cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EXPECT_EQ(OK, out.rv);
6542cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
6543cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EXPECT_EQ("hello!", out.response_data);
6544cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
6545cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
6546cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6547cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//-----------------------------------------------------------------------------
6548cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// All tests are run with three different connection types: SPDY after NPN
6549cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// negotiation, SPDY without SSL, and SPDY with SSL.
6550cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//
6551cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// TODO(akalin): Use ::testing::Combine() when we are able to use
6552cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// <tr1/tuple>.
6553cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(
6554cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Spdy,
6555cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SpdyNetworkTransactionNoTLSUsageCheckTest,
6556cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ::testing::Values(SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2,
6557cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                       SPDYNPN),
6558cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                      SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNPN),
6559cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                      SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN)));
6560cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6561cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSVersionTooOld) {
6562cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SSLSocketDataProvider> ssl_provider(
6563cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new SSLSocketDataProvider(ASYNC, OK));
6564cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6565cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                &ssl_provider->connection_status);
6566cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6567cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RunNoTLSUsageCheckTest(ssl_provider.Pass());
6568cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
6569cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6570cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdyNetworkTransactionNoTLSUsageCheckTest, TLSCipherSuiteSucky) {
6571cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SSLSocketDataProvider> ssl_provider(
6572cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new SSLSocketDataProvider(ASYNC, OK));
6573cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Set to TLS_RSA_WITH_NULL_MD5
6574cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6575cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6576cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RunNoTLSUsageCheckTest(ssl_provider.Pass());
6577cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
6578cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6579cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class SpdyNetworkTransactionTLSUsageCheckTest
6580cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : public SpdyNetworkTransactionTest {
6581cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) protected:
6582cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void RunTLSUsageCheckTest(scoped_ptr<SSLSocketDataProvider> ssl_provider) {
6583f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_ptr<SpdyFrame> goaway(
6584f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        spdy_util_.ConstructSpdyGoAway(0, GOAWAY_INADEQUATE_SECURITY, ""));
6585f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    MockWrite writes[] = {CreateMockWrite(*goaway)};
6586f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
6587f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DelayedSocketData data(1, NULL, 0, writes, arraysize(writes));
6588cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    HttpRequestInfo request;
6589cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    request.method = "GET";
6590cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    request.url = GURL("https://www.google.com/");
6591cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    NormalSpdyTransactionHelper helper(
6592cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        request, DEFAULT_PRIORITY, BoundNetLog(), GetParam(), NULL);
6593cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    helper.RunToCompletionWithSSLData(&data, ssl_provider.Pass());
6594cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    TransactionHelperResult out = helper.output();
6595cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EXPECT_EQ(ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, out.rv);
6596cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
6597cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
6598cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6599cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(
6600cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Spdy,
6601cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SpdyNetworkTransactionTLSUsageCheckTest,
6602cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ::testing::Values(SpdyNetworkTransactionTestParams(kProtoSPDY4, SPDYNPN)));
6603cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6604cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSVersionTooOld) {
6605cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SSLSocketDataProvider> ssl_provider(
6606cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new SSLSocketDataProvider(ASYNC, OK));
6607cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_SSL3,
6608cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                &ssl_provider->connection_status);
6609cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6610cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RunTLSUsageCheckTest(ssl_provider.Pass());
6611cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
6612cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6613cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTLSUsageCheckTest, TLSCipherSuiteSucky) {
6614cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<SSLSocketDataProvider> ssl_provider(
6615cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new SSLSocketDataProvider(ASYNC, OK));
6616cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Set to TLS_RSA_WITH_NULL_MD5
6617cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SSLConnectionStatusSetCipherSuite(0x1, &ssl_provider->connection_status);
6618cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6619cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RunTLSUsageCheckTest(ssl_provider.Pass());
6620cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
6621cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
66225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
6623