spdy_network_transaction_unittest.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
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"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/scoped_temp_dir.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h"
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/stl_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/auth.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log_unittest.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/request_priority.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_bytes_element_reader.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/upload_data_stream.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_file_element_reader.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_session_peer.h"
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "net/http/http_network_transaction.h"
227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "net/http/http_server_properties.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_transaction_unittest.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_pool_base.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/socket/next_proto.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/buffered_spdy_framer.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_http_stream.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_http_utils.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session_pool.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_test_util_common.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_test_utils.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_test_util.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/platform_test.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kRequestUrl[] = "http://www.google.com/";
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)enum SpdyNetworkTransactionTestSSLType {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SPDYNPN,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SPDYNOSSL,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SPDYSSL,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)struct SpdyNetworkTransactionTestParams {
507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SpdyNetworkTransactionTestParams()
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      : protocol(kProtoSPDY2),
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        ssl_type(SPDYNPN) {}
537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SpdyNetworkTransactionTestParams(
557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      NextProto protocol,
567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      SpdyNetworkTransactionTestSSLType ssl_type)
577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      : protocol(protocol),
587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        ssl_type(ssl_type) {}
597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  NextProto protocol;
617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SpdyNetworkTransactionTestSSLType ssl_type;
627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)};
637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)HttpResponseInfo::ConnectionInfo NextProtoToConnectionInfo(
657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    NextProto next_proto) {
667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  switch (next_proto) {
677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kProtoSPDY2:
687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return HttpResponseInfo::CONNECTION_INFO_SPDY2;
697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kProtoSPDY3:
707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kProtoSPDY31:
717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return HttpResponseInfo::CONNECTION_INFO_SPDY3;
727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kProtoSPDY4a2:
737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return HttpResponseInfo::CONNECTION_INFO_SPDY4;
747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    case kProtoQUIC1SPDY3:
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return HttpResponseInfo::CONNECTION_INFO_QUIC1_SPDY3;
767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kProtoUnknown:
787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kProtoHTTP11:
797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kProtoSPDY1:
807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kProtoSPDY21:
817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      break;
827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  NOTREACHED();
857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return HttpResponseInfo::CONNECTION_INFO_SPDY2;
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)SpdySessionDependencies* CreateSpdySessionDependencies(
897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SpdyNetworkTransactionTestParams test_params) {
907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return new SpdySessionDependencies(test_params.protocol);
917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)SpdySessionDependencies* CreateSpdySessionDependencies(
947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SpdyNetworkTransactionTestParams test_params,
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ProxyService* proxy_service) {
967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return new SpdySessionDependencies(test_params.protocol, proxy_service);
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}  // namespace
1007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)class SpdyNetworkTransactionTest
1027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : public ::testing::TestWithParam<SpdyNetworkTransactionTestParams> {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SpdyNetworkTransactionTest() : spdy_util_(GetParam().protocol) {
105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    google_get_request_initialized_ = false;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    google_post_request_initialized_ = false;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    google_chunked_post_request_initialized_ = false;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Empty the current queue.
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->RunUntilIdle();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct TransactionHelperResult {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string status_line;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string response_data;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpResponseInfo response_info;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A helper class that handles all the initial npn/ssl setup.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class NormalSpdyTransactionHelper {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NormalSpdyTransactionHelper(const HttpRequestInfo& request,
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                RequestPriority priority,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const BoundNetLog& log,
1327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                SpdyNetworkTransactionTestParams test_params,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                SpdySessionDependencies* session_deps)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : request_(request),
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          priority_(priority),
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_deps_(session_deps == NULL ?
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        CreateSpdySessionDependencies(test_params) :
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                        session_deps),
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_(SpdySessionDependencies::SpdyCreateSession(
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       session_deps_.get())),
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          log_(log),
1427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          test_params_(test_params),
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          deterministic_(false),
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          spdy_enabled_(true) {
1457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      switch (test_params_.ssl_type) {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case SPDYNOSSL:
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case SPDYSSL:
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          port_ = 80;
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case SPDYNPN:
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          port_ = 443;
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        default:
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          NOTREACHED();
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~NormalSpdyTransactionHelper() {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Any test which doesn't close the socket by sending it an EOF will
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // have a valid session left open, which leaks the entire session pool.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is just fine - in fact, some of our tests intentionally do this
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // so that we can check consistency of the SpdySessionPool as the test
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // finishes.  If we had put an EOF on the socket, the SpdySession would
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // have closed and we wouldn't be able to check the consistency.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Forcefully close existing sessions here.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session()->spdy_session_pool()->CloseAllSessions();
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void SetDeterministic() {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_deps_.get());
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      deterministic_ = true;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void SetSpdyDisabled() {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      spdy_enabled_ = false;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      port_ = 80;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void RunPreTestSetup() {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!session_deps_.get())
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        session_deps_.reset(CreateSpdySessionDependencies(test_params_));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!session_.get())
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        session_ = SpdySessionDependencies::SpdyCreateSession(
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            session_deps_.get());
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HttpStreamFactory::set_use_alternate_protocols(false);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HttpStreamFactory::set_force_spdy_over_ssl(false);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HttpStreamFactory::set_force_spdy_always(false);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
191ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      std::vector<NextProto> next_protos = SpdyNextProtos();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      switch (test_params_.ssl_type) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case SPDYNPN:
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          session_->http_server_properties()->SetAlternateProtocol(
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              HostPortPair("www.google.com", 80), 443,
197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch              AlternateProtocolFromNextProto(test_params_.protocol));
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          HttpStreamFactory::set_use_alternate_protocols(true);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          HttpStreamFactory::SetNextProtos(next_protos);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case SPDYNOSSL:
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          HttpStreamFactory::set_force_spdy_over_ssl(false);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          HttpStreamFactory::set_force_spdy_always(true);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case SPDYSSL:
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          HttpStreamFactory::set_force_spdy_over_ssl(true);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          HttpStreamFactory::set_force_spdy_always(true);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NOTREACHED();
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We're now ready to use SSL-npn SPDY.
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      trans_.reset(new HttpNetworkTransaction(priority_, session_.get()));
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start the transaction, read some data, finish.
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void RunDefaultTest() {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!StartDefaultTest())
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FinishDefaultTest();
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool StartDefaultTest() {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output_.rv = trans_->Start(&request_, callback.callback(), log_);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We expect an IO Pending or some sort of error.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_LT(output_.rv, 0);
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return output_.rv == ERR_IO_PENDING;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void FinishDefaultTest() {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output_.rv = callback.WaitForResult();
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (output_.rv != OK) {
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        session_->spdy_session_pool()->CloseCurrentSessions(net::ERR_ABORTED);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Verify responses.
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const HttpResponseInfo* response = trans_->GetResponseInfo();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(response != NULL);
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ASSERT_TRUE(response->headers.get() != NULL);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(spdy_enabled_, response->was_fetched_via_spdy);
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (HttpStreamFactory::spdy_enabled()) {
2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        EXPECT_EQ(NextProtoToConnectionInfo(test_params_.protocol),
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  response->connection_info);
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  response->connection_info);
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (test_params_.ssl_type == SPDYNPN && spdy_enabled_) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_TRUE(response->was_npn_negotiated);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_TRUE(!response->was_npn_negotiated);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If SPDY is not enabled, a HTTP request should not be diverted
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // over a SSL session.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!spdy_enabled_) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(request_.url.SchemeIs("https"),
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  response->was_npn_negotiated);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_EQ("127.0.0.1", response->socket_address.host());
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_EQ(port_, response->socket_address.port());
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output_.status_line = response->headers->GetStatusLine();
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output_.response_info = *response;  // Make a copy so we can verify.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output_.rv = ReadTransaction(trans_.get(), &output_.response_data);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Most tests will want to call this function. In particular, the MockReads
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // should end with an empty read, and that read needs to be processed to
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // ensure proper deletion of the spdy_session_pool.
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void VerifyDataConsumed() {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (DataVector::iterator it = data_vector_.begin();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          it != data_vector_.end(); ++it) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_TRUE((*it)->at_read_eof()) << "Read count: "
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          << (*it)->read_count()
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          << " Read index: "
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          << (*it)->read_index();
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_TRUE((*it)->at_write_eof()) << "Write count: "
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           << (*it)->write_count()
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           << " Write index: "
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           << (*it)->write_index();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Occasionally a test will expect to error out before certain reads are
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // processed. In that case we want to explicitly ensure that the reads were
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // not processed.
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void VerifyDataNotConsumed() {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (DataVector::iterator it = data_vector_.begin();
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          it != data_vector_.end(); ++it) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_TRUE(!(*it)->at_read_eof()) << "Read count: "
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           << (*it)->read_count()
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           << " Read index: "
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           << (*it)->read_index();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_TRUE(!(*it)->at_write_eof()) << "Write count: "
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            << (*it)->write_count()
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            << " Write index: "
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            << (*it)->write_index();
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void RunToCompletion(StaticSocketDataProvider* data) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RunPreTestSetup();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddData(data);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RunDefaultTest();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VerifyDataConsumed();
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void AddData(StaticSocketDataProvider* data) {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(!deterministic_);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_vector_.push_back(data);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SSLSocketDataProvider* ssl_provider =
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new SSLSocketDataProvider(ASYNC, OK);
3167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (test_params_.ssl_type == SPDYNPN)
3177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        ssl_provider->SetNextProto(test_params_.protocol);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_vector_.push_back(ssl_provider);
3207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (test_params_.ssl_type == SPDYNPN || test_params_.ssl_type == SPDYSSL)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        session_deps_->socket_factory->AddSSLSocketDataProvider(ssl_provider);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_deps_->socket_factory->AddSocketDataProvider(data);
3247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (test_params_.ssl_type == SPDYNPN) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        StaticSocketDataProvider* hanging_non_alternate_protocol_socket =
3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            new StaticSocketDataProvider(NULL, 0, NULL, 0);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hanging_non_alternate_protocol_socket->set_connect_data(
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            never_finishing_connect);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        session_deps_->socket_factory->AddSocketDataProvider(
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            hanging_non_alternate_protocol_socket);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        alternate_vector_.push_back(hanging_non_alternate_protocol_socket);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void AddDeterministicData(DeterministicSocketData* data) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(deterministic_);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_vector_.push_back(data);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SSLSocketDataProvider* ssl_provider =
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new SSLSocketDataProvider(ASYNC, OK);
3417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (test_params_.ssl_type == SPDYNPN)
3427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        ssl_provider->SetNextProto(test_params_.protocol);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_vector_.push_back(ssl_provider);
3457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (test_params_.ssl_type == SPDYNPN ||
3467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          test_params_.ssl_type == SPDYSSL) {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        session_deps_->deterministic_socket_factory->
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            AddSSLSocketDataProvider(ssl_provider);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_deps_->deterministic_socket_factory->AddSocketDataProvider(data);
3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (test_params_.ssl_type == SPDYNPN) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DeterministicSocketData* hanging_non_alternate_protocol_socket =
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            new DeterministicSocketData(NULL, 0, NULL, 0);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hanging_non_alternate_protocol_socket->set_connect_data(
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            never_finishing_connect);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        session_deps_->deterministic_socket_factory->AddSocketDataProvider(
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            hanging_non_alternate_protocol_socket);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        alternate_deterministic_vector_.push_back(
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            hanging_non_alternate_protocol_socket);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void SetSession(const scoped_refptr<HttpNetworkSession>& session) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_ = session;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpNetworkTransaction* trans() { return trans_.get(); }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void ResetTrans() { trans_.reset(); }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionHelperResult& output() { return output_; }
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HttpRequestInfo& request() const { return request_; }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<HttpNetworkSession>& session() const {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return session_;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdySessionDependencies>& session_deps() {
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return session_deps_;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int port() const { return port_; }
3787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SpdyNetworkTransactionTestParams test_params() const {
3797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return test_params_;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef std::vector<StaticSocketDataProvider*> DataVector;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef ScopedVector<SSLSocketDataProvider> SSLVector;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef ScopedVector<StaticSocketDataProvider> AlternateVector;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef ScopedVector<DeterministicSocketData> AlternateDeterministicVector;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo request_;
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RequestPriority priority_;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdySessionDependencies> session_deps_;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<HttpNetworkSession> session_;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionHelperResult output_;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<StaticSocketDataProvider> first_transaction_;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSLVector ssl_vector_;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestCompletionCallback callback;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpNetworkTransaction> trans_;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpNetworkTransaction> trans_http_;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DataVector data_vector_;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AlternateVector alternate_vector_;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AlternateDeterministicVector alternate_deterministic_vector_;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BoundNetLog& log_;
4017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SpdyNetworkTransactionTestParams test_params_;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int port_;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool deterministic_;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool spdy_enabled_;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             int expected_status);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ConnectStatusHelper(const MockRead& status);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpRequestInfo& CreateGetPushRequest() {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    google_get_push_request_.method = "GET";
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    google_get_push_request_.url = GURL("http://www.google.com/foo.dat");
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    google_get_push_request_.load_flags = 0;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return google_get_push_request_;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpRequestInfo& CreateGetRequest() {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!google_get_request_initialized_) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_.method = "GET";
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_.url = GURL(kDefaultURL);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_.load_flags = 0;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_initialized_ = true;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return google_get_request_;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpRequestInfo& CreateGetRequestWithUserAgent() {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!google_get_request_initialized_) {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_.method = "GET";
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_.url = GURL(kDefaultURL);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_.load_flags = 0;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_.extra_headers.SetHeader("User-Agent", "Chrome");
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_get_request_initialized_ = true;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return google_get_request_;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpRequestInfo& CreatePostRequest() {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!google_post_request_initialized_) {
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ScopedVector<UploadElementReader> element_readers;
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      element_readers.push_back(
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new UploadBytesElementReader(kUploadData, kUploadDataSize));
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      upload_data_stream_.reset(new UploadDataStream(&element_readers, 0));
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_.method = "POST";
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_.url = GURL(kDefaultURL);
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      google_post_request_.upload_data_stream = upload_data_stream_.get();
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_initialized_ = true;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return google_post_request_;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpRequestInfo& CreateFilePostRequest() {
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!google_post_request_initialized_) {
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath file_path;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK_EQ(static_cast<int>(kUploadDataSize),
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               file_util::WriteFile(file_path, kUploadData, kUploadDataSize));
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ScopedVector<UploadElementReader> element_readers;
4637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      element_readers.push_back(
4647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          new UploadFileElementReader(base::MessageLoopProxy::current().get(),
4657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      file_path,
4667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      0,
4677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      kUploadDataSize,
4687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      base::Time()));
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      upload_data_stream_.reset(new UploadDataStream(&element_readers, 0));
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_.method = "POST";
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_.url = GURL(kDefaultURL);
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      google_post_request_.upload_data_stream = upload_data_stream_.get();
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_initialized_ = true;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return google_post_request_;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpRequestInfo& CreateComplexPostRequest() {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!google_post_request_initialized_) {
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int kFileRangeOffset = 1;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int kFileRangeLength = 3;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath file_path;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK_EQ(static_cast<int>(kUploadDataSize),
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               file_util::WriteFile(file_path, kUploadData, kUploadDataSize));
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ScopedVector<UploadElementReader> element_readers;
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      element_readers.push_back(
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new UploadBytesElementReader(kUploadData, kFileRangeOffset));
4937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      element_readers.push_back(
4947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          new UploadFileElementReader(base::MessageLoopProxy::current().get(),
4957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      file_path,
4967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      kFileRangeOffset,
4977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      kFileRangeLength,
4987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      base::Time()));
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      element_readers.push_back(new UploadBytesElementReader(
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kUploadData + kFileRangeOffset + kFileRangeLength,
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      upload_data_stream_.reset(new UploadDataStream(&element_readers, 0));
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_.method = "POST";
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_.url = GURL(kDefaultURL);
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      google_post_request_.upload_data_stream = upload_data_stream_.get();
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_post_request_initialized_ = true;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return google_post_request_;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpRequestInfo& CreateChunkedPostRequest() {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!google_chunked_post_request_initialized_) {
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      upload_data_stream_.reset(
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          new UploadDataStream(UploadDataStream::CHUNKED, 0));
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_chunked_post_request_.method = "POST";
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_chunked_post_request_.url = GURL(kDefaultURL);
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      google_chunked_post_request_.upload_data_stream =
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          upload_data_stream_.get();
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      google_chunked_post_request_initialized_ = true;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return google_chunked_post_request_;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read the result of a particular transaction, knowing that we've got
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // multiple transactions in the read pipeline; so as we read, we may have
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to skip over data destined for other transactions while we consume
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the data for |trans|.
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ReadResult(HttpNetworkTransaction* trans,
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 StaticSocketDataProvider* data,
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 std::string* result) {
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kSize = 3000;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int bytes_read = 0;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(kSize));
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestCompletionCallback callback;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (true) {
538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      int rv = trans->Read(buf.get(), kSize, callback.callback());
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rv == ERR_IO_PENDING) {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Multiple transactions may be in the data set.  Keep pulling off
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // reads until we complete our callback.
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (!callback.have_result()) {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          data->CompleteRead();
54490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          base::MessageLoop::current()->RunUntilIdle();
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = callback.WaitForResult();
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (rv <= 0) {
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result->append(buf->data(), rv);
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytes_read += rv;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return bytes_read;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void VerifyStreamsClosed(const NormalSpdyTransactionHelper& helper) {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This lengthy block is reaching into the pool to dig out the active
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // session.  Once we have the session, we verify that the streams are
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // all closed and not leaked at this point.
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url = helper.request().url;
5617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    int port = helper.test_params().ssl_type == SPDYNPN ? 443 : 80;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HostPortPair host_port_pair(url.host(), port);
56390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
56490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       kPrivacyModeDisabled);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BoundNetLog log;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<HttpNetworkSession>& session = helper.session();
567ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    base::WeakPtr<SpdySession> spdy_session =
5687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        session->spdy_session_pool()->FindAvailableSession(key, log);
5697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ASSERT_TRUE(spdy_session != NULL);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, spdy_session->num_active_streams());
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, spdy_session->num_unclaimed_pushed_streams());
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunServerPushTest(OrderedSocketData* data,
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         HttpResponseInfo* response,
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         HttpResponseInfo* push_response,
577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         const std::string& expected) {
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       BoundNetLog(), GetParam(), NULL);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.RunPreTestSetup();
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.AddData(data);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpNetworkTransaction* trans = helper.trans();
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start the transaction with basic parameters.
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestCompletionCallback callback;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = trans->Start(
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &CreateGetRequest(), callback.callback(), BoundNetLog());
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERR_IO_PENDING, rv);
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = callback.WaitForResult();
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Request the pushed path.
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpNetworkTransaction> trans2(
594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = trans2->Start(
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERR_IO_PENDING, rv);
59890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->RunUntilIdle();
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // The data for the pushed path may be coming in more than 1 frame. Compile
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the results into a single string.
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read the server push body.
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string result2;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReadResult(trans2.get(), data, &result2);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read the response body.
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string result;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReadResult(trans, data, &result);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify that we consumed all test data.
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(data->at_read_eof());
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(data->at_write_eof());
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify that the received push data is same as the expected push data.
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(result2.compare(expected), 0) << "Received data: "
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            << result2
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            << "||||| Expected data: "
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            << expected;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify the SYN_REPLY.
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Copy the response info, because trans goes away.
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *response = *trans->GetResponseInfo();
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *push_response = *trans2->GetResponseInfo();
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VerifyStreamsClosed(helper);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void DeleteSessionCallback(NormalSpdyTransactionHelper* helper,
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int result) {
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper->ResetTrans();
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void StartTransactionCallback(
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<HttpNetworkSession>& session,
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int result) {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpNetworkTransaction> trans(
637868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestCompletionCallback callback;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo request;
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request.method = "GET";
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request.url = GURL("http://www.google.com/");
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request.load_flags = 0;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERR_IO_PENDING, rv);
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback.WaitForResult();
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
648b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  SpdyTestUtil spdy_util_;
649b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<UploadDataStream> upload_data_stream_;
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool google_get_request_initialized_;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool google_post_request_initialized_;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool google_chunked_post_request_initialized_;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo google_get_request_;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo google_post_request_;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo google_chunked_post_request_;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo google_get_push_request_;
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ScopedTempDir temp_dir_;
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All tests are run with three different connection types: SPDY after NPN
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// negotiation, SPDY without SSL, and SPDY with SSL.
6657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)//
6667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// TODO(akalin): Use ::testing::Combine() when we are able to use
6677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// <tr1/tuple>.
6687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(
6697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    Spdy,
6707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SpdyNetworkTransactionTest,
6717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ::testing::Values(
6727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY2, SPDYNOSSL),
6737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY2, SPDYSSL),
6747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY2, SPDYNPN),
6757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNOSSL),
6767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYSSL),
6777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNPN),
6787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNOSSL),
6797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYSSL),
6807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY31, SPDYNPN),
6817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY4a2, SPDYNOSSL),
6827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY4a2, SPDYSSL),
6837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        SpdyNetworkTransactionTestParams(kProtoSPDY4a2, SPDYNPN)));
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify HttpNetworkTransaction constructor.
6867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, Constructor) {
687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SpdySessionDependencies> session_deps(
6887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      CreateSpdySessionDependencies(GetParam()));
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<HttpNetworkSession> session(
690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SpdySessionDependencies::SpdyCreateSession(session_deps.get()));
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<HttpTransaction> trans(
692868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, Get) {
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the request.
69790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
69890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req) };
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
7027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (RequestPriority p = MINIMUM_PRIORITY; p < NUM_PRIORITIES;
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       p = RequestPriority(p + 1)) {
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Construct the request.
72490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_ptr<SpdyFrame> req(
72590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, p, true));
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite writes[] = { CreateMockWrite(*req) };
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SpdyPriority spdy_prio = 0;
7297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_TRUE(GetSpdyPriority(spdy_util_.spdy_version(), *req, &spdy_prio));
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this repeats the RequestPriority-->SpdyPriority mapping from
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SpdyFramer::ConvertRequestPriorityToSpdyPriority to make
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // sure it's being done right.
7337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (spdy_util_.spdy_version() < SPDY3) {
7347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      switch(p) {
7357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case HIGHEST:
7367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(0, spdy_prio);
7377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
7387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case MEDIUM:
7397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(1, spdy_prio);
7407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
7417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case LOW:
7427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case LOWEST:
7437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(2, spdy_prio);
7447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
7457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case IDLE:
7467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(3, spdy_prio);
7477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
7487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        default:
7497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          FAIL();
7507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
7517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    } else {
7527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      switch(p) {
7537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case HIGHEST:
7547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(0, spdy_prio);
7557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
7567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case MEDIUM:
7577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(1, spdy_prio);
7587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
7597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case LOW:
7607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(2, spdy_prio);
7617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
7627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case LOWEST:
7637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(3, spdy_prio);
7647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
7657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        case IDLE:
7667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          EXPECT_EQ(4, spdy_prio);
7677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          break;
7687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        default:
7697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          FAIL();
7707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
7747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead reads[] = {
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*resp),
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*body),
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockRead(ASYNC, 0, 0)  // EOF
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelayedSocketData data(1, reads, arraysize(reads),
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              writes, arraysize(writes));
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo http_req = CreateGetRequest();
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NormalSpdyTransactionHelper helper(http_req, p, BoundNetLog(),
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       GetParam(), NULL);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.RunToCompletion(&data);
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionHelperResult out = helper.output();
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, out.rv);
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("hello!", out.response_data);
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start three gets simultaniously; making sure that multiplexed
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// streams work properly.
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This can't use the TransactionHelper method, since it only
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// handles a single transaction, and finishes them as soon
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as it launches them.
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(gavinp): create a working generalized TransactionHelper that
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can allow multiple streams in flight.
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ThreeGets) {
80690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
80790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
8107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
81290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
81390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
8147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
8157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
8167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
81890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req3(
81990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
8207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
8217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
8227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req2),
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req3),
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp, 1),
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp2, 4),
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body2),
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp3, 7),
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body3),
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody),
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody2),
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody3),
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0),  // EOF
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog log;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out;
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We require placeholder data because three get requests are sent out, so
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there needs to be three sets of SSL connection data.
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans1(
858868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans2(
860868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans3(
862868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback3;
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq1 = CreateGetRequest();
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq2 = CreateGetRequest();
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq3 = CreateGetRequest();
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback1.WaitForResult();
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback3.WaitForResult();
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
885868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response1->headers.get() != NULL);
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response1->was_fetched_via_spdy);
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response1->headers->GetStatusLine();
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response1;
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  trans2->GetResponseInfo();
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans1.get(), &out.response_data);
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) {
90290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
90390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
9067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
90890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
90990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
9107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
9117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
9127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req2),
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp, 1),
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp2, 4),
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body2),
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody),
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody2),
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0),  // EOF
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_placeholder.set_connect_data(never_finishing_connect);
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog log;
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out;
9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We require placeholder data because two get requests are sent out, so
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there needs to be two sets of SSL connection data.
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans1(
945868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans2(
947868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq1 = CreateGetRequest();
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq2 = CreateGetRequest();
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback1.WaitForResult();
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback2.WaitForResult();
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
966868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response1->headers.get() != NULL);
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response1->was_fetched_via_spdy);
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response1->headers->GetStatusLine();
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response1;
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans1.get(), &out.response_data);
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
976868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response2->headers.get() != NULL);
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response2->was_fetched_via_spdy);
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response2->headers->GetStatusLine();
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response2;
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans2.get(), &out.response_data);
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) {
98990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
99090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
9937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
99590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
99690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
9977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
9987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
9997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req2),
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp, 1),
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp2, 4),
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body2),
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody),
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody2),
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0),  // EOF
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData preconnect_data(reads, arraysize(reads),
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    writes, arraysize(writes));
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect never_finishing_connect(ASYNC, ERR_IO_PENDING);
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_placeholder.set_connect_data(never_finishing_connect);
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog log;
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out;
10242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&preconnect_data);
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We require placeholder data because 3 connections are attempted (first is
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the preconnect, 2nd and 3rd are the never finished connections.
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans1(
1034868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans2(
1036868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq = CreateGetRequest();
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Preconnect the first.
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLConfig preconnect_ssl_config;
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.session()->ssl_config_service()->GetSSLConfig(&preconnect_ssl_config);
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpStreamFactory* http_stream_factory =
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      helper.session()->http_stream_factory();
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (http_stream_factory->has_next_protos()) {
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    preconnect_ssl_config.next_protos = http_stream_factory->next_protos();
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  http_stream_factory->PreconnectStreams(
10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1, httpreq, DEFAULT_PRIORITY,
10542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      preconnect_ssl_config, preconnect_ssl_config);
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans1->Start(&httpreq, callback1.callback(), log);
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans2->Start(&httpreq, callback2.callback(), log);
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback1.WaitForResult();
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback2.WaitForResult();
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1067868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response1->headers.get() != NULL);
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response1->was_fetched_via_spdy);
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response1->headers->GetStatusLine();
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response1;
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans1.get(), &out.response_data);
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
1077868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response2->headers.get() != NULL);
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response2->was_fetched_via_spdy);
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response2->headers->GetStatusLine();
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response2;
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans2.get(), &out.response_data);
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Similar to ThreeGets above, however this test adds a SETTINGS
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// frame.  The SETTINGS frame is read during the IO loop waiting on
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the first transaction completion, and sets a maximum concurrent
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stream limit of 1.  This means that our IO loop exists after the
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// second transaction completes, so we can assert on read_index().
10947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) {
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the request.
109690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
109790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
10987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
11007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
110290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
110390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
11047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
11067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
110890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req3(
110990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, LOWEST, true));
11107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
11117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, false));
11127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(5, true));
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsMap settings;
11152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const uint32 max_concurrent_streams = 1;
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
111890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
111990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(settings));
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req2),
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req3),
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*settings_frame, 1),
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody),
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp2, 7),
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body2),
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody2),
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp3, 12),
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body3),
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody3),
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0),  // EOF
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog log;
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out;
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
11492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       BoundNetLog(), GetParam(), NULL);
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.RunPreTestSetup();
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.AddData(&data);
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We require placeholder data because three get requests are sent out, so
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // there needs to be three sets of SSL connection data.
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.AddData(&data_placeholder);
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.AddData(&data_placeholder);
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpNetworkTransaction> trans1(
1158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpNetworkTransaction> trans2(
1160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpNetworkTransaction> trans3(
1162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestCompletionCallback callback1;
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestCompletionCallback callback2;
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestCompletionCallback callback3;
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo httpreq1 = CreateGetRequest();
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo httpreq2 = CreateGetRequest();
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo httpreq3 = CreateGetRequest();
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(out.rv, ERR_IO_PENDING);
11747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // Run transaction 1 through quickly to force a read of our SETTINGS
11757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // frame.
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = callback1.WaitForResult();
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(OK, out.rv);
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(out.rv, ERR_IO_PENDING);
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(out.rv, ERR_IO_PENDING);
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = callback2.WaitForResult();
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(OK, out.rv);
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(7U, data.read_index());  // i.e. the third trans was queued
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = callback3.WaitForResult();
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(OK, out.rv);
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HttpResponseInfo* response1 = trans1->GetResponseInfo();
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(response1 != NULL);
1192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_TRUE(response1->headers.get() != NULL);
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(response1->was_fetched_via_spdy);
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.status_line = response1->headers->GetStatusLine();
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.response_info = *response1;
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = ReadTransaction(trans1.get(), &out.response_data);
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, out.rv);
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("hello!hello!", out.response_data);
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HttpResponseInfo* response2 = trans2->GetResponseInfo();
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.status_line = response2->headers->GetStatusLine();
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.response_info = *response2;
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = ReadTransaction(trans2.get(), &out.response_data);
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, out.rv);
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("hello!hello!", out.response_data);
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HttpResponseInfo* response3 = trans3->GetResponseInfo();
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.status_line = response3->headers->GetStatusLine();
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.response_info = *response3;
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.rv = ReadTransaction(trans3.get(), &out.response_data);
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, out.rv);
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("hello!hello!", out.response_data);
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.VerifyDataConsumed();
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Similar to ThreeGetsWithMaxConcurrent above, however this test adds
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a fourth transaction.  The third and fourth transactions have
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// different data ("hello!" vs "hello!hello!") and because of the
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// user specified priority, we expect to see them inverted in
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the response from the server.
12277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) {
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the request.
122990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
123090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
12317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
12327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
12337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
123590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
123690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
12377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
12387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
12397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> req4(
124290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, HIGHEST, true));
12437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp4(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
12447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody4(spdy_util_.ConstructSpdyBodyFrame(5, true));
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
124690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req3(
124790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 7, LOWEST, true));
12487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 7));
12497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(7, false));
12507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody3(spdy_util_.ConstructSpdyBodyFrame(7, true));
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsMap settings;
12532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const uint32 max_concurrent_streams = 1;
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
125690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
125790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(settings));
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req),
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req2),
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req4),
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req3),
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*settings_frame, 1),
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody),
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp2, 7),
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body2),
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody2),
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp4, 13),
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody4),
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp3, 16),
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body3),
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody3),
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0),  // EOF
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog log;
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out;
12872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
12882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We require placeholder data because four get requests are sent out, so
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there needs to be four sets of SSL connection data.
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans1(
1297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans2(
1299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans3(
1301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans4(
1303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(HIGHEST, helper.session().get()));
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback3;
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback4;
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq1 = CreateGetRequest();
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq2 = CreateGetRequest();
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq3 = CreateGetRequest();
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq4 = CreateGetRequest();
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run transaction 1 through quickly to force a read of our SETTINGS frame.
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback1.WaitForResult();
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans4->Start(&httpreq4, callback4.callback(), log);
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, out.rv);
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback2.WaitForResult();
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(data.read_index(), 7U);  // i.e. the third & fourth trans queued
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback3.WaitForResult();
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
1336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response1->headers.get() != NULL);
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response1->was_fetched_via_spdy);
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response1->headers->GetStatusLine();
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response1;
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans1.get(), &out.response_data);
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response2->headers->GetStatusLine();
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response2;
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans2.get(), &out.response_data);
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notice: response3 gets two hellos, response4 gets one
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // hello, so we know dequeuing priority was respected.
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response3 = trans3->GetResponseInfo();
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response3->headers->GetStatusLine();
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response3;
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans3.get(), &out.response_data);
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback4.WaitForResult();
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response4 = trans4->GetResponseInfo();
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response4->headers->GetStatusLine();
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response4;
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans4.get(), &out.response_data);
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Similar to ThreeGetsMaxConcurrrent above, however, this test
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deletes a session in the middle of the transaction to insure
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that we properly remove pendingcreatestream objects from
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the spdy_session
13807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) {
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the request.
138290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
138390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
13847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
13857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
13867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody(spdy_util_.ConstructSpdyBodyFrame(1, true));
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
138890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
138990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
13907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
13917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, false));
13927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fbody2(spdy_util_.ConstructSpdyBodyFrame(3, true));
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsMap settings;
13952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const uint32 max_concurrent_streams = 1;
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
139890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
139990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(settings));
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req),
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req2),
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*settings_frame, 1),
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody),
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp2, 7),
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body2),
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fbody2),
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0),  // EOF
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog log;
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out;
14212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
14222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We require placeholder data because three get requests are sent out, so
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there needs to be three sets of SSL connection data.
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans1(
1430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans2(
1432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans3(
1434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback3;
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq1 = CreateGetRequest();
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq2 = CreateGetRequest();
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq3 = CreateGetRequest();
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans1->Start(&httpreq1, callback1.callback(), log);
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(out.rv, ERR_IO_PENDING);
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run transaction 1 through quickly to force a read of our SETTINGS frame.
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback1.WaitForResult();
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans2->Start(&httpreq2, callback2.callback(), log);
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(out.rv, ERR_IO_PENDING);
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete trans3.release();
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(out.rv, ERR_IO_PENDING);
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback2.WaitForResult();
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(8U, data.read_index());
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response1 = trans1->GetResponseInfo();
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(response1 != NULL);
1462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response1->headers.get() != NULL);
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response1->was_fetched_via_spdy);
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response1->headers->GetStatusLine();
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response1;
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans1.get(), &out.response_data);
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response2 = trans2->GetResponseInfo();
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(response2 != NULL);
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response2->headers->GetStatusLine();
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response2;
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(trans2.get(), &out.response_data);
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!hello!", out.response_data);
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The KillerCallback will delete the transaction on error as part of the
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// callback.
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class KillerCallback : public TestCompletionCallbackBase {
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit KillerCallback(HttpNetworkTransaction* transaction)
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : transaction_(transaction),
1491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        callback_(base::Bind(&KillerCallback::OnComplete,
1492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             base::Unretained(this))) {
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~KillerCallback() {}
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const CompletionCallback& callback() const { return callback_; }
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnComplete(int result) {
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result < 0)
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete transaction_;
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetResult(result);
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* transaction_;
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback callback_;
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Similar to ThreeGetsMaxConcurrrentDelete above, however, this test
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// closes the socket while we have a pending transaction waiting for
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a pending stream creation.  http://crbug.com/52901
15167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentSocketClose) {
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the request.
151890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
151990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
15207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
15217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, false));
15227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> fin_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
152490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req2(
152590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
15267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SettingsMap settings;
15292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const uint32 max_concurrent_streams = 1;
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SettingsFlagsAndValue(SETTINGS_FLAG_NONE, max_concurrent_streams);
153290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame(
153390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdySettings(settings));
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req),
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req2),
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*settings_frame, 1),
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*fin_body),
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp2, 7),
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_CONNECTION_RESET, 0),  // Abort!
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data_placeholder(NULL, 0, NULL, 0);
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog log;
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out;
15532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
15542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We require placeholder data because three get requests are sent out, so
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there needs to be three sets of SSL connection data.
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data_placeholder);
1561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session().get());
1562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session().get());
15632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HttpNetworkTransaction* trans3(
1564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback1;
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback2;
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  KillerCallback callback3(trans3);
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq1 = CreateGetRequest();
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq2 = CreateGetRequest();
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo httpreq3 = CreateGetRequest();
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans1.Start(&httpreq1, callback1.callback(), log);
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(out.rv, ERR_IO_PENDING);
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run transaction 1 through quickly to force a read of our SETTINGS frame.
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback1.WaitForResult();
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, out.rv);
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans2.Start(&httpreq2, callback2.callback(), log);
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(out.rv, ERR_IO_PENDING);
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = trans3->Start(&httpreq3, callback3.callback(), log);
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(out.rv, ERR_IO_PENDING);
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback3.WaitForResult();
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_ABORTED, out.rv);
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(6U, data.read_index());
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response1 = trans1.GetResponseInfo();
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(response1 != NULL);
1591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response1->headers.get() != NULL);
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response1->was_fetched_via_spdy);
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response1->headers->GetStatusLine();
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response1;
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(&trans1, &out.response_data);
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response2 = trans2.GetResponseInfo();
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(response2 != NULL);
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response2->headers->GetStatusLine();
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response2;
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = ReadTransaction(&trans2, &out.response_data);
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_RESET, out.rv);
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a simple PUT request works.
16097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, Put) {
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup the request
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo request;
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.method = "PUT";
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.url = GURL("http://www.google.com/");
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdyHeaderInfo kSynStartHeader = {
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SYN_STREAM,             // Kind = Syn
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1,                      // Stream ID
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                      // Associated stream ID
16197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ConvertRequestPriorityToSpdyPriority(
16207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        LOWEST, spdy_util_.spdy_version()),
16217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    kSpdyCredentialSlotUnused,
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CONTROL_FLAG_FIN,       // Control Flags
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    false,                  // Compressed
16242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RST_STREAM_INVALID,     // Status
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NULL,                   // Data
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                      // Length
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DATA_FLAG_NONE          // Data Flags
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
16297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> put_headers(
16307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructPutHeaderBlock("http://www.google.com", 0));
1631b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyFrame(
16327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      kSynStartHeader, put_headers.Pass()));
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
163490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CreateMockWrite(*req),
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdyHeaderInfo kSynReplyHeader = {
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SYN_REPLY,              // Kind = SynReply
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1,                      // Stream ID
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                      // Associated stream ID
16427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ConvertRequestPriorityToSpdyPriority(
16437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        LOWEST, spdy_util_.spdy_version()),
16447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    kSpdyCredentialSlotUnused,
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CONTROL_FLAG_NONE,      // Control Flags
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    false,                  // Compressed
16472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RST_STREAM_INVALID,     // Status
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NULL,                   // Data
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                      // Length
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DATA_FLAG_NONE          // Data Flags
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
16527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
16537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
16547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
16557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  (*reply_headers)["content-length"] = "1234";
1656b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyFrame(
16577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      kSynReplyHeader, reply_headers.Pass()));
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
16662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a simple HEAD request works.
16767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, Head) {
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup the request
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo request;
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.method = "HEAD";
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.url = GURL("http://www.google.com/");
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdyHeaderInfo kSynStartHeader = {
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SYN_STREAM,             // Kind = Syn
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1,                      // Stream ID
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                      // Associated stream ID
16867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ConvertRequestPriorityToSpdyPriority(
16877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        LOWEST, spdy_util_.spdy_version()),
16887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    kSpdyCredentialSlotUnused,
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CONTROL_FLAG_FIN,       // Control Flags
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    false,                  // Compressed
16912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RST_STREAM_INVALID,     // Status
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NULL,                   // Data
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                      // Length
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DATA_FLAG_NONE          // Data Flags
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
16967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> head_headers(
16977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructHeadHeaderBlock("http://www.google.com", 0));
1698b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyFrame(
16997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      kSynStartHeader, head_headers.Pass()));
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
170190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CreateMockWrite(*req),
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdyHeaderInfo kSynReplyHeader = {
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SYN_REPLY,              // Kind = SynReply
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1,                      // Stream ID
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                      // Associated stream ID
17097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ConvertRequestPriorityToSpdyPriority(
17107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        LOWEST, spdy_util_.spdy_version()),
17117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    kSpdyCredentialSlotUnused,
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CONTROL_FLAG_NONE,      // Control Flags
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    false,                  // Compressed
17142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RST_STREAM_INVALID,     // Status
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NULL,                   // Data
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                      // Length
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DATA_FLAG_NONE          // Data Flags
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
17197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
17207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
17217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
17227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  (*reply_headers)["content-length"] = "1234";
1723b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyFrame(
1724b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      kSynReplyHeader,
17257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      reply_headers.Pass()));
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
17342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a simple POST works.
17447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, Post) {
17452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
17467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
17477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
17487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*body),  // POST upload frame
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(2, reads, arraysize(reads),
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
17632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a POST with a file works.
17737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, FilePost) {
17742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
17757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
17767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
17777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*body),  // POST upload frame
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(2, reads, arraysize(reads),
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
17922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateFilePostRequest(), DEFAULT_PRIORITY,
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a complex POST works.
18027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
18032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
18047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
18057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
18067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*body),  // POST upload frame
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(2, reads, arraysize(reads),
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateComplexPostRequest(),
18222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     DEFAULT_PRIORITY,
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a chunked POST works.
18327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ChunkedPost) {
18337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
18347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
18352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockWrite writes[] = {
18362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*req),
18372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*body),
18382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
18392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
18412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockRead reads[] = {
18422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*resp),
18432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*body),
18442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
18452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DelayedSocketData data(2, reads, arraysize(reads),
18482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         writes, arraysize(writes));
18492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
18502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     DEFAULT_PRIORITY,
18512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
18522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // These chunks get merged into a single frame when being sent.
18542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kFirstChunkSize = kUploadDataSize/2;
18552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.request().upload_data_stream->AppendChunk(
18562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kUploadData, kFirstChunkSize, false);
18572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.request().upload_data_stream->AppendChunk(
18582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kUploadData + kFirstChunkSize, kUploadDataSize - kFirstChunkSize, true);
18592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.RunToCompletion(&data);
18612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TransactionHelperResult out = helper.output();
18622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, out.rv);
18632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
18642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kUploadData, out.response_data);
18652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
18662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Test that a chunked POST works with chunks appended after transaction starts.
18687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) {
18697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
18707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false));
18717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> chunk2(spdy_util_.ConstructSpdyBodyFrame(1, false));
18727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true));
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*chunk1),
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*chunk2),
18772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockWrite(*chunk3),
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*chunk1),
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*chunk2),
18852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateMockRead(*chunk3),
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DelayedSocketData data(4, reads, arraysize(reads),
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateChunkedPostRequest(),
18922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     DEFAULT_PRIORITY,
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.request().upload_data_stream->AppendChunk(
18962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kUploadData, kUploadDataSize, false);
18972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.RunPreTestSetup();
18992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.AddData(&data);
19002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(helper.StartDefaultTest());
19012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
190290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
19032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.request().upload_data_stream->AppendChunk(
19042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kUploadData, kUploadDataSize, false);
190590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
19062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.request().upload_data_stream->AppendChunk(
19072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kUploadData, kUploadDataSize, true);
19082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.FinishDefaultTest();
19102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  helper.VerifyDataConsumed();
19112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string expected_response;
19132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_response += kUploadData;
19142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_response += kUploadData;
19152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_response += kUploadData;
19162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
19202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected_response, out.response_data);
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a POST without any post data works.
19247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, NullPost) {
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup the request
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo request;
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.method = "POST";
19282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request.url = GURL(kRequestUrl);
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create an empty UploadData.
19302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request.upload_data_stream = NULL;
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // When request.upload_data_stream is NULL for post, content-length is
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // expected to be 0.
19342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
19357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(kRequestUrl, 1, 0, LOWEST, NULL, 0));
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the FIN bit since there will be no body.
19377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test::SetFrameFlags(req.get(), CONTROL_FLAG_FIN, spdy_util_.spdy_version());
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
19437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that a simple POST works.
19637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
19642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create an empty UploadDataStream.
19652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedVector<UploadElementReader> element_readers;
19662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UploadDataStream stream(&element_readers, 0);
19672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup the request
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo request;
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.method = "POST";
19717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  request.url = GURL(kRequestUrl);
19722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request.upload_data_stream = &stream;
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint64 kContentLength = 0;
19752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
19767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
19777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kRequestUrl, 1, kContentLength, LOWEST, NULL, 0));
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the FIN bit since there will be no body.
19797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test::SetFrameFlags(req.get(), CONTROL_FLAG_FIN, spdy_util_.spdy_version());
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
19857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// While we're doing a post, the server sends back a SYN_REPLY.
20047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, PostWithEarlySynReply) {
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char upload[] = { "hello!" };
20062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedVector<UploadElementReader> element_readers;
20072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  element_readers.push_back(
20082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new UploadBytesElementReader(upload, sizeof(upload)));
20092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UploadDataStream stream(&element_readers, 0);
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup the request
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo request;
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.method = "POST";
20147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  request.url = GURL(kRequestUrl);
20152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request.upload_data_stream = &stream;
20162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> stream_reply(
20187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*stream_reply, 1),
2021ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockRead(ASYNC, 0, 4)  // EOF
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
20257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
20267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          kRequestUrl, 1, kUploadDataSize, LOWEST, NULL, 0));
20277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2028ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<SpdyFrame> rst(
2029ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req, 0),
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*body, 2),
2033ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    CreateMockWrite(*rst, 3)
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
20382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreatePostRequest(), DEFAULT_PRIORITY,
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.SetDeterministic();
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddDeterministicData(&data);
20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreatePostRequest(), callback.callback(), BoundNetLog());
20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2050ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.RunFor(4);
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback.WaitForResult();
20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.RunFor(1);
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The client upon cancellation tries to send a RST_STREAM frame. The mock
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// socket causes the TCP write to return zero. This test checks that the client
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// tries to queue up the RST_STREAM frame again.
20597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) {
206090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
206190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> rst(
206390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req.get(), 0, SYNCHRONOUS),
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(SYNCHRONOUS, 0, 0, 2),
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp.get(), 1, ASYNC),
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0, 4)  // EOF
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
20782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.SetDeterministic();
20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddDeterministicData(&data);
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetStop(2);
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.Run();
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.ResetTrans();
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetStop(20);
20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.Run();
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that the transaction doesn't crash when we don't have a reply.
21007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ResponseWithoutSynReply) {
21017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads), NULL, 0);
21082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
2112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that the transaction doesn't crash when we get two replies on the same
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stream ID. See http://crbug.com/45639.
21177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) {
211890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
211990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
2121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_STREAM_IN_USE));
2122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req),
2124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*rst),
2125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
21287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback.WaitForResult();
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, rv);
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response = trans->GetResponseInfo();
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(response != NULL);
2154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response->headers.get() != NULL);
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response->was_fetched_via_spdy);
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_data;
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = ReadTransaction(trans, &response_data);
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) {
2164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct the request.
2165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
2166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
2168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
2170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req),
2171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*rst),
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char* const headers[] = {
2175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "transfer-encoding", "chunked"
2176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(
2178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGetSynReply(headers, 1, 1));
2179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(
2180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp),
2183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body),
2184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(1, reads, arraysize(reads),
2188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
2189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
21902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
2191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunToCompletion(&data);
2192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out = helper.output();
2193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
21942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.session()->spdy_session_pool()->CloseAllSessions();
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ResetPushWithTransferEncoding) {
2200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct the request.
220190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
220290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
2204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*req),
2207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*rst),
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char* const headers[] = {
2212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "transfer-encoding", "chunked"
2213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> push(
2215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPush(headers, arraysize(headers) / 2,
2216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   2, 1, "http://www.google.com/1"));
2217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
2220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*push),
2221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body),
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
22272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
2229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunToCompletion(&data);
2230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out = helper.output();
2231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, out.rv);
2232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
2233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello!", out.response_data);
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.session()->spdy_session_pool()->CloseAllSessions();
2236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
2237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, CancelledTransaction) {
2240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct the request.
2241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
2242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req),
2245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp),
2250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // This following read isn't used by the test, except during the
2251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // RunUntilIdle() call at the end since the SpdySession survives the
2252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // HttpNetworkTransaction and still tries to continue Read()'ing.  Any
2253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // MockRead will do here.
2254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
2255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StaticSocketDataProvider data(reads, arraysize(reads),
2258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                writes, arraysize(writes));
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
2262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
2263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
2264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
2267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
2268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
2269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
2270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.ResetTrans();  // Cancel the transaction.
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
2273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // MockClientSocketFactory) are still alive.
227490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
2275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataNotConsumed();
22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verify that the client sends a Rst Frame upon cancelling the stream.
2279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) {
2280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
2281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> rst(
2283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
2285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0, SYNCHRONOUS),
2286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*rst, 2, SYNCHRONOUS),
22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1, ASYNC),
2292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 3)  // EOF
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(),
2300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     GetParam(), NULL);
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.SetDeterministic();
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddDeterministicData(&data);
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
2309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
2310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.SetStop(2);
2313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.Run();
2314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.ResetTrans();
2315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.SetStop(20);
2316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.Run();
23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
2319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verify that the client can correctly deal with the user callback attempting
2322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// to start another transaction on a session that is closing down. See
2323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// http://crbug.com/47455
2324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) {
2325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
2326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
2328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes2[] = { CreateMockWrite(*req) };
23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The indicated length of this frame is longer than its actual length. When
2331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // the session receives an empty frame after this one, it shuts down the
2332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // session, and calls the read callback with the incomplete data.
2333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const uint8 kGetBodyFrame2[] = {
2334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    0x00, 0x00, 0x00, 0x01,
2335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    0x01, 0x00, 0x00, 0x07,
2336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    'h', 'e', 'l', 'l', 'o', '!',
2337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 2),
2342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 3),  // Force a pause
2343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, reinterpret_cast<const char*>(kGetBodyFrame2),
2344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch             arraysize(kGetBodyFrame2), 4),
2345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 5),  // Force a pause
2346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 6),  // EOF
2347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads2[] = {
2349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 2),
2350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 3),  // EOF
23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
2354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
2355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data2(1, reads2, arraysize(reads2),
2356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          writes2, arraysize(writes2));
23572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
23592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
2361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
2362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data2);
23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction with basic parameters.
23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback.WaitForResult();
23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int kSize = 3000;
2372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = trans->Read(
2374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      buf.get(),
2375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSize,
2376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&SpdyNetworkTransactionTest::StartTransactionCallback,
2377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 helper.session()));
2378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // This forces an err_IO_pending, which sets the callback.
2379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.CompleteRead();
2380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // This finishes the read.
2381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.CompleteRead();
2382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
2383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verify that the client can correctly deal with the user callback deleting the
2386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// transaction. Failures will usually be valgrind errors. See
2387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// http://crbug.com/46925
2388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) {
2389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
2390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp.get(), 2),
2397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 3),  // Force a pause
2398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body.get(), 4),
2399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 5),  // EOF
24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
2403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
24042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
24062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
2408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction with basic parameters.
24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
2415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Setup a user callback which will delete the session, and clear out the
2418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // memory holding the stream object. Note that the callback deletes trans.
2419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int kSize = 3000;
2420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSize));
2421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = trans->Read(
2422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      buf.get(),
2423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSize,
2424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&SpdyNetworkTransactionTest::DeleteSessionCallback,
2425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 base::Unretained(&helper)));
2426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING, rv);
2427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.CompleteRead();
24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Finish running rest of tasks.
2430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Send a spdy request to www.google.com that gets redirected to www.foo.com.
2435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
2436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const SpdyHeaderInfo kSynStartHeader = spdy_util_.MakeSpdyHeader(SYN_STREAM);
2437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
2438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*headers)["user-agent"] = "";
2440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*headers)["accept-encoding"] = "gzip,deflate";
2441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
2442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*headers2)["user-agent"] = "";
2444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*headers2)["accept-encoding"] = "gzip,deflate";
24457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Setup writes/reads to www.google.com
2447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyFrame(
2448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSynStartHeader, headers.Pass()));
2449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyFrame(
2450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSynStartHeader, headers2.Pass()));
2451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReplyRedirect(1));
2452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 1),
2454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 2),
2457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 3)  // EOF
2458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Setup writes/reads to www.foo.com
2461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes2[] = {
2464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
2465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads2[] = {
2467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 2),
2468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body2, 3),
2469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 4)  // EOF
2470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
2472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
2473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data2(reads2, arraysize(reads2),
2474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          writes2, arraysize(writes2));
24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpStreamFactory::set_force_spdy_over_ssl(false);
2478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpStreamFactory::set_force_spdy_always(true);
2479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestDelegate d;
2480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  {
2481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
2482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    net::URLRequest r(
2483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        GURL("http://www.google.com/"), &d, &spdy_url_request_context);
2484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    spdy_url_request_context.socket_factory().
2485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        AddSocketDataProvider(&data);
2486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    spdy_url_request_context.socket_factory().
2487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        AddSocketDataProvider(&data2);
24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    d.set_quit_on_redirect(true);
2490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    r.Start();
2491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::MessageLoop::current()->Run();
24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(1, d.received_redirect_count());
24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    r.FollowDeferredRedirect();
2496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::MessageLoop::current()->Run();
2497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(1, d.response_started_count());
2498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_FALSE(d.received_data_before_response());
2499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(net::URLRequestStatus::SUCCESS, r.status().status());
2500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string contents("hello!");
2501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(contents, d.data_received());
2502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof());
2504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
2505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data2.at_read_eof());
2506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data2.at_write_eof());
2507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Send a spdy request to www.google.com. Get a pushed stream that redirects to
2510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// www.foo.com.
2511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
2512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const SpdyHeaderInfo kSynStartHeader = spdy_util_.MakeSpdyHeader(SYN_STREAM);
25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
2515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock("http://www.google.com/"));
2516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*headers)["user-agent"] = "";
2517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*headers)["accept-encoding"] = "gzip,deflate";
25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Setup writes/reads to www.google.com
2520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
2521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyFrame(kSynStartHeader, headers.Pass()));
2522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rep(
2524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyPush(NULL,
2525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        0,
2526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        2,
2527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        1,
2528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        "http://www.google.com/foo.dat",
2529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        "301 Moved Permanently",
2530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        "http://www.foo.com/index.php"));
2531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
2533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
2534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 1),
2536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*rst, 6),
2537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
2539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 2),
2540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*rep, 3),
2541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body, 4),
2542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 5),  // Force a pause
2543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 7)  // EOF
25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Setup writes/reads to www.foo.com
2547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers2(
2548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock("http://www.foo.com/index.php"));
2549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*headers2)["user-agent"] = "";
2550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*headers2)["accept-encoding"] = "gzip,deflate";
2551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
2552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyFrame(kSynStartHeader, headers2.Pass()));
2553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
2555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes2[] = {
2556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 1),
2557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads2[] = {
2559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 2),
2560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body2, 3),
2561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 5)  // EOF
2562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
2563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
2564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
2565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data2(reads2, arraysize(reads2),
2566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                          writes2, arraysize(writes2));
25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(erikchen): Make test support SPDYSSL, SPDYNPN
2569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpStreamFactory::set_force_spdy_over_ssl(false);
2570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpStreamFactory::set_force_spdy_always(true);
2571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestDelegate d;
2572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestDelegate d2;
2573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
2574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  {
2575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    net::URLRequest r(
2576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        GURL("http://www.google.com/"), &d, &spdy_url_request_context);
2577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    spdy_url_request_context.socket_factory().
2578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        AddSocketDataProvider(&data);
25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    r.Start();
2581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::MessageLoop::current()->Run();
25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(0, d.received_redirect_count());
2584eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string contents("hello!");
2585eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(contents, d.data_received());
25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    net::URLRequest r2(
2588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        GURL("http://www.google.com/foo.dat"), &d2, &spdy_url_request_context);
2589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    spdy_url_request_context.socket_factory().
2590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        AddSocketDataProvider(&data2);
25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    d2.set_quit_on_redirect(true);
2593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    r2.Start();
2594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::MessageLoop::current()->Run();
2595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(1, d2.received_redirect_count());
25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    r2.FollowDeferredRedirect();
2598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::MessageLoop::current()->Run();
2599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(1, d2.response_started_count());
2600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_FALSE(d2.received_data_before_response());
2601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(net::URLRequestStatus::SUCCESS, r2.status().status());
2602eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string contents2("hello!");
2603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(contents2, d2.data_received());
2604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.CompleteRead();
2606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data2.CompleteRead();
2607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof());
2608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
2609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data2.at_read_eof());
2610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data2.at_write_eof());
26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame) {
2614eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
261590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
2617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
2619eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
2628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
2630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
2631eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
2632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
2633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
2636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
2637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2638eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 5),
2639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
2643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
2644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed");
2645eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
2647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunServerPushTest(&data,
2648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response,
2649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response2,
2650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    expected_push_result);
26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
2653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
2654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
2657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
2658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
26607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushBeforeSynReply) {
2662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
266390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
2665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
2667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
2676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
2678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
2679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
2680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
2681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 2),
2684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 3),
2685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 4, SYNCHRONOUS),
2686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 5),
2687eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
2691eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
2692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed");
2693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
2695eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunServerPushTest(&data,
2696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response,
2697eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response2,
2698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    expected_push_result);
26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
2701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
2702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
2705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
2706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
2707eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
27087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2709eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushSingleDataFrame2) {
2710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
271190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2712eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = { CreateMockWrite(*stream1_syn, 1), };
27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2715eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2719eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
2720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2721eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
2722eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
2723eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
2724eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
2725eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
2726eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2727eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2729eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
2730eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
2731eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 4),
2732eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2733eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
2737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
2738eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed");
2739eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
2740eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
2741eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunServerPushTest(&data,
2742eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response,
2743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response2,
2744eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    expected_push_result);
27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2746eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
2747eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
2748eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
2751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
2752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushServerAborted) {
2756eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
275790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2758eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
2759eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
2761eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2764eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2765eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2766eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2767eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2768eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2769eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
2770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
2772eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_rst(
2773eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
2776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
2777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_rst, 4),
2778eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
2779eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2782eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
2783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
27842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
2785eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
2786eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
2788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
2789eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction with basic parameters.
27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
2797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
2798eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv);
27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2800eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
2801eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof()) << "Read count: "
2802eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_count()
2803eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << " Read index: "
2804eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_index();
2805eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof()) << "Write count: "
2806eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_count()
2807eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << " Write index: "
2808eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_index();
28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
2811eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response = *trans->GetResponseInfo();
2812eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
2813eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2816eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verify that we don't leak streams and that we properly send a reset
2817eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// if the server pushes the same stream twice.
2818eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushDuplicate) {
2819eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
282090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2821eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
2822eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
2823eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream3_rst(
2824eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(4, RST_STREAM_PROTOCOL_ERROR));
2825eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2826eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
2827eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream3_rst, 5),
28285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
28295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2832eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2833eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2834eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2835eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
2836eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2837eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
2838eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
2839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
2840eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
2841eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
2842eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2843eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream3_syn(spdy_util_.ConstructSpdyPush(NULL,
2844eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2845eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    4,
2846eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2847eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
28485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2849eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
2850eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
2851eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream3_syn, 4),
2852eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 6, SYNCHRONOUS),
2853eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 7),
2854eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 8),  // Force a pause
28555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
28565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2857eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
2858eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
2859eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed");
28605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
28615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
2862eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunServerPushTest(&data,
2863eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response,
2864eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response2,
2865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    expected_push_result);
28665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2867eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
2868eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
2869eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
28705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2871eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
2872eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
2873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
28745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2876eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrame) {
2877eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
287890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2879eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
2880eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
2881eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
2882eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
2883eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
28845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2886eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2887eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2888eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2889eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2890eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
2891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
2893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static const char kPushedData[] = "pushed my darling hello my baby";
2894eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body_base(
2895eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
2896eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
2897eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const size_t kChunkSize = strlen(kPushedData) / 4;
2898eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body1(
2899eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2900eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body2(
2901eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2902eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body3(
2903eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2904eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    kChunkSize, false));
2905eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body4(
2906eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    stream2_body_base->size() - 3 * kChunkSize, false));
29085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2909eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
2910eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
2911eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body1, 4),
2912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body2, 5),
2913eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body3, 6),
2914eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body4, 7),
2915eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 8, SYNCHRONOUS),
2916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 9),  // Force a pause
29175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
29185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2919eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
2920eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
2921eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed my darling hello my baby");
29225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
29235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
2924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunServerPushTest(&data, &response, &response2, kPushedData);
29255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2926eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
2927eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
2928eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
29295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2930eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
2931eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
2932eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
29335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushMultipleDataFrameInterrupted) {
2936eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
2937eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2938eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
2939eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
29405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
2941eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
29425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2943eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2944eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2945eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2946eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
2947eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
2948eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
2949eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
2950eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    1,
2951eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
2952eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static const char kPushedData[] = "pushed my darling hello my baby";
2953eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body_base(
2954eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
2955eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
2956eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const size_t kChunkSize = strlen(kPushedData) / 4;
2957eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body1(
2958eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data(), kChunkSize, false));
2959eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body2(
2960eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data() + kChunkSize, kChunkSize, false));
2961eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body3(
2962eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data() + 2 * kChunkSize,
2963eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    kChunkSize, false));
2964eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body4(
2965eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new SpdyFrame(stream2_body_base->data() + 3 * kChunkSize,
2966eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    stream2_body_base->size() - 3 * kChunkSize, false));
29675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
2968eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
2969eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
2970eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body1, 4),
2971eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body2, 5),
2972eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 6),  // Force a pause
2973eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body3, 7),
2974eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body4, 8),
2975eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body.get(), 9, SYNCHRONOUS),
2976eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 10)  // Force a pause.
29775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
29785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2979eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
2980eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
29815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
29825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
2983eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunServerPushTest(&data, &response, &response2, kPushedData);
29845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
2986eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
2987eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
29885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2989eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
2990eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
2991eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
29925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2994eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID0) {
2995eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
299690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
2997eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
2998eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
2999eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_rst(
3000eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
30015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
3002eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
3003eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream2_rst, 4),
30045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
30055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame>
3007eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3008eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
3009eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3010eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
3011eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
3012eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
3013eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
30145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
3015eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
3016eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
3017eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 4),
3018eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 5)  // Force a pause
30195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
30205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
30225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
30232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
30245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
30255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3026eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
3027eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
30287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3029eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
30305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3031eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction with basic parameters.
3032eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
3033eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
3034eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
3035eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
3036eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
3037eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv);
30387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3039eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
3040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_count()
3042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << " Read index: "
3043eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_index();
3044eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3045eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_count()
3046eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << " Write index: "
3047eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_index();
30485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3049eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
3050eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response = *trans->GetResponseInfo();
3051eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
3052eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
30535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushInvalidAssociatedStreamID9) {
3056eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
305790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
3059eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
3060eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_rst(
3061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_INVALID_STREAM));
30625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
3063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
3064eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream2_rst, 4),
30655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
30665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame>
3068eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
30695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame>
3070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
3071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    0,
3072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    2,
3073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    9,
3074eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    "http://www.google.com/foo.dat"));
30755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
3076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
3077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
3078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 4),
3079eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 5),  // Force a pause
30805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
30815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
30835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
30842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
30855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
30867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3087eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
3088eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
30895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
30915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction with basic parameters.
3093eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
3094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
3095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
3096eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
3097eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
3098eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv);
30995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
3101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_count()
3103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << " Read index: "
3104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_index();
3105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_count()
3107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << " Write index: "
3108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_index();
31095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
3111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response = *trans->GetResponseInfo();
3112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
3113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
31145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushNoURL) {
311790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> stream1_syn(
311890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
31197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> stream1_body(
31207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, true));
3121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_rst(
3122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
31235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
31245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*stream1_syn, 1),
3125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream2_rst, 4),
31265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
31275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame>
31297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> incomplete_headers(new SpdyHeaderBlock());
3131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*incomplete_headers)["hello"] = "bye";
3132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*incomplete_headers)[spdy_util_.GetStatusKey()] = "200 OK";
3133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*incomplete_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
3134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_syn(
3135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(incomplete_headers.Pass(),
3136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
3137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           2,  // Stream ID
3138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
3139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           SYN_STREAM,
3140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
3141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           // Associated stream ID
3142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           1));
31435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
31445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*stream1_reply, 2),
31455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*stream2_syn, 3),
3146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 4),
3147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 5)  // Force a pause
31485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
31495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
31515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
3152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
3153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
31547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
3156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
31575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
31595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction with basic parameters.
3161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
3162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
3163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
3164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
3165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
3166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv);
3167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
3168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof()) << "Read count: "
3169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_count()
3170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << " Read index: "
3171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_index();
3172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof()) << "Write count: "
3173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_count()
3174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << " Write index: "
3175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_index();
31765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the SYN_REPLY.
3178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response = *trans->GetResponseInfo();
3179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response.headers.get() != NULL);
31805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
31815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verify that various SynReply headers parse correctly through the
3184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// HTTP layer.
3185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, SynReplyHeaders) {
3186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  struct SynReplyHeadersTests {
3187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int num_headers;
3188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const char* extra_headers[5];
3189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SpdyHeaderBlock expected_headers;
3190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } test_cases[] = {
3191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // This uses a multi-valued cookie header.
3192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { 2,
3193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      { "cookie", "val1",
3194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        "cookie", "val2",  // will get appended separated by NULL
3195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        NULL
3196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      },
3197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    },
3198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // This is the minimalist set of headers.
3199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { 0,
3200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      { NULL },
3201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    },
3202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Headers with a comma separated list.
3203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    { 1,
3204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      { "cookie", "val1,val2",
3205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        NULL
3206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      },
3207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
32085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
32095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[0].expected_headers["cookie"] = "val1";
32117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[0].expected_headers["cookie"] += '\0';
32127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[0].expected_headers["cookie"] += "val2";
32137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[0].expected_headers["hello"] = "bye";
32147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[0].expected_headers["status"] = "200";
32157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[0].expected_headers["version"] = "HTTP/1.1";
32167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
32177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[1].expected_headers["hello"] = "bye";
32187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[1].expected_headers["status"] = "200";
32197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[1].expected_headers["version"] = "HTTP/1.1";
32207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
32217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[2].expected_headers["cookie"] = "val1,val2";
32227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[2].expected_headers["hello"] = "bye";
32237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[2].expected_headers["status"] = "200";
32247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test_cases[2].expected_headers["version"] = "HTTP/1.1";
32257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
32265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
32275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdyFrame> req(
322890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
32295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite writes[] = { CreateMockWrite(*req) };
32305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdyFrame> resp(
32327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        spdy_util_.ConstructSpdyGetSynReply(test_cases[i].extra_headers,
32335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 test_cases[i].num_headers,
32345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 1));
32357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
32365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead reads[] = {
32375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*resp),
32385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*body),
32395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockRead(ASYNC, 0, 0)  // EOF
32405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
32415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelayedSocketData data(1, reads, arraysize(reads),
32435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           writes, arraysize(writes));
32442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
32455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       BoundNetLog(), GetParam(), NULL);
32465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.RunToCompletion(&data);
32475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionHelperResult out = helper.output();
32485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, out.rv);
32505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
32515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("hello!", out.response_data);
32525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
32545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(headers.get() != NULL);
32555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* iter = NULL;
32567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    std::string name, value;
32577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    SpdyHeaderBlock header_block;
32585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
32597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (header_block[name].empty()) {
32607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        header_block[name] = value;
32617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      } else {
32627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        header_block[name] += '\0';
32637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        header_block[name] += value;
32647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
32655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
32667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    EXPECT_EQ(test_cases[i].expected_headers, header_block);
32675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that various SynReply headers parse vary fields correctly
32715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// through the HTTP layer, and the response matches the request.
32727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, SynReplyHeadersVary) {
32735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const SpdyHeaderInfo syn_reply_info = {
32745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SYN_REPLY,                              // Syn Reply
32755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1,                                      // Stream ID
32765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                                      // Associated Stream ID
32777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ConvertRequestPriorityToSpdyPriority(
32787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        LOWEST, spdy_util_.spdy_version()),
32797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    kSpdyCredentialSlotUnused,
32805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CONTROL_FLAG_NONE,                      // Control Flags
32815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    false,                                  // Compressed
32822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RST_STREAM_INVALID,                     // Status
32835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NULL,                                   // Data
32845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                                      // Data Length
32855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DATA_FLAG_NONE                          // Data Flags
32865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
32875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Modify the following data to change/add test cases:
32885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct SynReplyTests {
32895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SpdyHeaderInfo* syn_reply;
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)      &syn_reply_info,
32985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
32995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { 1, 4 },
33005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { { "cookie",   "val1,val2",
33015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        },
33037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        { "vary",     "cookie",
33047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetStatusKey(), "200",
33057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetPathKey(),      "/index.php",
33067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetVersionKey(), "HTTP/1.1",
33075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
33095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
33105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }, {    // Multiple vary fields.
33115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &syn_reply_info,
33125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
33135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { 2, 5 },
33145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { { "friend",   "barney",
33155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "enemy",    "snaggletooth",
33165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        },
33187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        { "vary",     "friend",
33195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "vary",     "enemy",
33207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetStatusKey(), "200",
33217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetPathKey(),      "/index.php",
33227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetVersionKey(), "HTTP/1.1",
33235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
33255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
33265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }, {    // Test a '*' vary field.
33275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &syn_reply_info,
33285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false,
33295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { 1, 4 },
33305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { { "cookie",   "val1,val2",
33315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        },
33337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        { "vary",     "*",
33347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetStatusKey(), "200",
33357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetPathKey(),      "/index.php",
33367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetVersionKey(), "HTTP/1.1",
33375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
33395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
33405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }, {    // Multiple comma-separated vary fields.
33415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &syn_reply_info,
33425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      true,
33435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { 2, 4 },
33445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { { "friend",   "barney",
33455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "enemy",    "snaggletooth",
33465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        },
33487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        { "vary",     "friend,enemy",
33497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetStatusKey(), "200",
33507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetPathKey(),      "/index.php",
33517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          spdy_util_.GetVersionKey(), "HTTP/1.1",
33525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL
33535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
33545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
33555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
33565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
33575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
33595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Construct the request.
33605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdyFrame> frame_req(
336190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        spdy_util_.ConstructSpdyGet(test_cases[i].extra_headers[0],
336290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    test_cases[i].num_headers[0],
336390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    false, 1, LOWEST, true));
33645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite writes[] = {
33665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockWrite(*frame_req),
33675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
33685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Construct the reply.
33705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdyFrame> frame_reply(
33717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyFrame(*test_cases[i].syn_reply,
33727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    test_cases[i].extra_headers[1],
33737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    test_cases[i].num_headers[1],
33747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    NULL,
33757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    0));
33765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
33785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead reads[] = {
33795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*frame_reply),
33805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*body),
33815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockRead(ASYNC, 0, 0)  // EOF
33825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
33835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Attach the headers to the request.
33855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int header_count = test_cases[i].num_headers[0];
33865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo request = CreateGetRequest();
33885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int ct = 0; ct < header_count; ct++) {
33895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char* header_key = test_cases[i].extra_headers[0][ct * 2];
33905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char* header_value = test_cases[i].extra_headers[0][ct * 2 + 1];
33915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request.extra_headers.SetHeader(header_key, header_value);
33925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
33935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelayedSocketData data(1, reads, arraysize(reads),
33955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           writes, arraysize(writes));
33962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
33975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       BoundNetLog(), GetParam(), NULL);
33985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.RunToCompletion(&data);
33995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionHelperResult out = helper.output();
34005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, out.rv) << i;
34025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("HTTP/1.1 200 OK", out.status_line) << i;
34035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ("hello!", out.response_data) << i;
34045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Test the response information.
34065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(out.response_info.response_time >
34075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                out.response_info.request_time) << i;
34085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta test_delay = out.response_info.response_time -
34095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 out.response_info.request_time;
34105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta min_expected_delay;
34115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    min_expected_delay.FromMilliseconds(10);
34125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GT(test_delay.InMillisecondsF(),
34135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              min_expected_delay.InMillisecondsF()) << i;
34145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(out.response_info.vary_data.is_valid(),
34155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              test_cases[i].vary_matches) << i;
34165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check the headers.
34185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<HttpResponseHeaders> headers = out.response_info.headers;
34195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(headers.get() != NULL) << i;
34205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* iter = NULL;
34215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name, value, lines;
34225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
34235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lines.append(name);
34245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lines.append(": ");
34255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lines.append(value);
34265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lines.append("\n");
34275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
34285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Construct the expected header reply string.
3430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SpdyHeaderBlock reply_headers;
3431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    AppendToHeaderBlock(test_cases[i].extra_headers[1],
3432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        test_cases[i].num_headers[1],
3433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        &reply_headers);
3434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::string expected_reply =
3435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        spdy_util_.ConstructSpdyReplyString(reply_headers);
3436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_EQ(expected_reply, lines) << i;
34375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
34385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
34395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that we don't crash on invalid SynReply responses.
34417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, InvalidSynReply) {
34425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdyHeaderInfo kSynStartHeader = {
34435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SYN_REPLY,              // Kind = SynReply
34445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1,                      // Stream ID
34455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                      // Associated stream ID
34467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ConvertRequestPriorityToSpdyPriority(
34477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        LOWEST, spdy_util_.spdy_version()),
34487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    kSpdyCredentialSlotUnused,
34495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CONTROL_FLAG_NONE,      // Control Flags
34505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    false,                  // Compressed
34512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RST_STREAM_INVALID,     // Status
34525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NULL,                   // Data
34535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                      // Length
34545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DATA_FLAG_NONE          // Data Flags
34555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
34565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct InvalidSynReplyTests {
34585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_headers;
34595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* headers[10];
34605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } test_cases[] = {
34615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SYN_REPLY missing status header
34625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { 4,
34635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { "cookie", "val1",
34645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "cookie", "val2",
34657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        spdy_util_.GetPathKey(), "/index.php",
34667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        spdy_util_.GetVersionKey(), "HTTP/1.1",
34675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NULL
34685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      },
34695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
34705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SYN_REPLY missing version header
34715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { 2,
34727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      { "status", "200",
34737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        spdy_util_.GetPathKey(), "/index.php",
34745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NULL
34755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      },
34765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
34775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SYN_REPLY with no headers
34785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { 0, { NULL }, },
34795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
34805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
34825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdyFrame> req(
348390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame> rst(
3485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
34865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite writes[] = {
34875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockWrite(*req),
3488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateMockWrite(*rst),
34895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
34905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdyFrame> resp(
34927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)       spdy_util_.ConstructSpdyFrame(kSynStartHeader,
34937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                     NULL, 0,
34947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                     test_cases[i].headers,
34957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                     test_cases[i].num_headers));
34967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
34975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead reads[] = {
34985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*resp),
34995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockRead(ASYNC, 0, 0)  // EOF
35005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
35015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelayedSocketData data(1, reads, arraysize(reads),
35035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           writes, arraysize(writes));
35042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
35055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       BoundNetLog(), GetParam(), NULL);
35065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.RunToCompletion(&data);
35075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionHelperResult out = helper.output();
3508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
35095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
35105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that we don't crash on some corrupt frames.
35137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) {
35145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the length field that's too short.
35155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> syn_reply_wrong_length(
35167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
35177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
3518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t right_size =
3519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (spdy_util_.spdy_version() < SPDY4) ?
3520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      syn_reply_wrong_length->size() - framer.GetControlFrameHeaderSize() :
3521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      syn_reply_wrong_length->size();
3522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t wrong_size = right_size - 4;
35232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  test::SetFrameLength(syn_reply_wrong_length.get(),
3524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       wrong_size,
35257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       spdy_util_.spdy_version());
35265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct SynReplyTests {
35285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SpdyFrame* syn_reply;
35295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } test_cases[] = {
35305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { syn_reply_wrong_length.get(), },
35315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
35325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
35345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<SpdyFrame> req(
353590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
3536ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    scoped_ptr<SpdyFrame> rst(
3537ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
3538ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    MockWrite writes[] = {
3539ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateMockWrite(*req),
3540ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      CreateMockWrite(*rst),
35415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
35425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
35445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead reads[] = {
35452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MockRead(ASYNC, test_cases[i].syn_reply->data(), wrong_size),
35465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateMockRead(*body),
35475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockRead(ASYNC, 0, 0)  // EOF
35485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
35495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelayedSocketData data(1, reads, arraysize(reads),
35515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           writes, arraysize(writes));
35522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
35535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       BoundNetLog(), GetParam(), NULL);
35545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    helper.RunToCompletion(&data);
35555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionHelperResult out = helper.output();
35565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
35575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
35585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that we shutdown correctly on write errors.
35617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, WriteError) {
356290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
356390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
35645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
35655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We'll write 10 bytes successfully
35665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, req->data(), 10),
35675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Followed by ERROR!
35685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, ERR_FAILED),
35695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
35705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(2, NULL, 0,
35725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
35732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
35745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
35755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
35765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
35775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_FAILED, out.rv);
35785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.Reset();
35795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that partial writes work.
35827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, PartialWrite) {
35835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Chop the SYN_STREAM frame into 5 chunks.
358490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
358590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
35865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kChunks = 5;
3587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<MockWrite[]> writes(ChopWriteFrame(*req.get(), kChunks));
35885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
35907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
35915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
35925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
35935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
35945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
35955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
35965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(kChunks, reads, arraysize(reads),
35985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes.get(), kChunks);
35992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
36005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
36015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
36025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
36035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
36045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
36055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
36065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
36075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In this test, we enable compression, but get a uncompressed SynReply from
36095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the server.  Verify that teardown is all clean.
36107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) {
36115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> compressed(
361290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, true, 1, LOWEST, true));
36135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> rst(
361490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
36155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
36165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*compressed),
36175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
36185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
36207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
36215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
36225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
36235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
36245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
36265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
36277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SpdySessionDependencies* session_deps =
36287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      CreateSpdySessionDependencies(GetParam());
36292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps->enable_compression = true;
36302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
36312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     BoundNetLog(), GetParam(), session_deps);
36325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
36335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
36345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
36355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.Reset();
36365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
36375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that the NetLog contains good data for a simple GET request.
36397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, NetLog) {
36405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* const kExtraHeaders[] = {
36415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "user-agent",   "Chrome",
36425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
364390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
364490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, false, 1, LOWEST, true));
36455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req) };
36465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
36487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
36495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
36505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
36515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
36525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
36535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
36545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CapturingBoundNetLog log;
36565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
36585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
36595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequestWithUserAgent(),
36602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     DEFAULT_PRIORITY,
36615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     log.bound(), GetParam(), NULL);
36625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunToCompletion(&data);
36635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
36645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
36655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
36665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
36675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that the NetLog was filled reasonably.
36695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This test is intentionally non-specific about the exact ordering of the
36705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // log; instead we just check to make sure that certain events exist, and that
36715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // they are in the right order.
36725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::CapturingNetLog::CapturedEntryList entries;
36735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  log.GetEntries(&entries);
36745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(0u, entries.size());
36765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pos = 0;
36775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos = net::ExpectLogContainsSomewhere(entries, 0,
36785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
36795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_BEGIN);
36805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
36815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST,
36825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_END);
36835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
36845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
36855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_BEGIN);
36865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
36875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_HTTP_TRANSACTION_READ_HEADERS,
36885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_END);
36895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
36905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
36915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_BEGIN);
36925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos = net::ExpectLogContainsSomewhere(entries, pos + 1,
36935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_HTTP_TRANSACTION_READ_BODY,
36945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_END);
36955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that we logged all the headers correctly
36975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pos = net::ExpectLogContainsSomewhere(
36985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entries, 0,
36995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
37005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_NONE);
37015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::ListValue* header_list;
37035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(entries[pos].params.get());
37045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list));
37055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> expected;
37077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  expected.push_back(std::string(spdy_util_.GetHostKey()) + ": www.google.com");
37087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  expected.push_back(std::string(spdy_util_.GetPathKey()) + ": /");
37097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  expected.push_back(std::string(spdy_util_.GetSchemeKey()) + ": http");
37107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  expected.push_back(std::string(spdy_util_.GetVersionKey()) + ": HTTP/1.1");
37117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  expected.push_back(std::string(spdy_util_.GetMethodKey()) + ": GET");
37125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected.push_back("user-agent: Chrome");
37135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(expected.size(), header_list->GetSize());
37145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<std::string>::const_iterator it = expected.begin();
37155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != expected.end();
37165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
37175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringValue header(*it);
37185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_NE(header_list->end(), header_list->Find(header)) <<
37195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Header not found: " << *it;
37205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
37215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
37225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Since we buffer the IO from the stream to the renderer, this test verifies
37245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that when we read out the maximum amount of data (e.g. we received 50 bytes
37255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on the network, but issued a Read for only 5 of those bytes) that the data
37265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// flow still works correctly.
37277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, BufferFull) {
37287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
37295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
373090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
373190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
37325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req) };
37335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 2 data frames in a single read.
37355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame_1(
37365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "goodby", 6, DATA_FLAG_NONE));
37375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame_2(
37385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "e worl", 6, DATA_FLAG_NONE));
37395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdyFrame* data_frames[2] = {
37405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame_1.get(),
37415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame_2.get(),
37425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
37435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char combined_data_frames[100];
37445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int combined_data_frames_len =
37455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CombineFrames(data_frames, arraysize(data_frames),
37465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    combined_data_frames, arraysize(combined_data_frames));
37475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> last_frame(
37485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "d", 1, DATA_FLAG_FIN));
37495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
37515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
37525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
37535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING),  // Force a pause
37545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
37555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING),  // Force a pause
37565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*last_frame),
37575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
37585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
37595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
37615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
37625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
37645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
37665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
37675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
37685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
37695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
37705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
37715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
37725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
37735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
37755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback.WaitForResult();
37765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(out.rv, OK);
37775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response = trans->GetResponseInfo();
3779868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response->headers.get() != NULL);
37805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response->was_fetched_via_spdy);
37815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response->headers->GetStatusLine();
37825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response;  // Make a copy so we can verify.
37835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read Data
37855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback read_callback;
37865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string content;
37885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
37895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read small chunks at a time.
37905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kSmallReadSize = 3;
37915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3792868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
37935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == net::ERR_IO_PENDING) {
37945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.CompleteRead();
37955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = read_callback.WaitForResult();
37965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
37975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv > 0) {
37985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content.append(buf->data(), rv);
37995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (rv < 0) {
38005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
38015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
38025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv > 0);
38035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_data.swap(content);
38055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
38075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MockClientSocketFactory) are still alive.
380890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
38095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that we consumed all test data.
38115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
38125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
38145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
38155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("goodbye world", out.response_data);
38165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
38175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that basic buffering works; when multiple data frames arrive
38195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// at the same time, ensure that we don't notify a read completion for
38205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// each data frame individually.
38217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, Buffering) {
38227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
38235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
382490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
382590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
38265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req) };
38275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 4 data frames in a single read.
38295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame(
38305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
38315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame_fin(
38325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
38335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdyFrame* data_frames[4] = {
38345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get(),
38355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get(),
38365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get(),
38375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame_fin.get()
38385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
38395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char combined_data_frames[100];
38405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int combined_data_frames_len =
38415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CombineFrames(data_frames, arraysize(data_frames),
38425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    combined_data_frames, arraysize(combined_data_frames));
38435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
38455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
38465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
38475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING),  // Force a pause
38485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
38495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
38505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
38515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
38535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
38545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
38565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
38575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
38585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
38595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
38605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
38625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
38635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
38645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
38655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
38675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback.WaitForResult();
38685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(out.rv, OK);
38695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response = trans->GetResponseInfo();
3871868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response->headers.get() != NULL);
38725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response->was_fetched_via_spdy);
38735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response->headers->GetStatusLine();
38745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response;  // Make a copy so we can verify.
38755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read Data
38775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback read_callback;
38785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string content;
38805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reads_completed = 0;
38815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
38825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read small chunks at a time.
38835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kSmallReadSize = 14;
38845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3885868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
38865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == net::ERR_IO_PENDING) {
38875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.CompleteRead();
38885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = read_callback.WaitForResult();
38895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
38905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv > 0) {
38915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(kSmallReadSize, rv);
38925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content.append(buf->data(), rv);
38935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (rv < 0) {
38945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FAIL() << "Unexpected read error: " << rv;
38955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
38965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reads_completed++;
38975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv > 0);
38985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3, reads_completed);  // Reads are: 14 bytes, 14 bytes, 0 bytes.
39005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_data.swap(content);
39025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
39045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MockClientSocketFactory) are still alive.
390590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
39065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that we consumed all test data.
39085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
39095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
39115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
39125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("messagemessagemessagemessage", out.response_data);
39135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
39145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify the case where we buffer data but read it after it has been buffered.
39167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, BufferedAll) {
39177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
39185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
391990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
392090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
39215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req) };
39225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 5 data frames in a single read.
39245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> syn_reply(
39257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
39262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // turn off FIN bit
39277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  test::SetFrameFlags(
39287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      syn_reply.get(), CONTROL_FLAG_NONE, spdy_util_.spdy_version());
39295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame(
39305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
39315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame_fin(
39325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_FIN));
39335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdyFrame* frames[5] = {
39345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syn_reply.get(),
39355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get(),
39365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get(),
39375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get(),
39385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame_fin.get()
39395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
39405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char combined_frames[200];
39415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int combined_frames_len =
39425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CombineFrames(frames, arraysize(frames),
39435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    combined_frames, arraysize(combined_frames));
39445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
39465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, combined_frames, combined_frames_len),
39475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
39485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
39495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
39515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
39525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
39545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
39555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
39565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
39575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
39585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
39605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
39615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
39625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
39635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
39655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback.WaitForResult();
39665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(out.rv, OK);
39675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response = trans->GetResponseInfo();
3969868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response->headers.get() != NULL);
39705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response->was_fetched_via_spdy);
39715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response->headers->GetStatusLine();
39725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response;  // Make a copy so we can verify.
39735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read Data
39755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback read_callback;
39765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string content;
39785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reads_completed = 0;
39795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
39805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read small chunks at a time.
39815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kSmallReadSize = 14;
39825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
3983868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
39845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv > 0) {
39855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(kSmallReadSize, rv);
39865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content.append(buf->data(), rv);
39875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (rv < 0) {
39885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FAIL() << "Unexpected read error: " << rv;
39895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
39905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reads_completed++;
39915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv > 0);
39925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3, reads_completed);
39945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_data.swap(content);
39965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
39985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MockClientSocketFactory) are still alive.
399990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
40005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that we consumed all test data.
40025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
40035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
40055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
40065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("messagemessagemessagemessage", out.response_data);
40075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
40085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify the case where we buffer data and close the connection.
40107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, BufferedClosed) {
40117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
40125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
401390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
401490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
40155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req) };
40165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All data frames in a single read.
40185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: We don't FIN the stream.
40195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame(
40205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
40215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdyFrame* data_frames[4] = {
40225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get(),
40235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get(),
40245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get(),
40255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_frame.get()
40265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
40275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char combined_data_frames[100];
40285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int combined_data_frames_len =
40295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CombineFrames(data_frames, arraysize(data_frames),
40305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    combined_data_frames, arraysize(combined_data_frames));
40317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
40325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
40335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
40345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING),  // Force a wait
40355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, combined_data_frames, combined_data_frames_len),
40365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
40375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
40385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
40405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
40415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
40435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
40445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
40455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
40465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
40475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
40495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
40515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
40525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
40535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
40555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback.WaitForResult();
40565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(out.rv, OK);
40575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response = trans->GetResponseInfo();
4059868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response->headers.get() != NULL);
40605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response->was_fetched_via_spdy);
40615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response->headers->GetStatusLine();
40625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response;  // Make a copy so we can verify.
40635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read Data
40655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback read_callback;
40665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string content;
40685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reads_completed = 0;
40695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
40705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read small chunks at a time.
40715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kSmallReadSize = 14;
40725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kSmallReadSize));
4073868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
40745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == net::ERR_IO_PENDING) {
40755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.CompleteRead();
40765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = read_callback.WaitForResult();
40775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
40785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv > 0) {
40795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content.append(buf->data(), rv);
40805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (rv < 0) {
40815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This test intentionally closes the connection, and will get an error.
40825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
40835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
40845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
40855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reads_completed++;
40865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv > 0);
40875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, reads_completed);
40895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_data.swap(content);
40915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flush the MessageLoop while the SpdySessionDependencies (in particular, the
40935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MockClientSocketFactory) are still alive.
409490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
40955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that we consumed all test data.
40975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
40985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
40995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify the case where we buffer data and cancel the transaction.
41017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) {
41027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
41035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
410490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
410590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
41065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req) };
41075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: We don't FIN the stream.
41095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_frame(
41105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      framer.CreateDataFrame(1, "message", 7, DATA_FLAG_NONE));
41115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
41135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
41145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
41155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING),  // Force a wait
41165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*data_frame),
41175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
41185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
41195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
41215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
41225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
41245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
41255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
41265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
41275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
41285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
41295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
41315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
41325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
41335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
41355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.rv = callback.WaitForResult();
41365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(out.rv, OK);
41375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response = trans->GetResponseInfo();
4139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response->headers.get() != NULL);
41405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(response->was_fetched_via_spdy);
41415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.status_line = response->headers->GetStatusLine();
41425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out.response_info = *response;  // Make a copy so we can verify.
41435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read Data
41455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback read_callback;
41465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
41485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kReadSize = 256;
41495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kReadSize));
4150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    rv = trans->Read(buf.get(), kReadSize, read_callback.callback());
41515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == net::ERR_IO_PENDING) {
41525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Complete the read now, which causes buffering to start.
41535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.CompleteRead();
41545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Destroy the transaction, causing the stream to get cancelled
41555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // and orphaning the buffered IO task.
41565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      helper.ResetTrans();
41575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
41585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
41595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We shouldn't get here in this test.
41605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FAIL() << "Unexpected read: " << rv;
41615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv > 0);
41625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flush the MessageLoop; this will cause the buffered IO task
41645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to run for the final time.
416590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
41665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that we consumed all test data.
41685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
41695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
41705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that if the server requests persistence of settings, that we save
41725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the settings in the HttpServerProperties.
41737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_P(SpdyNetworkTransactionTest, SettingsSaved) {
41745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const SpdyHeaderInfo kSynReplyInfo = {
41755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SYN_REPLY,                              // Syn Reply
41765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1,                                      // Stream ID
41775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                                      // Associated Stream ID
41787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ConvertRequestPriorityToSpdyPriority(
41797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        LOWEST, spdy_util_.spdy_version()),
41807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    kSpdyCredentialSlotUnused,
41815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CONTROL_FLAG_NONE,                      // Control Flags
41825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    false,                                  // Compressed
41832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RST_STREAM_INVALID,                     // Status
41845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NULL,                                   // Data
41855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                                      // Data Length
41865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DATA_FLAG_NONE                          // Data Flags
41875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
41885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog net_log;
41902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
41912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     net_log, GetParam(), NULL);
41925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
41935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that no settings exist initially.
41955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostPortPair host_port_pair("www.google.com", helper.port());
41965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
41975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
41985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_port_pair).empty());
41995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the request.
420190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
420290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
42035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = { CreateMockWrite(*req) };
42045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct the reply.
42067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
42077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
42087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
42095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> reply(
42107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
42115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
42135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int kSampleValue1 = 0x0a0a0a0a;
42145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdySettingsIds kSampleId2 = SETTINGS_DOWNLOAD_BANDWIDTH;
42155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int kSampleValue2 = 0x0b0b0b0b;
42165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdySettingsIds kSampleId3 = SETTINGS_ROUND_TRIP_TIME;
42175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int kSampleValue3 = 0x0c0c0c0c;
42185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> settings_frame;
42195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
42205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Construct the SETTINGS frame.
42215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SettingsMap settings;
42225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // First add a persisted setting.
42235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    settings[kSampleId1] =
42245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue1);
42255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Next add a non-persisted setting.
42265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    settings[kSampleId2] =
42275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kSampleValue2);
42285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Next add another persisted setting.
42295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    settings[kSampleId3] =
42305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SettingsFlagsAndValue(SETTINGS_FLAG_PLEASE_PERSIST, kSampleValue3);
423190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    settings_frame.reset(spdy_util_.ConstructSpdySettings(settings));
42325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
42335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
42355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
42365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*reply),
42375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
4238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*settings_frame),
4239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
4240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(1, reads, arraysize(reads),
4243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
4244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
4245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunDefaultTest();
4246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
4247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out = helper.output();
4248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, out.rv);
4249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello!", out.response_data);
4251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  {
4253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Verify we had two persisted settings.
4254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const SettingsMap& settings_map =
4255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        spdy_session_pool->http_server_properties()->GetSpdySettings(
4256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            host_port_pair);
4257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ASSERT_EQ(2u, settings_map.size());
4258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Verify the first persisted setting.
4260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
4261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(it1 != settings_map.end());
4262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SettingsFlagsAndValue flags_and_value1 = it1->second;
4263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
4264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(kSampleValue1, flags_and_value1.second);
4265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Verify the second persisted setting.
4267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SettingsMap::const_iterator it3 = settings_map.find(kSampleId3);
4268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(it3 != settings_map.end());
4269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SettingsFlagsAndValue flags_and_value3 = it3->second;
4270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value3.first);
4271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(kSampleValue3, flags_and_value3.second);
4272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
4273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
4274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test that when there are settings saved that they are sent back to the
4276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// server upon session establishment.
4277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, SettingsPlayback) {
4278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static const SpdyHeaderInfo kSynReplyInfo = {
4279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SYN_REPLY,                              // Syn Reply
4280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    1,                                      // Stream ID
4281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    0,                                      // Associated Stream ID
4282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ConvertRequestPriorityToSpdyPriority(
4283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        LOWEST, spdy_util_.spdy_version()),
4284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    kSpdyCredentialSlotUnused,
4285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CONTROL_FLAG_NONE,                      // Control Flags
4286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    false,                                  // Compressed
4287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    RST_STREAM_INVALID,                     // Status
4288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    NULL,                                   // Data
4289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    0,                                      // Data Length
4290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DATA_FLAG_NONE                          // Data Flags
4291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  BoundNetLog net_log;
4294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     net_log, GetParam(), NULL);
4296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
4297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that no settings exist initially.
4299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port_pair("www.google.com", helper.port());
4300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
4301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(spdy_session_pool->http_server_properties()->GetSpdySettings(
4302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      host_port_pair).empty());
4303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const SpdySettingsIds kSampleId1 = SETTINGS_UPLOAD_BANDWIDTH;
4305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  unsigned int kSampleValue1 = 0x0a0a0a0a;
4306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const SpdySettingsIds kSampleId2 = SETTINGS_ROUND_TRIP_TIME;
4307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  unsigned int kSampleValue2 = 0x0c0c0c0c;
4308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // First add a persisted setting.
4310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_session_pool->http_server_properties()->SetSpdySetting(
4311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      host_port_pair,
4312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSampleId1,
4313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SETTINGS_FLAG_PLEASE_PERSIST,
4314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSampleValue1);
4315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Next add another persisted setting.
4317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_session_pool->http_server_properties()->SetSpdySetting(
4318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      host_port_pair,
4319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSampleId2,
4320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SETTINGS_FLAG_PLEASE_PERSIST,
4321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSampleValue2);
4322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(2u, spdy_session_pool->http_server_properties()->GetSpdySettings(
4324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      host_port_pair).size());
4325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct the SETTINGS frame.
4327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const SettingsMap& settings =
4328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_session_pool->http_server_properties()->GetSpdySettings(
4329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          host_port_pair);
4330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> settings_frame(
4331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySettings(settings));
4332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct the request.
4334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
4335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
4338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*settings_frame),
4339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req),
4340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct the reply.
4343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> reply_headers(new SpdyHeaderBlock());
4344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*reply_headers)[spdy_util_.GetStatusKey()] = "200";
4345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*reply_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> reply(
4347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    spdy_util_.ConstructSpdyFrame(kSynReplyInfo, reply_headers.Pass()));
4348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
4351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*reply),
4352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body),
43535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
43545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
43555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(2, reads, arraysize(reads),
43575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
43585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddData(&data);
43595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunDefaultTest();
43605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
43615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionHelperResult out = helper.output();
43625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, out.rv);
43635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
43645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("hello!", out.response_data);
43655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
43675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify we had two persisted settings.
43685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SettingsMap& settings_map =
43695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        spdy_session_pool->http_server_properties()->GetSpdySettings(
43705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            host_port_pair);
43715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(2u, settings_map.size());
43725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify the first persisted setting.
43745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SettingsMap::const_iterator it1 = settings_map.find(kSampleId1);
43755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(it1 != settings_map.end());
43765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SettingsFlagsAndValue flags_and_value1 = it1->second;
43775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value1.first);
43785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kSampleValue1, flags_and_value1.second);
43795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify the second persisted setting.
4381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SettingsMap::const_iterator it2 = settings_map.find(kSampleId2);
4382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(it2 != settings_map.end());
4383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    SettingsFlagsAndValue flags_and_value2 = it2->second;
4384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(SETTINGS_FLAG_PERSISTED, flags_and_value2.first);
4385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(kSampleValue2, flags_and_value2.second);
43865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
43875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
43885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, GoAwayWithActiveStream) {
4390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
4391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
43937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> go_away(spdy_util_.ConstructSpdyGoAway());
4395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
4396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*go_away),
43975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
43985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(1, reads, arraysize(reads),
4400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
44012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
4403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
4404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunToCompletion(&data);
4405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out = helper.output();
4406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_ABORTED, out.rv);
4407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
4408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) {
4410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
4411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = { CreateMockWrite(*req) };
4413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
4416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp),
4417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, 0, 0)  // EOF
4418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(1, reads, arraysize(reads),
4421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
4422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  BoundNetLog log;
4423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     log, GetParam(), NULL);
4425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
4426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
4427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
4428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
4430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out;
4431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  out.rv = trans->Start(&CreateGetRequest(), callback.callback(), log);
4432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(out.rv, ERR_IO_PENDING);
4434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  out.rv = callback.WaitForResult();
4435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(out.rv, OK);
4436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
4438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response->headers.get() != NULL);
4439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
4440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  out.rv = ReadTransaction(trans, &out.response_data);
4441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, out.rv);
4442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
4444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
4445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
4446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test to make sure we can correctly connect through a proxy.
4448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ProxyConnect) {
4449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
4451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.session_deps().reset(CreateSpdySessionDependencies(
4452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      GetParam(),
4453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")));
4454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.SetSession(make_scoped_refptr(
4455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
4457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
4458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Host: www.google.com\r\n"
4461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Proxy-Connection: keep-alive\r\n\r\n"};
4462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Host: www.google.com\r\n"
4464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Proxy-Connection: keep-alive\r\n\r\n"};
4465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
4467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes_SPDYNPN[] = {
4472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 2),
4474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads_SPDYNPN[] = {
4476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 3),
4478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body.get(), 4),
4479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 5),
4480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes_SPDYSSL[] = {
4483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 2),
4485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads_SPDYSSL[] = {
4487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 3),
4489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body.get(), 4),
4490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 5),
4491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes_SPDYNOSSL[] = {
4494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
4495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads_SPDYNOSSL[] = {
4498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 1),
4499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body.get(), 2),
4500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 3),
4501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<OrderedSocketData> data;
4504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch(GetParam().ssl_type) {
4505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SPDYNOSSL:
4506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      data.reset(new OrderedSocketData(reads_SPDYNOSSL,
4507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       arraysize(reads_SPDYNOSSL),
4508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       writes_SPDYNOSSL,
4509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       arraysize(writes_SPDYNOSSL)));
4510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
4511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SPDYSSL:
4512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      data.reset(new OrderedSocketData(reads_SPDYSSL,
4513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       arraysize(reads_SPDYSSL),
4514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       writes_SPDYSSL,
4515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       arraysize(writes_SPDYSSL)));
4516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
4517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SPDYNPN:
4518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      data.reset(new OrderedSocketData(reads_SPDYNPN,
4519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       arraysize(reads_SPDYNPN),
4520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       writes_SPDYNPN,
4521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       arraysize(writes_SPDYNPN)));
4522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
4523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default:
4524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      NOTREACHED();
4525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
4526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(data.get());
4528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
4529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
4531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
4532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
4533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
4535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, rv);
4536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
4538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response = *trans->GetResponseInfo();
4539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
4540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
4541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string response_data;
4543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
4544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello!", response_data);
4545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
4546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
4547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test to make sure we can correctly connect through a proxy to www.google.com,
4549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// if there already exists a direct spdy connection to www.google.com. See
4550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// http://crbug.com/49874
4551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, DirectConnectProxyReconnect) {
4552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // When setting up the first transaction, we store the SpdySessionPool so that
4553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // we can use the same pool in the second transaction.
4554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
4556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Use a proxy service which returns a proxy fallback list from DIRECT to
4558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // myproxy:70. For this test there will be no fallback, so it is equivalent
4559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // to simply DIRECT. The reason for appending the second proxy is to verify
4560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // that the session pool key used does is just "DIRECT".
4561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.session_deps().reset(CreateSpdySessionDependencies(
4562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      GetParam(),
4563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ProxyService::CreateFixedFromPacResult("DIRECT; PROXY myproxy:70")));
4564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.SetSession(make_scoped_refptr(
4565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SpdySessionDependencies::SpdyCreateSession(helper.session_deps().get())));
4566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool();
45685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
45695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct and send a simple GET request.
4571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
4572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
4574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 1),
4575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
4580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 2),
4581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body, 3),
4582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 4),  // Force a pause
4583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 5)  // EOF
4584eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4585eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
4586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
4587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
4588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
4589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
4591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out;
4592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  out.rv = trans->Start(
4593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
4594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(out.rv, ERR_IO_PENDING);
4596eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  out.rv = callback.WaitForResult();
4597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(out.rv, OK);
4598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
4600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response->headers.get() != NULL);
4601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
4602eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  out.rv = ReadTransaction(trans, &out.response_data);
4603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, out.rv);
4604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  out.status_line = response->headers->GetStatusLine();
4605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello!", out.response_data);
4607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Check that the SpdySession is still in the SpdySessionPool.
4609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HostPortPair host_port_pair("www.google.com", helper.port());
4610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey session_pool_key_direct(
4611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      host_port_pair, ProxyServer::Direct(), kPrivacyModeDisabled);
46127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(HasSpdySession(spdy_session_pool, session_pool_key_direct));
4613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdySessionKey session_pool_key_proxy(
4614eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      host_port_pair,
4615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ProxyServer::FromURI("www.foo.com", ProxyServer::SCHEME_HTTP),
4616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kPrivacyModeDisabled);
46177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(HasSpdySession(spdy_session_pool, session_pool_key_proxy));
4618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4619eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set up data for the proxy connection.
4620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kConnect443[] = {"CONNECT www.google.com:443 HTTP/1.1\r\n"
4621eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Host: www.google.com\r\n"
4622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Proxy-Connection: keep-alive\r\n\r\n"};
4623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kConnect80[] = {"CONNECT www.google.com:80 HTTP/1.1\r\n"
4624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Host: www.google.com\r\n"
4625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           "Proxy-Connection: keep-alive\r\n\r\n"};
4626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"};
4627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyGet(
4628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "http://www.google.com/foo.dat", false, 1, LOWEST));
4629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
46315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes_SPDYNPN[] = {
4633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite(SYNCHRONOUS, kConnect443, arraysize(kConnect443) - 1, 0),
4634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 2),
4635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads_SPDYNPN[] = {
4637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4638eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 3),
4639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body2, 4),
4640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 5)  // EOF
4641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
46425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes_SPDYNOSSL[] = {
4644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 0),
4645eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads_SPDYNOSSL[] = {
4647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 1),
4648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body2, 2),
4649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 3)  // EOF
4650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
46515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes_SPDYSSL[] = {
4653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite(SYNCHRONOUS, kConnect80, arraysize(kConnect80) - 1, 0),
4654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 2),
4655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads_SPDYSSL[] = {
4657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, kHTTP200, arraysize(kHTTP200) - 1, 1),
4658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 3),
4659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body2, 4),
4660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 5),
4661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
46625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<OrderedSocketData> data_proxy;
4664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch(GetParam().ssl_type) {
4665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SPDYNPN:
4666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      data_proxy.reset(new OrderedSocketData(reads_SPDYNPN,
4667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             arraysize(reads_SPDYNPN),
4668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             writes_SPDYNPN,
4669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             arraysize(writes_SPDYNPN)));
4670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
4671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SPDYNOSSL:
4672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      data_proxy.reset(new OrderedSocketData(reads_SPDYNOSSL,
4673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             arraysize(reads_SPDYNOSSL),
4674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             writes_SPDYNOSSL,
4675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             arraysize(writes_SPDYNOSSL)));
4676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
4677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case SPDYSSL:
4678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      data_proxy.reset(new OrderedSocketData(reads_SPDYSSL,
4679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             arraysize(reads_SPDYSSL),
4680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             writes_SPDYSSL,
4681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             arraysize(writes_SPDYSSL)));
4682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
4683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default:
4684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      NOTREACHED();
4685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
46865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4687eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Create another request to www.google.com, but this time through a proxy.
4688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo request_proxy;
4689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request_proxy.method = "GET";
4690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request_proxy.url = GURL("http://www.google.com/foo.dat");
4691eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request_proxy.load_flags = 0;
4692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdySessionDependencies> ssd_proxy(
4693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateSpdySessionDependencies(GetParam()));
4694eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Ensure that this transaction uses the same SpdySessionPool.
4695eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<HttpNetworkSession> session_proxy(
4696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SpdySessionDependencies::SpdyCreateSession(ssd_proxy.get()));
4697eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper_proxy(request_proxy, DEFAULT_PRIORITY,
4698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           BoundNetLog(), GetParam(), NULL);
4699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkSessionPeer session_peer(session_proxy);
4700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<net::ProxyService> proxy_service(
4701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
4702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_peer.SetProxyService(proxy_service.get());
4703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper_proxy.session_deps().swap(ssd_proxy);
4704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper_proxy.SetSession(session_proxy);
4705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper_proxy.RunPreTestSetup();
4706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper_proxy.AddData(data_proxy.get());
47075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans_proxy = helper_proxy.trans();
4709eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback_proxy;
4710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans_proxy->Start(
4711eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &request_proxy, callback_proxy.callback(), BoundNetLog());
4712eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
4713eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback_proxy.WaitForResult();
4714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, rv);
47155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response_proxy = *trans_proxy->GetResponseInfo();
4717eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response_proxy.headers.get() != NULL);
4718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response_proxy.headers->GetStatusLine());
47195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string response_data;
4721eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(OK, ReadTransaction(trans_proxy, &response_data));
4722eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello!", response_data);
4723eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4724eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.CompleteRead();
4725eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper_proxy.VerifyDataConsumed();
4726eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
47275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4728eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// When we get a TCP-level RST, we need to retry a HttpNetworkTransaction
4729eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// on a new connection, if the connection was previously known to be good.
4730eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// This can happen when a server reboots without saying goodbye, or when
4731eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// we're behind a NAT that masked the RST.
4732eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) {
4733eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
47347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
47355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
4736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp),
4737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body),
4738eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING),
4739eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_CONNECTION_RESET),
4740eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4741eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4742eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads2[] = {
4743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp),
47445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*body),
47455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
47465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
47475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4748eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // This test has a couple of variants.
4749eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  enum {
4750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Induce the RST while waiting for our transaction to send.
4751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    VARIANT_RST_DURING_SEND_COMPLETION,
4752eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Induce the RST while waiting for our transaction to read.
4753eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // In this case, the send completed - everything copied into the SNDBUF.
4754eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    VARIANT_RST_DURING_READ_COMPLETION
4755eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
47565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4757eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (int variant = VARIANT_RST_DURING_SEND_COMPLETION;
4758eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       variant <= VARIANT_RST_DURING_READ_COMPLETION;
4759eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       ++variant) {
4760eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DelayedSocketData data1(1, reads, arraysize(reads), NULL, 0);
47615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4762eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DelayedSocketData data2(1, reads2, arraysize(reads2), NULL, 0);
47635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4764eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4765eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       BoundNetLog(), GetParam(), NULL);
4766eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    helper.AddData(&data1);
4767eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    helper.AddData(&data2);
4768eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    helper.RunPreTestSetup();
47695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (int i = 0; i < 2; ++i) {
4771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      scoped_ptr<HttpNetworkTransaction> trans(
4772eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
47737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      TestCompletionCallback callback;
4775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      int rv = trans->Start(
4776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          &helper.request(), callback.callback(), BoundNetLog());
4777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_EQ(ERR_IO_PENDING, rv);
4778eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // On the second transaction, we trigger the RST.
4779eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (i == 1) {
4780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        if (variant == VARIANT_RST_DURING_READ_COMPLETION) {
4781eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          // Writes to the socket complete asynchronously on SPDY by running
4782eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          // through the message loop.  Complete the write here.
4783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          base::MessageLoop::current()->RunUntilIdle();
4784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        }
47855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4786eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        // Now schedule the ERR_CONNECTION_RESET.
4787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        EXPECT_EQ(3u, data1.read_index());
4788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        data1.CompleteRead();
4789eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        EXPECT_EQ(4u, data1.read_index());
4790eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
4791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      rv = callback.WaitForResult();
4792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_EQ(OK, rv);
47935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      const HttpResponseInfo* response = trans->GetResponseInfo();
4795eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      ASSERT_TRUE(response != NULL);
4796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_TRUE(response->headers.get() != NULL);
4797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_TRUE(response->was_fetched_via_spdy);
4798eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      std::string response_data;
4799eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      rv = ReadTransaction(trans.get(), &response_data);
4800eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_EQ(OK, rv);
4801eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4802eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      EXPECT_EQ("hello!", response_data);
4803eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
48045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    helper.VerifyDataConsumed();
4806eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
4807eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
48087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4809eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test that turning SPDY on and off works properly.
4810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, SpdyOnOffToggle) {
4811eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  net::HttpStreamFactory::set_spdy_enabled(true);
481290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
481390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4814eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite spdy_writes[] = { CreateMockWrite(*req) };
48155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4817eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
4818eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead spdy_reads[] = {
48195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*resp),
4820eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body),
4821eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
48225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
48235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4824eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(1, spdy_reads, arraysize(spdy_reads),
4825eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         spdy_writes, arraysize(spdy_writes));
48262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
4827eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
4828eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunToCompletion(&data);
4829eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out = helper.output();
4830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, out.rv);
4831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
4832eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello!", out.response_data);
48335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4834eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  net::HttpStreamFactory::set_spdy_enabled(false);
4835eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead http_reads[] = {
4836eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4837eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead("hello from http"),
4838eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(SYNCHRONOUS, OK),
4839eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
4840eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data2(1, http_reads, arraysize(http_reads), NULL, 0);
4841eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper2(CreateGetRequest(), DEFAULT_PRIORITY,
4842eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
4843eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper2.SetSpdyDisabled();
4844eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper2.RunToCompletion(&data2);
4845eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out2 = helper2.output();
4846eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, out2.rv);
4847eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", out2.status_line);
4848eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello from http", out2.response_data);
48495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4850eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  net::HttpStreamFactory::set_spdy_enabled(true);
48515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
48525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4853eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Tests that Basic authentication works over SPDY
4854eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) {
4855eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  net::HttpStreamFactory::set_spdy_enabled(true);
48565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4857eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The first request will be a bare GET, the second request will be a
4858eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // GET with an Authorization header.
4859eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req_get(
486090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4861eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char* const kExtraAuthorizationHeaders[] = {
4862eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "authorization", "Basic Zm9vOmJhcg=="
48635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4864eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req_get_authorization(
4865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
4866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                  arraysize(kExtraAuthorizationHeaders) / 2,
4867eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                  false, 3, LOWEST, true));
4868eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite spdy_writes[] = {
4869eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req_get, 1),
4870eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req_get_authorization, 4),
48715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
48725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // The first response is a 401 authentication challenge, and the second
4874eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // response will be a 200 response since the second request includes a valid
4875eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Authorization header.
4876eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char* const kExtraAuthenticationHeaders[] = {
4877eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "www-authenticate",
4878eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "Basic realm=\"MyRealm\""
48795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4880eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp_authentication(
4881eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySynReplyError(
4882eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          "401 Authentication Required",
4883eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          kExtraAuthenticationHeaders,
4884eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          arraysize(kExtraAuthenticationHeaders) / 2,
4885eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1));
4886eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body_authentication(
4887eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
4888eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp_data(
4889eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
4890eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
4891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead spdy_reads[] = {
4892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp_authentication, 2),
4893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body_authentication, 3),
4894eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp_data, 5),
4895eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body_data, 6),
4896eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 7),
48975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
48985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4899eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(spdy_reads, arraysize(spdy_reads),
4900eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         spdy_writes, arraysize(spdy_writes));
4901eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo request(CreateGetRequest());
4902eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  BoundNetLog net_log;
4903eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
4904eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     net_log, GetParam(), NULL);
49055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4906eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
4907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
4908eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
49095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
4910eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int rv_start = trans->Start(&request, callback.callback(), net_log);
4911eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv_start);
4912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int rv_start_complete = callback.WaitForResult();
4913eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv_start_complete);
49145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Make sure the response has an auth challenge.
4916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const HttpResponseInfo* const response_start = trans->GetResponseInfo();
4917eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(response_start != NULL);
4918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(response_start->headers.get() != NULL);
4919eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(401, response_start->headers->response_code());
4920eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response_start->was_fetched_via_spdy);
4921eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AuthChallengeInfo* auth_challenge = response_start->auth_challenge.get();
4922eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(auth_challenge != NULL);
4923eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(auth_challenge->is_proxy);
4924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("basic", auth_challenge->scheme);
4925eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("MyRealm", auth_challenge->realm);
49265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4927eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Restart with a username/password.
4928eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AuthCredentials credentials(ASCIIToUTF16("foo"), ASCIIToUTF16("bar"));
4929eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback_restart;
4930eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int rv_restart = trans->RestartWithAuth(
4931eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      credentials, callback_restart.callback());
4932eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv_restart);
4933eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const int rv_restart_complete = callback_restart.WaitForResult();
4934eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv_restart_complete);
4935eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(cbentzel): This is actually the same response object as before, but
4936eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // data has changed.
4937eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
4938eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(response_restart != NULL);
4939eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(response_restart->headers.get() != NULL);
4940eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(200, response_restart->headers->response_code());
4941eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
49425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
49435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4944eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushWithHeaders) {
4945eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
494690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
4947eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
4948eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
49495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
4950eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 1),
49515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
49525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4953eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
4954eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_util_.AddUrlToHeaderBlock(
4955eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "http://www.google.com/foo.dat", initial_headers.get());
4956eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_syn(
4957eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
4958eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
4959eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           2,
4960eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
4961eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           SYN_STREAM,
4962eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
4963eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           1));
4964eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4965eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
4966eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)["hello"] = "bye";
4967eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)[spdy_util_.GetStatusKey()] = "200";
4968eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
4969eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_headers(
4970eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
4971eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
4972eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           2,
4973eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
4974eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           HEADERS,
4975eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
4976eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           0));
4977eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4978eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
4979eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
4980eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
4981eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
4982eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
4983eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
49845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
4985eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 2),
4986eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 3),
4987eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_headers, 4),
4988eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
4989eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 5),
4990eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 7),  // Force a pause
49915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4992eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4993eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
4994eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
4995eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed");
49965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OrderedSocketData data(reads, arraysize(reads),
49975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         writes, arraysize(writes));
4998eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RunServerPushTest(&data,
4999eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response,
5000eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    &response2,
5001eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    expected_push_result);
50025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5003eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
5004eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
5005eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
50065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5007eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
5008eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
5009eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
5010eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
50115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5012eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushClaimBeforeHeaders) {
5013eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // We push a stream and attempt to claim it before the headers come down.
5014eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
5015eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5016eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
5017eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
5018eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
5019eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
50205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
50215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5022eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5023eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_util_.AddUrlToHeaderBlock(
5024eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "http://www.google.com/foo.dat", initial_headers.get());
5025eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_syn(
5026eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
5027eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
5028eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           2,
5029eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
5030eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           SYN_STREAM,
5031eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
5032eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           1));
50335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5034eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5035eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)["hello"] = "bye";
5036eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5037eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5038eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_headers(
5039eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
5041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           2,
5042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
5043eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           HEADERS,
5044eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
5045eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           0));
50465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5047eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
5048eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5049eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
5050eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
5051eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
5052eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
5053eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
5054eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 1),
5055eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 2),
5056eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 3),
5057eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_headers, 4),
5058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 5),
5059eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 6),  // EOF
5060eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
50615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5062eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
5063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
5064eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed");
5065eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
5066eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
50675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5068eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
5070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.SetDeterministic();
5071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddDeterministicData(&data);
5072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
50737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5074eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
50755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // and the body of the primary stream, but before we've received the HEADERS
5078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // for the pushed stream.
5079eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.SetStop(3);
50805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5081eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction.
5082eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
5083eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
5084eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
5085eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5086eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.Run();
5087eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
5088eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, rv);
50895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Request the pushed path.  At this point, we've received the push, but the
5091eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // headers are not yet complete.
5092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<HttpNetworkTransaction> trans2(
5093eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = trans2->Start(
5095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5096eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5097eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(3);
5098eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
50995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the server push body.
5101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string result2;
5102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ReadResult(trans2.get(), &data, &result2);
5103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the response body.
5104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string result;
5105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ReadResult(trans, &data, &result);
51065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that the received push data is same as the expected push data.
5108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(result2.compare(expected_push_result), 0)
5109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      << "Received data: "
5110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      << result2
5111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      << "||||| Expected data: "
5112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      << expected_push_result;
51135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
5115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Copy the response info, because trans goes away.
5116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  response = *trans->GetResponseInfo();
5117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  response2 = *trans2->GetResponseInfo();
51185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  VerifyStreamsClosed(helper);
51205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
5122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
5123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
51245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
5126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
5127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
51285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the final EOF (which will close the session)
5130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
51315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
5133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof());
5134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
5135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
51367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushWithTwoHeaderFrames) {
5138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // We push a stream and attempt to claim it before the headers come down.
5139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_syn(
514090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
5142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
5143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
5144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
5145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
51465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_util_.AddUrlToHeaderBlock(
5149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      "http://www.google.com/foo.dat", initial_headers.get());
5150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_syn(
5151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
5152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
5153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           2,
5154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
5155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           SYN_STREAM,
5156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
5157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           1));
5158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*middle_headers)["hello"] = "bye";
5161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_headers1(
5162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
5164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           2,
5165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
5166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           HEADERS,
5167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
5168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           0));
5169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)[spdy_util_.GetStatusKey()] = "200";
5172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_headers2(
5174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
5176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           2,
5177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
5178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           HEADERS,
5179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
5180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           0));
5181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
5183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
5185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
5186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
5187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
5188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
5189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 1),
5190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 2),
5191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 3),
5192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_headers1, 4),
5193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_headers2, 5),
5194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 6),
5195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 7),  // EOF
51965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
51975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response;
5199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response2;
5200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string expected_push_result("pushed");
5201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
5202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
5203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
52042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
52055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
5206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.SetDeterministic();
5207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddDeterministicData(&data);
5208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
52095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
52115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // the first HEADERS frame, and the body of the primary stream, but before
5214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // we've received the final HEADERS for the pushed stream.
5215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.SetStop(4);
52165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction.
5218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
5219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
5220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
5221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.Run();
5223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
5224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, rv);
52257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Request the pushed path.  At this point, we've received the push, but the
5227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // headers are not yet complete.
5228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<HttpNetworkTransaction> trans2(
5229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = trans2->Start(
5231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(3);
5234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
52355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the server push body.
5237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string result2;
5238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ReadResult(trans2.get(), &data, &result2);
5239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the response body.
5240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string result;
5241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ReadResult(trans, &data, &result);
5242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that the received push data is same as the expected push data.
5244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(expected_push_result, result2);
5245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
5247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Copy the response info, because trans goes away.
5248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  response = *trans->GetResponseInfo();
5249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  response2 = *trans2->GetResponseInfo();
52505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  VerifyStreamsClosed(helper);
52525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
5254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response.headers.get() != NULL);
5255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
52565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the pushed stream.
5258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers.get() != NULL);
5259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response2.headers->GetStatusLine());
52605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify we got all the headers
5262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (spdy_util_.spdy_version() < SPDY3) {
5263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(response2.headers->HasHeaderValue(
5264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        "url",
5265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        "http://www.google.com/foo.dat"));
5266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else {
5267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(response2.headers->HasHeaderValue(
5268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        "scheme", "http"));
5269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(response2.headers->HasHeaderValue(
5270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        "host", "www.google.com"));
5271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(response2.headers->HasHeaderValue(
5272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        "path", "/foo.dat"));
5273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
5274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers->HasHeaderValue("hello", "bye"));
5275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers->HasHeaderValue("status", "200"));
5276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response2.headers->HasHeaderValue("version", "HTTP/1.1"));
52775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the final EOF (which will close the session)
5279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
52805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
5282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof());
5283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
5284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
52857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushWithNoStatusHeaderFrames) {
5287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // We push a stream and attempt to claim it before the headers come down.
528890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> stream1_syn(
528990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
52907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> stream1_body(
52917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, true));
52925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
5293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*stream1_syn, 0, SYNCHRONOUS),
52945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
52955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
52977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  spdy_util_.AddUrlToHeaderBlock(
52987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      "http://www.google.com/foo.dat", initial_headers.get());
5299a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  scoped_ptr<SpdyFrame> stream2_syn(
53007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
5301a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           false,
5302a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           2,
5303a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           LOWEST,
5304a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           SYN_STREAM,
5305a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           CONTROL_FLAG_NONE,
5306a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           1));
53077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> middle_headers(new SpdyHeaderBlock());
5309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*middle_headers)["hello"] = "bye";
5310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_headers1(
5311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(middle_headers.Pass(),
5312a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           false,
5313a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           2,
5314a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           LOWEST,
5315a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           HEADERS,
5316a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           CONTROL_FLAG_NONE,
5317a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           0));
53185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame>
53207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char kPushedData[] = "pushed";
5322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream2_body(
5323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
5324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          2, kPushedData, strlen(kPushedData), true));
53255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
5326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply, 1),
5327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_syn, 2),
5328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body, 3),
5329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_headers1, 4),
5330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream2_body, 5),
5331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 6),  // EOF
53325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
53335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
5335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
5336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
5339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.SetDeterministic();
5340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddDeterministicData(&data);
5341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
5342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
5344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Run until we've received the primary SYN_STREAM, the pushed SYN_STREAM,
5346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // the first HEADERS frame, and the body of the primary stream, but before
5347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // we've received the final HEADERS for the pushed stream.
5348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.SetStop(4);
5349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction.
5351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
5352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(
5353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetRequest(), callback.callback(), BoundNetLog());
5354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.Run();
5356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
5357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, rv);
5358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Request the pushed path.  At this point, we've received the push, but the
5360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // headers are not yet complete.
5361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<HttpNetworkTransaction> trans2(
5362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session().get()));
5363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = trans2->Start(
5364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &CreateGetPushRequest(), callback.callback(), BoundNetLog());
5365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
5367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
5368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the server push body.
5370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string result2;
5371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ReadResult(trans2.get(), &data, &result2);
5372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the response body.
5373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string result;
5374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ReadResult(trans, &data, &result);
5375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("hello!", result);
5376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we haven't received any push data.
5378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("", result2);
5379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify the SYN_REPLY.
5381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Copy the response info, because trans goes away.
5382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response = *trans->GetResponseInfo();
5383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(trans2->GetResponseInfo() == NULL);
5384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  VerifyStreamsClosed(helper);
53865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the SYN_REPLY.
5388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response.headers.get() != NULL);
53895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
53905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read the final EOF (which will close the session).
5392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
53935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
5395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof());
5396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof());
5397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
53987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, SynReplyWithHeaders) {
5400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
540190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
5403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
5404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
5405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req),
5406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*rst),
5407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch };
5408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*initial_headers)[spdy_util_.GetStatusKey()] = "200 OK";
5411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*initial_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_reply(
5413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
5414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
5415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           1,
5416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
5417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           SYN_REPLY,
5418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
5419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           0));
5420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
5422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)["hello"] = "bye";
5423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_headers(
5424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
5426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           1,
5427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
5428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           HEADERS,
5429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
5430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           0));
54317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyFrame> stream1_body(
54327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, true));
5433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
5434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply),
5435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_headers),
5436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body),
5437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
5438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
5439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(1, reads, arraysize(reads),
5441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
5442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
5444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunToCompletion(&data);
5445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out = helper.output();
5446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
5448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, SynReplyWithLateHeaders) {
5450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
5451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
5453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
54545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
5455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req),
5456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*rst),
54575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
54585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> initial_headers(new SpdyHeaderBlock());
5460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*initial_headers)[spdy_util_.GetStatusKey()] = "200 OK";
5461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*initial_headers)[spdy_util_.GetVersionKey()] = "HTTP/1.1";
5462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_reply(
54637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyControlFrame(initial_headers.Pass(),
5464a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           false,
5465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           1,
5466a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           LOWEST,
5467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           SYN_REPLY,
5468a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           CONTROL_FLAG_NONE,
5469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           0));
54707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
54717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
54727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  (*late_headers)["hello"] = "bye";
5473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_headers(
54747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
5475a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           false,
5476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           1,
5477a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           LOWEST,
5478a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           HEADERS,
5479a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           CONTROL_FLAG_NONE,
5480a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                           0));
5481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body(
5482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, false));
5483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> stream1_body2(
5484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, true));
54855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
5486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_reply),
5487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body),
5488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_headers),
5489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*stream1_body2),
5490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
54915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
54925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(1, reads, arraysize(reads),
5494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
5495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
5496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
5497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunToCompletion(&data);
5498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TransactionHelperResult out = helper.output();
5499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, out.rv);
5500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
5501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, ServerPushCrossOriginCorrectness) {
5503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // In this test we want to verify that we can't accidentally push content
5504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // which can't be pushed by this content server.
5505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // This test assumes that:
5506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   - if we're requesting http://www.foo.com/barbaz
5507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  //   - the browser has made a connection to "www.foo.com".
5508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // A list of the URL to fetch, followed by the URL being pushed.
5510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static const char* const kTestCases[] = {
5511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://www.google.com/foo.html",
5512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://www.google.com:81/foo.js",     // Bad port
5513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://www.google.com/foo.html",
5515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "https://www.google.com/foo.js",       // Bad protocol
5516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://www.google.com/foo.html",
5518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "ftp://www.google.com/foo.js",         // Invalid Protocol
5519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://www.google.com/foo.html",
5521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://blat.www.google.com/foo.js",   // Cross subdomain
5522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://www.google.com/foo.html",
5524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "http://www.foo.com/foo.js",           // Cross domain
5525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
5526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t index = 0; index < arraysize(kTestCases); index += 2) {
5528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const char* url_to_fetch = kTestCases[index];
5529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const char* url_to_push = kTestCases[index + 1];
5530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame> stream1_syn(
5532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        spdy_util_.ConstructSpdyGet(url_to_fetch, false, 1, LOWEST));
5533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame> stream1_body(
5534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        spdy_util_.ConstructSpdyBodyFrame(1, true));
5535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame> push_rst(
5536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
5537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockWrite writes[] = {
5538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateMockWrite(*stream1_syn, 1),
5539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateMockWrite(*push_rst, 4),
5540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    };
5541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame>
5543eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame>
5545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
5546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                 0,
5547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                 2,
5548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                 1,
5549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                 url_to_push));
5550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const char kPushedData[] = "pushed";
5551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame> stream2_body(
5552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        spdy_util_.ConstructSpdyBodyFrame(
5553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            2, kPushedData, strlen(kPushedData), true));
5554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdyFrame> rst(
5555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_CANCEL));
5556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead reads[] = {
5558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateMockRead(*stream1_reply, 2),
5559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateMockRead(*stream2_syn, 3),
5560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateMockRead(*stream1_body, 5, SYNCHRONOUS),
5561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateMockRead(*stream2_body, 6),
5562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      MockRead(ASYNC, ERR_IO_PENDING, 7),  // Force a pause
5563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    };
5564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    HttpResponseInfo response;
5566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    OrderedSocketData data(reads, arraysize(reads),
5567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           writes, arraysize(writes));
5568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    HttpRequestInfo request;
5570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    request.method = "GET";
5571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    request.url = GURL(url_to_fetch);
5572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    request.load_flags = 0;
5573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Enable cross-origin push. Since we are not using a proxy, this should
5575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // not actually enable cross-origin SPDY push.
5576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<SpdySessionDependencies> session_deps(
5577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        CreateSpdySessionDependencies(GetParam()));
5578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    session_deps->trusted_spdy_proxy = "123.45.67.89:8080";
5579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
5580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       BoundNetLog(), GetParam(),
5581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       session_deps.release());
5582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    helper.RunPreTestSetup();
5583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    helper.AddData(&data);
5584eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5585eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    HttpNetworkTransaction* trans = helper.trans();
55865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Start the transaction with basic parameters.
5588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    TestCompletionCallback callback;
5589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ(ERR_IO_PENDING, rv);
5592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    rv = callback.WaitForResult();
5593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Read the response body.
5595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string result;
5596eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ReadResult(trans, &data, &result);
5597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Verify that we consumed all test data.
5599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(data.at_read_eof());
5600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(data.at_write_eof());
5601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5602eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Verify the SYN_REPLY.
5603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Copy the response info, because trans goes away.
5604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    response = *trans->GetResponseInfo();
5605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    VerifyStreamsClosed(helper);
5607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Verify the SYN_REPLY.
5609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_TRUE(response.headers.get() != NULL);
5610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
5611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
5612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
5613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5614eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) {
5615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct the request.
5616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(
5617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5618eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
5619eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
5620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
5621eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 1),
5622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 3),
5623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
5624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> refused(
5626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_REFUSED_STREAM));
5627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(3, true));
5629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
5630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*refused, 2),
5631eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 4),
5632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body, 5),
5633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 6)  // EOF
5634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
5635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(reads, arraysize(reads),
5637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes, arraysize(writes));
56382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
56395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
5640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
56415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
5642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
56435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
56445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
56455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the transaction with basic parameters.
56475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
56485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = trans->Start(
56495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &CreateGetRequest(), callback.callback(), BoundNetLog());
56505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
56515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback.WaitForResult();
5652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv);
56535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Verify that we consumed all test data.
5655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_read_eof()) << "Read count: "
5656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_count()
5657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << " Read index: "
5658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                   << data.read_index();
5659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(data.at_write_eof()) << "Write count: "
5660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_count()
5661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << " Write index: "
5662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                    << data.write_index();
56635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
56645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the SYN_REPLY.
5665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpResponseInfo response = *trans->GetResponseInfo();
5666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRUE(response.headers.get() != NULL);
56675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1 200 OK", response.headers->GetStatusLine());
56685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
56695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, OutOfOrderSynStream) {
5671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // This first request will start to establish the SpdySession.
5672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Then we will start the second (MEDIUM priority) and then third
5673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // (HIGHEST priority) request in such a way that the third will actually
5674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // start before the second, causing the second to be numbered differently
5675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // than the order they were created.
5676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req1(
567790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req2(
5679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, HIGHEST, true));
5680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req3(
5681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 5, MEDIUM, true));
56825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
5683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req1, 0),
5684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req2, 3),
5685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req3, 4),
56865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
56875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
5690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5691eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
5692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp3(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 5));
5693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(5, true));
56945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
5695eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp1, 1),
5696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body1, 2),
5697eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp2, 5),
5698eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body2, 6),
5699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp3, 7),
5700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body3, 8),
5701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 9)  // EOF
57025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
57035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
57055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
5706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(CreateGetRequest(), LOWEST,
57075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
57085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.SetDeterministic();
57095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
5710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddDeterministicData(&data);
57115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5712eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Start the first transaction to set up the SpdySession
57135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
57145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
5715eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo info1 = CreateGetRequest();
5716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(&info1, callback.callback(), BoundNetLog());
57175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
57185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5719eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Run the message loop, but do not allow the write to complete.
5720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // This leaves the SpdySession with a write pending, which prevents
5721eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // SpdySession from attempting subsequent writes until this write completes.
5722eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
5723eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5724eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Now, start both new transactions
5725eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo info2 = CreateGetRequest();
5726eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback2;
57275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpNetworkTransaction> trans2(
5728eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new HttpNetworkTransaction(MEDIUM, helper.session().get()));
5729eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = trans2->Start(&info2, callback2.callback(), BoundNetLog());
57305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
573190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
57325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5733eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo info3 = CreateGetRequest();
5734eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback3;
5735eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<HttpNetworkTransaction> trans3(
5736eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new HttpNetworkTransaction(HIGHEST, helper.session().get()));
5737eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = trans3->Start(&info3, callback3.callback(), BoundNetLog());
5738eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5739eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
57405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5741eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // We now have two SYN_STREAM frames queued up which will be
5742eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // dequeued only once the first write completes, which we
5743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // now allow to happen.
5744eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
5745eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, callback.WaitForResult());
57465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5747eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // And now we can allow everything else to run to completion.
5748eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.SetStop(10);
5749eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.Run();
5750eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, callback2.WaitForResult());
5751eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, callback3.WaitForResult());
57525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5753eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
5754eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
57555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5756eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The tests below are only for SPDY/3 and above.
57575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5758eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test that sent data frames and received WINDOW_UPDATE frames change
5759eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// the send_window_size_ correctly.
57605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5761eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// WINDOW_UPDATE is different than most other frames in that it can arrive
5762eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// while the client is still sending the request body.  In order to enforce
5763eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// this scenario, we feed a couple of dummy frames and give a delay of 0 to
5764eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// socket data provider, so that initial read that is done as soon as the
5765eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// stream is created, succeeds and schedules another read.  This way reads
5766eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// and writes are interleaved; after doing a full frame write, SpdyStream
5767eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// will break out of DoLoop and will read and process a WINDOW_UPDATE.
5768eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Once our WINDOW_UPDATE is read, we cannot send SYN_REPLY right away
5769eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// since request has not been completely written, therefore we feed
5770eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// enough number of WINDOW_UPDATEs to finish the first read and cause a
5771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// write, leading to a complete write of request body; after that we send
5772eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// a reply with a body, to cause a graceful shutdown.
57735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TODO(agayev): develop a socket data provider where both, reads and
5775eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// writes are ordered so that writing tests like these are easy and rewrite
5776eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// all these tests using it.  Right now we are working around the
5777eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// limitations as described above and it's not deterministic, tests may
5778eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// fail under specific circumstances.
5779eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
5780eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol < kProtoSPDY3)
57817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
57827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5783eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static int kFrameCount = 2;
5784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<std::string> content(
5785eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new std::string(kMaxSpdyFrameChunkSize, 'a'));
5786eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
5787eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
5788eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(
5789eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
5790eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content->c_str(), content->size(), false));
5791eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body_end(
5792eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
5793eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content->c_str(), content->size(), true));
5794eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
57955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
5796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
5797eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body, 1),
5798eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body_end, 2),
57995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
58005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5801eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static const int32 kDeltaWindowSize = 0xff;
5802eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static const int kDeltaCount = 4;
5803eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update(
5804eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
5805eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update_dummy(
5806eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
5807eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
58085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
5809eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update_dummy, 3),
5810eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update_dummy, 4),
5811eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update_dummy, 5),
5812eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update, 6),     // Four updates, therefore window
5813eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update, 7),     // size should increase by
5814eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update, 8),     // kDeltaWindowSize * 4
5815eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update, 9),
5816eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp, 10),
5817eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body_end, 11),
5818eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0, 12)  // EOF
58195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
58205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeterministicSocketData data(reads, arraysize(reads),
58225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               writes, arraysize(writes));
58235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5824eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<UploadElementReader> element_readers;
5825eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (int i = 0; i < kFrameCount; ++i) {
5826eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    element_readers.push_back(
5827eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        new UploadBytesElementReader(content->c_str(), content->size()));
5828eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
5829eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UploadDataStream upload_data_stream(&element_readers, 0);
5830eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5831eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Setup the request
5832eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo request;
5833eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.method = "POST";
5834eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.url = GURL(kDefaultURL);
5835eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.upload_data_stream = &upload_data_stream;
5836eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5837eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
58385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
58395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.SetDeterministic();
58405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddDeterministicData(&data);
58415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
58425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
58445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
5846eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
58475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
58495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5850eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(11);
58515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5852eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
5853eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream != NULL);
5854eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream->stream() != NULL);
5855eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize) +
5856eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            kDeltaWindowSize * kDeltaCount -
5857eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            kMaxSpdyFrameChunkSize * kFrameCount,
5858eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream->stream()->send_window_size());
58595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.RunFor(1);
58615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5862eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
5863eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv);
5864eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
58665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
58675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5868eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test that received data frames and sent WINDOW_UPDATE frames change
5869eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// the recv_window_size_ correctly.
5870eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) {
5871eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol < kProtoSPDY3)
58727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
58737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5874eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Set the data in the body frame large enough to trigger sending a
5875eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // WINDOW_UPDATE by the stream.
5876eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const std::string body_data(kSpdyStreamInitialWindowSize / 2 + 1, 'x');
5877eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
587890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
587990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
5880eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> session_window_update(
5881eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(0, body_data.size()));
5882eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update(
5883eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(1, body_data.size()));
58845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<MockWrite> writes;
5886eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*req));
5887eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol >= kProtoSPDY31)
5888eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    writes.push_back(CreateMockWrite(*session_window_update));
5889eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*window_update));
58907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> resp(
5892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
5893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body_no_fin(
5894eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
5895eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, body_data.data(), body_data.size(), false));
5896eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body_fin(
5897eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(1, NULL, 0, true));
58985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
5899eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*resp),
5900eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body_no_fin),
5901eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 0),  // Force a pause
5902eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body_fin),
5903eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, ERR_IO_PENDING, 0),  // Force a pause
59045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, 0, 0)  // EOF
59055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
59065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data(1, reads, arraysize(reads),
5908eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         vector_as_array(&writes), writes.size());
5909eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
59102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
59115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
5912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
5913eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
5914eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
5915eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
5917eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
5918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5919eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
5920eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
5921eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, rv);
5922eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5923eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyHttpStream* stream =
5924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      static_cast<SpdyHttpStream*>(trans->stream_.get());
5925eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream != NULL);
5926eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream->stream() != NULL);
5927eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5928eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(
5929eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      static_cast<int>(kSpdyStreamInitialWindowSize - body_data.size()),
5930eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      stream->stream()->recv_window_size());
5931eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5932eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const HttpResponseInfo* response = trans->GetResponseInfo();
5933eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(response != NULL);
5934eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(response->headers.get() != NULL);
5935eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5936eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(response->was_fetched_via_spdy);
5937eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5938eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Issue a read which will cause a WINDOW_UPDATE to be sent and window
5939eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // size increased to default.
5940eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(body_data.size()));
5941eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = trans->Read(buf.get(), body_data.size(), CompletionCallback());
5942eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(static_cast<int>(body_data.size()), rv);
5943eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string content(buf->data(), buf->data() + body_data.size());
5944eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(body_data, content);
5945eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5946eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Schedule the reading of empty data frame with FIN
5947eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.CompleteRead();
5948eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5949eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Force write of WINDOW_UPDATE which was scheduled during the above
5950eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // read.
5951eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
5952eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5953eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read EOF.
5954eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.CompleteRead();
5955eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5956eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
59575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
59585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5959eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test that WINDOW_UPDATE frame causing overflow is handled correctly.
5960eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
5961eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol < kProtoSPDY3)
59627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
59637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5964eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Number of full frames we hope to write (but will not, used to
5965eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // set content-length header correctly)
5966eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static int kFrameCount = 3;
59675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5968eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<std::string> content(
5969eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      new std::string(kMaxSpdyFrameChunkSize, 'a'));
5970eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
5971eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kRequestUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, NULL, 0));
5972eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body(
5973eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
5974eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content->c_str(), content->size(), false));
5975eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
5976eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
59777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5978eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // We're not going to write a data frame with FIN, we'll receive a bad
5979eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
5980eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockWrite writes[] = {
5981eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*req, 0),
5982eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*body, 2),
5983eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockWrite(*rst, 3),
5984eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
5985eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5986eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static const int32 kDeltaWindowSize = 0x7fffffff;  // cause an overflow
5987eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update(
5988eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
59895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
5990eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update, 1),
5991eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 4)  // EOF
59925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
59935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5994eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(reads, arraysize(reads),
5995eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               writes, arraysize(writes));
5996eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5997eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<UploadElementReader> element_readers;
5998eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (int i = 0; i < kFrameCount; ++i) {
5999eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    element_readers.push_back(
6000eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        new UploadBytesElementReader(content->c_str(), content->size()));
6001eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
6002eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UploadDataStream upload_data_stream(&element_readers, 0);
6003eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6004eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Setup the request
6005eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo request;
6006eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.method = "POST";
6007eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.url = GURL("http://www.google.com/");
6008eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.upload_data_stream = &upload_data_stream;
6009eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6010eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
60115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
6012eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.SetDeterministic();
6013eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
6014eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddDeterministicData(&data);
6015eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
6016eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6017eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
6018eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6019eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(ERR_IO_PENDING, rv);
6020eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6021eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(5);
6022eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(callback.have_result());
6023eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
6024eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
60255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
60265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6027eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test that after hitting a send window size of 0, the write process
6028eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// stalls and upon receiving WINDOW_UPDATE frame write resumes.
6029eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6030eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// This test constructs a POST request followed by enough data frames
6031eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// containing 'a' that would make the window size 0, followed by another
6032eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// data frame containing default content (which is "hello!") and this frame
6033eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// also contains a FIN flag.  DelayedSocketData is used to enforce all
6034eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// writes go through before a read could happen.  However, the last frame
6035eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// ("hello!")  is not supposed to go through since by the time its turn
6036eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// arrives, window size is 0.  At this point MessageLoop::Run() called via
6037eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// callback would block.  Therefore we call MessageLoop::RunUntilIdle()
6038eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// which returns after performing all possible writes.  We use DCHECKS to
6039eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// ensure that last data frame is still there and stream has stalled.
6040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// After that, next read is artifically enforced, which causes a
6041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// WINDOW_UPDATE to be read and I/O process resumes.
6042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
6043eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol < kProtoSPDY3)
60447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
60457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
6046eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Number of frames we need to send to zero out the window size: data
6047eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // frames plus SYN_STREAM plus the last data frame; also we need another
6048eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // data frame that we will send once the WINDOW_UPDATE is received,
6049eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // therefore +3.
6050eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
60515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6052eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Calculate last frame's size; 0 size data frame is legal.
6053eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t last_frame_size =
6054eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
60557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
6056eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct content for a data frame of maximum size.
6057eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string content(kMaxSpdyFrameChunkSize, 'a');
60585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6059eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6060eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      LOWEST, NULL, 0));
60625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Full frames.
6064eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(
6065eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
6066eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content.c_str(), content.size(), false));
60677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
6068eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Last frame to zero out the window size.
6069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(
6070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
6071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content.c_str(), last_frame_size, false));
60725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Data frame to be sent once WINDOW_UPDATE frame is received.
6074eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
60755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Fill in mock writes.
6077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<MockWrite[]> writes(new MockWrite[num_writes]);
6078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t i = 0;
6079eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes[i] = CreateMockWrite(*req);
6080eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (i = 1; i < num_writes - 2; i++)
6081eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    writes[i] = CreateMockWrite(*body1);
6082eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes[i++] = CreateMockWrite(*body2);
6083eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes[i] = CreateMockWrite(*body3);
60845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct read frame, give enough space to upload the rest of the
6086eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // data.
6087eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> session_window_update(
6088eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6089eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update(
6090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize));
6091eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockRead reads[] = {
6093eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*session_window_update),
6094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*session_window_update),
6095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update),
6096eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*window_update),
6097eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*reply),
6098eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body2),
6099eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    CreateMockRead(*body3),
6100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    MockRead(ASYNC, 0, 0)  // EOF
6101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  };
61025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Skip the session window updates unless we're using SPDY/3.1 and
6104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // above.
6105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t read_offset = (GetParam().protocol >= kProtoSPDY31) ? 0 : 2;
6106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t num_reads = arraysize(reads) - read_offset;
61075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Force all writes to happen before any read, last write will not
6109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // actually queue a frame, due to window size being 0.
6110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DelayedSocketData data(num_writes, reads + read_offset, num_reads,
6111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         writes.get(), num_writes);
61125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<UploadElementReader> element_readers;
6114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  upload_data_string.append(kUploadData, kUploadDataSize);
6116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  element_readers.push_back(new UploadBytesElementReader(
6117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      upload_data_string.c_str(), upload_data_string.size()));
6118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UploadDataStream upload_data_stream(&element_readers, 0);
61195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo request;
6121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.method = "POST";
6122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.url = GURL("http://www.google.com/");
6123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.upload_data_stream = &upload_data_stream;
6124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
6125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                     BoundNetLog(), GetParam(), NULL);
6126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddData(&data);
6127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.RunPreTestSetup();
61285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpNetworkTransaction* trans = helper.trans();
61305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
6132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
6133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING, rv);
61345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();  // Write as much as we can.
61365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream != NULL);
6139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream->stream() != NULL);
6140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, stream->stream()->send_window_size());
6141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // All the body data should have been read.
6142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(satorux): This is because of the weirdness in reading the request
6143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // body in OnSendBodyComplete(). See crbug.com/113107.
6144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(upload_data_stream.IsEOF());
6145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // But the body is not yet fully sent (kUploadData is not yet sent)
6146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // since we're send-stalled.
6147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
61485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.ForceNextRead();   // Read in WINDOW_UPDATE frame.
6150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
6151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
6152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
61535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test we correctly handle the case where the SETTINGS frame results in
6155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// unstalling the send window.
6156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
6157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol < kProtoSPDY3)
6158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
61595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Number of frames we need to send to zero out the window size: data
6161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // frames plus SYN_STREAM plus the last data frame; also we need another
6162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // data frame that we will send once the SETTING is received, therefore +3.
6163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
61645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Calculate last frame's size; 0 size data frame is legal.
6166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t last_frame_size =
6167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
61685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct content for a data frame of maximum size.
6170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string content(kMaxSpdyFrameChunkSize, 'a');
6171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      LOWEST, NULL, 0));
6175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Full frames.
6177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(
6178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
6179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content.c_str(), content.size(), false));
6180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Last frame to zero out the window size.
6182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(
6183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
6184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content.c_str(), last_frame_size, false));
61855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Data frame to be sent once SETTINGS frame is received.
6187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
61885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Fill in mock reads/writes.
6190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<MockRead> reads;
6191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<MockWrite> writes;
6192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t i = 0;
6193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*req, i++));
6194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  while (i < num_writes - 2)
6195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    writes.push_back(CreateMockWrite(*body1, i++));
6196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*body2, i++));
61975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct read frame for SETTINGS that gives enough space to upload the
6199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // rest of the data.
6200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SettingsMap settings;
6201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SettingsFlagsAndValue(
6203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize * 2);
6204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> settings_frame_large(
6205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySettings(settings));
62065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*settings_frame_large, i++));
62085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> session_window_update(
6210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(0, kUploadDataSize));
6211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol >= kProtoSPDY31)
6212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    reads.push_back(CreateMockRead(*session_window_update, i++));
62135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*body3, i++));
62155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*reply, i++));
6218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*body2, i++));
6219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*body3, i++));
6220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(MockRead(ASYNC, 0, i++));  // EOF
62217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
6222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Force all writes to happen before any read, last write will not
6223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // actually queue a frame, due to window size being 0.
6224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               vector_as_array(&writes), writes.size());
62265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<UploadElementReader> element_readers;
6228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  upload_data_string.append(kUploadData, kUploadDataSize);
6230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  element_readers.push_back(new UploadBytesElementReader(
6231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      upload_data_string.c_str(), upload_data_string.size()));
6232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UploadDataStream upload_data_stream(&element_readers, 0);
62335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo request;
6235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.method = "POST";
6236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.url = GURL("http://www.google.com/");
6237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.upload_data_stream = &upload_data_stream;
6238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
62395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
6240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.SetDeterministic();
62415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
6242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.AddDeterministicData(&data);
62435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
62445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
62455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
62465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
6247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
62485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
62495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(num_writes - 1);   // Write as much as we can.
62515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream != NULL);
6254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream->stream() != NULL);
6255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, stream->stream()->send_window_size());
6256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // All the body data should have been read.
6258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(satorux): This is because of the weirdness in reading the request
6259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // body in OnSendBodyComplete(). See crbug.com/113107.
6260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(upload_data_stream.IsEOF());
6261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // But the body is not yet fully sent (kUploadData is not yet sent)
6262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // since we're send-stalled.
6263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
6264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(6);   // Read in SETTINGS frame to unstall.
6266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
6267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  helper.VerifyDataConsumed();
6268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // If stream is NULL, that means it was unstalled and closed.
6269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream->stream() == NULL);
62705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
62715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Test we correctly handle the case where the SETTINGS frame results in a
6273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// negative send window size.
6274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
6275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol < kProtoSPDY3)
62767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
62777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
6278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Number of frames we need to send to zero out the window size: data
6279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // frames plus SYN_STREAM plus the last data frame; also we need another
6280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // data frame that we will send once the SETTING is received, therefore +3.
6281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t num_writes = kSpdyStreamInitialWindowSize / kMaxSpdyFrameChunkSize + 3;
62825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Calculate last frame's size; 0 size data frame is legal.
6284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t last_frame_size =
6285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kSpdyStreamInitialWindowSize % kMaxSpdyFrameChunkSize;
62865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct content for a data frame of maximum size.
6288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string content(kMaxSpdyFrameChunkSize, 'a');
6289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyPost(
6291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      kRequestUrl, 1, kSpdyStreamInitialWindowSize + kUploadDataSize,
6292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      LOWEST, NULL, 0));
6293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Full frames.
6295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body1(
6296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
6297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content.c_str(), content.size(), false));
6298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Last frame to zero out the window size.
6300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body2(
6301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyBodyFrame(
6302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          1, content.c_str(), last_frame_size, false));
6303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Data frame to be sent once SETTINGS frame is received.
6305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> body3(spdy_util_.ConstructSpdyBodyFrame(1, true));
6306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Fill in mock reads/writes.
6308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<MockRead> reads;
6309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<MockWrite> writes;
6310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  size_t i = 0;
6311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*req, i++));
6312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  while (i < num_writes - 2)
6313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    writes.push_back(CreateMockWrite(*body1, i++));
6314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*body2, i++));
6315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct read frame for SETTINGS that makes the send_window_size
6317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // negative.
6318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SettingsMap new_settings;
6319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  new_settings[SETTINGS_INITIAL_WINDOW_SIZE] =
6320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SettingsFlagsAndValue(
6321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          SETTINGS_FLAG_NONE, kSpdyStreamInitialWindowSize / 2);
6322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> settings_frame_small(
6323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdySettings(new_settings));
6324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Construct read frames for WINDOW_UPDATE that makes the send_window_size
6325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // positive.
6326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> session_window_update_init_size(
6327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(0, kSpdyStreamInitialWindowSize));
6328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> window_update_init_size(
6329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWindowUpdate(1, kSpdyStreamInitialWindowSize));
6330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*settings_frame_small, i++));
6332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (GetParam().protocol >= kProtoSPDY3)
6334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    reads.push_back(CreateMockRead(*session_window_update_init_size, i++));
6335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*window_update_init_size, i++));
6337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  writes.push_back(CreateMockWrite(*body3, i++));
6339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> reply(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
6341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*reply, i++));
6342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*body2, i++));
6343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(CreateMockRead(*body3, i++));
6344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  reads.push_back(MockRead(ASYNC, 0, i++));  // EOF
6345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Force all writes to happen before any read, last write will not
6347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // actually queue a frame, due to window size being 0.
6348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(vector_as_array(&reads), reads.size(),
6349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               vector_as_array(&writes), writes.size());
6350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ScopedVector<UploadElementReader> element_readers;
6352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string upload_data_string(kSpdyStreamInitialWindowSize, 'a');
6353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  upload_data_string.append(kUploadData, kUploadDataSize);
6354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  element_readers.push_back(new UploadBytesElementReader(
6355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      upload_data_string.c_str(), upload_data_string.size()));
6356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UploadDataStream upload_data_stream(&element_readers, 0);
6357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  HttpRequestInfo request;
6359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.method = "POST";
6360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.url = GURL("http://www.google.com/");
6361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request.upload_data_stream = &upload_data_stream;
6362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NormalSpdyTransactionHelper helper(request, DEFAULT_PRIORITY,
63635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     BoundNetLog(), GetParam(), NULL);
63645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.SetDeterministic();
63655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.RunPreTestSetup();
63665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.AddDeterministicData(&data);
63675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkTransaction* trans = helper.trans();
63695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallback callback;
6371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
63725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
63735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(num_writes - 1);   // Write as much as we can.
63755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyHttpStream* stream = static_cast<SpdyHttpStream*>(trans->stream_.get());
6377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream != NULL);
6378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream->stream() != NULL);
6379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(0, stream->stream()->send_window_size());
63805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // All the body data should have been read.
6382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(satorux): This is because of the weirdness in reading the request
6383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // body in OnSendBodyComplete(). See crbug.com/113107.
6384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(upload_data_stream.IsEOF());
6385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // But the body is not yet fully sent (kUploadData is not yet sent)
6386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // since we're send-stalled.
6387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(stream->stream()->send_stalled_by_flow_control());
63885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Read in WINDOW_UPDATE or SETTINGS frame.
6390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor((GetParam().protocol >= kProtoSPDY31) ? 8 : 7);
6391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  rv = callback.WaitForResult();
63925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  helper.VerifyDataConsumed();
63935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
63945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
6396