// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/spdy/spdy_websocket_stream.h"

#include <string>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "net/base/completion_callback.h"
#include "net/proxy/proxy_server.h"
#include "net/socket/ssl_client_socket.h"
#include "net/spdy/spdy_http_utils.h"
#include "net/spdy/spdy_protocol.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_test_util_spdy2.h"
#include "net/spdy/spdy_websocket_test_util_spdy2.h"
#include "testing/gtest/include/gtest/gtest.h"

using namespace net::test_spdy2;

namespace net {

namespace {

struct SpdyWebSocketStreamEvent {
  enum EventType {
    EVENT_CREATED,
    EVENT_SENT_HEADERS,
    EVENT_RECEIVED_HEADER,
    EVENT_SENT_DATA,
    EVENT_RECEIVED_DATA,
    EVENT_CLOSE,
  };
  SpdyWebSocketStreamEvent(EventType type,
                           const SpdyHeaderBlock& headers,
                           int result,
                           const std::string& data)
      : event_type(type),
        headers(headers),
        result(result),
        data(data) {}

  EventType event_type;
  SpdyHeaderBlock headers;
  int result;
  std::string data;
};

class SpdyWebSocketStreamEventRecorder : public SpdyWebSocketStream::Delegate {
 public:
  explicit SpdyWebSocketStreamEventRecorder(const CompletionCallback& callback)
      : callback_(callback) {}
  virtual ~SpdyWebSocketStreamEventRecorder() {}

  typedef base::Callback<void(SpdyWebSocketStreamEvent*)> StreamEventCallback;

  void SetOnCreated(const StreamEventCallback& callback) {
    on_created_ = callback;
  }
  void SetOnSentHeaders(const StreamEventCallback& callback) {
    on_sent_headers_ = callback;
  }
  void SetOnReceivedHeader(const StreamEventCallback& callback) {
    on_received_header_ = callback;
  }
  void SetOnSentData(const StreamEventCallback& callback) {
    on_sent_data_ = callback;
  }
  void SetOnReceivedData(const StreamEventCallback& callback) {
    on_received_data_ = callback;
  }
  void SetOnClose(const StreamEventCallback& callback) {
    on_close_ = callback;
  }

  virtual void OnCreatedSpdyStream(int result) {
    events_.push_back(
        SpdyWebSocketStreamEvent(SpdyWebSocketStreamEvent::EVENT_CREATED,
                                 SpdyHeaderBlock(),
                                 result,
                                 std::string()));
    if (!on_created_.is_null())
      on_created_.Run(&events_.back());
  }
  virtual void OnSentSpdyHeaders(int result) {
    events_.push_back(
        SpdyWebSocketStreamEvent(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
                                 SpdyHeaderBlock(),
                                 result,
                                 std::string()));
    if (!on_sent_data_.is_null())
      on_sent_data_.Run(&events_.back());
  }
  virtual int OnReceivedSpdyResponseHeader(
      const SpdyHeaderBlock& headers, int status) {
    events_.push_back(
        SpdyWebSocketStreamEvent(
            SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
            headers,
            status,
            std::string()));
    if (!on_received_header_.is_null())
      on_received_header_.Run(&events_.back());
    return status;
  }
  virtual void OnSentSpdyData(int amount_sent) {
    events_.push_back(
        SpdyWebSocketStreamEvent(
            SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
            SpdyHeaderBlock(),
            amount_sent,
            std::string()));
    if (!on_sent_data_.is_null())
      on_sent_data_.Run(&events_.back());
  }
  virtual void OnReceivedSpdyData(const char* data, int length) {
    events_.push_back(
        SpdyWebSocketStreamEvent(
            SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
            SpdyHeaderBlock(),
            length,
            std::string(data, length)));
    if (!on_received_data_.is_null())
      on_received_data_.Run(&events_.back());
  }
  virtual void OnCloseSpdyStream() {
    events_.push_back(
        SpdyWebSocketStreamEvent(
            SpdyWebSocketStreamEvent::EVENT_CLOSE,
            SpdyHeaderBlock(),
            OK,
            std::string()));
    if (!on_close_.is_null())
      on_close_.Run(&events_.back());
    if (!callback_.is_null())
      callback_.Run(OK);
  }

  const std::vector<SpdyWebSocketStreamEvent>& GetSeenEvents() const {
    return events_;
  }

 private:
  std::vector<SpdyWebSocketStreamEvent> events_;
  StreamEventCallback on_created_;
  StreamEventCallback on_sent_headers_;
  StreamEventCallback on_received_header_;
  StreamEventCallback on_sent_data_;
  StreamEventCallback on_received_data_;
  StreamEventCallback on_close_;
  CompletionCallback callback_;

  DISALLOW_COPY_AND_ASSIGN(SpdyWebSocketStreamEventRecorder);
};

}  // namespace

class SpdyWebSocketStreamSpdy2Test : public testing::Test {
 public:
  OrderedSocketData* data() { return data_.get(); }

  void DoSendHelloFrame(SpdyWebSocketStreamEvent* event) {
    // Record the actual stream_id.
    created_stream_id_ = websocket_stream_->stream_->stream_id();
    websocket_stream_->SendData(kMessageFrame, kMessageFrameLength);
  }

  void DoSendClosingFrame(SpdyWebSocketStreamEvent* event) {
    websocket_stream_->SendData(kClosingFrame, kClosingFrameLength);
  }

  void DoClose(SpdyWebSocketStreamEvent* event) {
    websocket_stream_->Close();
  }

  void DoSync(SpdyWebSocketStreamEvent* event) {
    sync_callback_.callback().Run(OK);
  }

 protected:
  SpdyWebSocketStreamSpdy2Test() {}
  virtual ~SpdyWebSocketStreamSpdy2Test() {}

  virtual void SetUp() {
    host_port_pair_.set_host("example.com");
    host_port_pair_.set_port(80);
    host_port_proxy_pair_.first = host_port_pair_;
    host_port_proxy_pair_.second = ProxyServer::Direct();

    spdy_settings_id_to_set_ = SETTINGS_MAX_CONCURRENT_STREAMS;
    spdy_settings_flags_to_set_ = SETTINGS_FLAG_PLEASE_PERSIST;
    spdy_settings_value_to_set_ = 1;

    spdy_settings_to_send_[spdy_settings_id_to_set_] =
        SettingsFlagsAndValue(
            SETTINGS_FLAG_PERSISTED, spdy_settings_value_to_set_);
  }

  virtual void TearDown() {
    MessageLoop::current()->RunUntilIdle();
  }

  void Prepare(SpdyStreamId stream_id) {
    stream_id_ = stream_id;

    request_frame_.reset(ConstructSpdyWebSocketSynStream(
        stream_id_,
        "/echo",
        "example.com",
        "http://example.com/wsdemo"));

    response_frame_.reset(ConstructSpdyWebSocketSynReply(stream_id_));

    message_frame_.reset(ConstructSpdyWebSocketDataFrame(
        kMessageFrame,
        kMessageFrameLength,
        stream_id_,
        false));

    closing_frame_.reset(ConstructSpdyWebSocketDataFrame(
        kClosingFrame,
        kClosingFrameLength,
        stream_id_,
        false));
  }

  int InitSession(MockRead* reads, size_t reads_count,
                  MockWrite* writes, size_t writes_count,
                  bool throttling) {
    data_.reset(new OrderedSocketData(reads, reads_count,
                                      writes, writes_count));
    session_deps_.socket_factory->AddSocketDataProvider(data_.get());
    http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
    SpdySessionPool* spdy_session_pool(http_session_->spdy_session_pool());

    if (throttling) {
      // Set max concurrent streams to 1.
      spdy_session_pool->http_server_properties()->SetSpdySetting(
          host_port_pair_,
          spdy_settings_id_to_set_,
          spdy_settings_flags_to_set_,
          spdy_settings_value_to_set_);
    }

    EXPECT_FALSE(spdy_session_pool->HasSession(host_port_proxy_pair_));
    session_ = spdy_session_pool->Get(host_port_proxy_pair_, BoundNetLog());
    EXPECT_TRUE(spdy_session_pool->HasSession(host_port_proxy_pair_));
    transport_params_ = new TransportSocketParams(host_port_pair_, MEDIUM,
                                                  false, false,
                                                  OnHostResolutionCallback());
    TestCompletionCallback callback;
    scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
    EXPECT_EQ(ERR_IO_PENDING,
              connection->Init(host_port_pair_.ToString(), transport_params_,
                               MEDIUM, callback.callback(),
                               http_session_->GetTransportSocketPool(
                                   HttpNetworkSession::NORMAL_SOCKET_POOL),
                               BoundNetLog()));
    EXPECT_EQ(OK, callback.WaitForResult());
    return session_->InitializeWithSocket(connection.release(), false, OK);
  }

  void SendRequest() {
    scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock);
    (*headers)["path"] = "/echo";
    (*headers)["host"] = "example.com";
    (*headers)["version"] = "WebSocket/13";
    (*headers)["scheme"] = "ws";
    (*headers)["origin"] = "http://example.com/wsdemo";

    websocket_stream_->SendRequest(headers.Pass());
  }

  SpdySettingsIds spdy_settings_id_to_set_;
  SpdySettingsFlags spdy_settings_flags_to_set_;
  uint32 spdy_settings_value_to_set_;
  SettingsMap spdy_settings_to_send_;
  SpdySessionDependencies session_deps_;
  scoped_ptr<OrderedSocketData> data_;
  scoped_refptr<HttpNetworkSession> http_session_;
  scoped_refptr<SpdySession> session_;
  scoped_refptr<TransportSocketParams> transport_params_;
  scoped_ptr<SpdyWebSocketStream> websocket_stream_;
  SpdyStreamId stream_id_;
  SpdyStreamId created_stream_id_;
  scoped_ptr<SpdyFrame> request_frame_;
  scoped_ptr<SpdyFrame> response_frame_;
  scoped_ptr<SpdyFrame> message_frame_;
  scoped_ptr<SpdyFrame> closing_frame_;
  HostPortPair host_port_pair_;
  HostPortProxyPair host_port_proxy_pair_;
  TestCompletionCallback completion_callback_;
  TestCompletionCallback sync_callback_;

  static const char kMessageFrame[];
  static const char kClosingFrame[];
  static const size_t kMessageFrameLength;
  static const size_t kClosingFrameLength;
};

// TODO(toyoshim): Replace old framing data to new one, then use HEADERS and
// data frames.
const char SpdyWebSocketStreamSpdy2Test::kMessageFrame[] = "\x81\x05hello";
const char SpdyWebSocketStreamSpdy2Test::kClosingFrame[] = "\x88\0";
const size_t SpdyWebSocketStreamSpdy2Test::kMessageFrameLength =
    arraysize(SpdyWebSocketStreamSpdy2Test::kMessageFrame) - 1;
const size_t SpdyWebSocketStreamSpdy2Test::kClosingFrameLength =
    arraysize(SpdyWebSocketStreamSpdy2Test::kClosingFrame) - 1;

TEST_F(SpdyWebSocketStreamSpdy2Test, Basic) {
  Prepare(1);
  MockWrite writes[] = {
    CreateMockWrite(*request_frame_.get(), 1),
    CreateMockWrite(*message_frame_.get(), 3),
    CreateMockWrite(*closing_frame_.get(), 5)
  };

  MockRead reads[] = {
    CreateMockRead(*response_frame_.get(), 2),
    CreateMockRead(*message_frame_.get(), 4),
    // Skip sequence 6 to notify closing has been sent.
    CreateMockRead(*closing_frame_.get(), 7),
    MockRead(SYNCHRONOUS, 0, 8)  // EOF cause OnCloseSpdyStream event.
  };

  EXPECT_EQ(OK, InitSession(reads, arraysize(reads),
                            writes, arraysize(writes), false));

  SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
  delegate.SetOnReceivedHeader(
      base::Bind(&SpdyWebSocketStreamSpdy2Test::DoSendHelloFrame,
                 base::Unretained(this)));
  delegate.SetOnReceivedData(
      base::Bind(&SpdyWebSocketStreamSpdy2Test::DoSendClosingFrame,
                 base::Unretained(this)));

  websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));

  BoundNetLog net_log;
  GURL url("ws://example.com/echo");
  ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));

  ASSERT_TRUE(websocket_stream_->stream_);

  SendRequest();

  completion_callback_.WaitForResult();

  EXPECT_EQ(stream_id_, created_stream_id_);

  websocket_stream_.reset();

  const std::vector<SpdyWebSocketStreamEvent>& events =
      delegate.GetSeenEvents();
  ASSERT_EQ(7U, events.size());

  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
            events[0].event_type);
  EXPECT_LT(0, events[0].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
            events[1].event_type);
  EXPECT_EQ(OK, events[1].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
            events[2].event_type);
  EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[2].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
            events[3].event_type);
  EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
            events[4].event_type);
  EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[4].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
            events[5].event_type);
  EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[5].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE,
            events[6].event_type);
  EXPECT_EQ(OK, events[6].result);

  // EOF close SPDY session.
  EXPECT_TRUE(!http_session_->spdy_session_pool()->HasSession(
      host_port_proxy_pair_));
  EXPECT_TRUE(data()->at_read_eof());
  EXPECT_TRUE(data()->at_write_eof());
}

TEST_F(SpdyWebSocketStreamSpdy2Test, DestructionBeforeClose) {
  Prepare(1);
  MockWrite writes[] = {
    CreateMockWrite(*request_frame_.get(), 1),
    CreateMockWrite(*message_frame_.get(), 3)
  };

  MockRead reads[] = {
    CreateMockRead(*response_frame_.get(), 2),
    CreateMockRead(*message_frame_.get(), 4),
    MockRead(ASYNC, ERR_IO_PENDING, 5)
  };

  EXPECT_EQ(OK, InitSession(reads, arraysize(reads),
                            writes, arraysize(writes), false));

  SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
  delegate.SetOnReceivedHeader(
      base::Bind(&SpdyWebSocketStreamSpdy2Test::DoSendHelloFrame,
                 base::Unretained(this)));
  delegate.SetOnReceivedData(
      base::Bind(&SpdyWebSocketStreamSpdy2Test::DoSync,
                 base::Unretained(this)));

  websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));

  BoundNetLog net_log;
  GURL url("ws://example.com/echo");
  ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));

  SendRequest();

  sync_callback_.WaitForResult();

  // WebSocketStream destruction remove its SPDY stream from the session.
  EXPECT_TRUE(session_->IsStreamActive(stream_id_));
  websocket_stream_.reset();
  EXPECT_FALSE(session_->IsStreamActive(stream_id_));

  const std::vector<SpdyWebSocketStreamEvent>& events =
      delegate.GetSeenEvents();
  ASSERT_GE(4U, events.size());

  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
            events[0].event_type);
  EXPECT_LT(0, events[0].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
            events[1].event_type);
  EXPECT_EQ(OK, events[1].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
            events[2].event_type);
  EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[2].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
            events[3].event_type);
  EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);

  EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(
      host_port_proxy_pair_));
  EXPECT_TRUE(data()->at_read_eof());
  EXPECT_TRUE(data()->at_write_eof());
}

TEST_F(SpdyWebSocketStreamSpdy2Test, DestructionAfterExplicitClose) {
  Prepare(1);
  MockWrite writes[] = {
    CreateMockWrite(*request_frame_.get(), 1),
    CreateMockWrite(*message_frame_.get(), 3),
    CreateMockWrite(*closing_frame_.get(), 5)
  };

  MockRead reads[] = {
    CreateMockRead(*response_frame_.get(), 2),
    CreateMockRead(*message_frame_.get(), 4),
    MockRead(ASYNC, ERR_IO_PENDING, 6)
  };

  EXPECT_EQ(OK, InitSession(reads, arraysize(reads),
                            writes, arraysize(writes), false));

  SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
  delegate.SetOnReceivedHeader(
      base::Bind(&SpdyWebSocketStreamSpdy2Test::DoSendHelloFrame,
                 base::Unretained(this)));
  delegate.SetOnReceivedData(
      base::Bind(&SpdyWebSocketStreamSpdy2Test::DoClose,
                 base::Unretained(this)));

  websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));

  BoundNetLog net_log;
  GURL url("ws://example.com/echo");
  ASSERT_EQ(OK, websocket_stream_->InitializeStream(url, HIGHEST, net_log));

  SendRequest();

  completion_callback_.WaitForResult();

  // SPDY stream has already been removed from the session by Close().
  EXPECT_FALSE(session_->IsStreamActive(stream_id_));
  websocket_stream_.reset();

  const std::vector<SpdyWebSocketStreamEvent>& events =
      delegate.GetSeenEvents();
  ASSERT_EQ(5U, events.size());

  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
            events[0].event_type);
  EXPECT_LT(0, events[0].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
            events[1].event_type);
  EXPECT_EQ(OK, events[1].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
            events[2].event_type);
  EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[2].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
            events[3].event_type);
  EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE, events[4].event_type);

  EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(
      host_port_proxy_pair_));
}

TEST_F(SpdyWebSocketStreamSpdy2Test, IOPending) {
  Prepare(1);
  scoped_ptr<SpdyFrame> settings_frame(
      ConstructSpdySettings(spdy_settings_to_send_));
  MockWrite writes[] = {
    // Setting throttling make SpdySession send settings frame automatically.
    CreateMockWrite(*settings_frame.get(), 1),
    CreateMockWrite(*request_frame_.get(), 3),
    CreateMockWrite(*message_frame_.get(), 6),
    CreateMockWrite(*closing_frame_.get(), 9)
  };

  MockRead reads[] = {
    CreateMockRead(*settings_frame.get(), 2),
    CreateMockRead(*response_frame_.get(), 4),
    // Skip sequence 5 (I/O Pending)
    CreateMockRead(*message_frame_.get(), 7),
    // Skip sequence 8 (I/O Pending)
    CreateMockRead(*closing_frame_.get(), 10),
    MockRead(SYNCHRONOUS, 0, 11)  // EOF cause OnCloseSpdyStream event.
  };

  EXPECT_EQ(OK, InitSession(reads, arraysize(reads),
                            writes, arraysize(writes), true));

  // Create a dummy WebSocketStream which cause ERR_IO_PENDING to another
  // WebSocketStream under test.
  SpdyWebSocketStreamEventRecorder block_delegate((CompletionCallback()));

  scoped_ptr<SpdyWebSocketStream> block_stream(
      new SpdyWebSocketStream(session_, &block_delegate));
  BoundNetLog block_net_log;
  GURL block_url("ws://example.com/block");
  ASSERT_EQ(OK,
            block_stream->InitializeStream(block_url, HIGHEST, block_net_log));

  // Create a WebSocketStream under test.
  SpdyWebSocketStreamEventRecorder delegate(completion_callback_.callback());
  delegate.SetOnCreated(
      base::Bind(&SpdyWebSocketStreamSpdy2Test::DoSync,
                 base::Unretained(this)));
  delegate.SetOnReceivedHeader(
      base::Bind(&SpdyWebSocketStreamSpdy2Test::DoSendHelloFrame,
                 base::Unretained(this)));
  delegate.SetOnReceivedData(
      base::Bind(&SpdyWebSocketStreamSpdy2Test::DoSendClosingFrame,
                 base::Unretained(this)));

  websocket_stream_.reset(new SpdyWebSocketStream(session_, &delegate));
  BoundNetLog net_log;
  GURL url("ws://example.com/echo");
  ASSERT_EQ(ERR_IO_PENDING, websocket_stream_->InitializeStream(
      url, HIGHEST, net_log));

  // Delete the fist stream to allow create the second stream.
  block_stream.reset();
  ASSERT_EQ(OK, sync_callback_.WaitForResult());

  SendRequest();

  completion_callback_.WaitForResult();

  websocket_stream_.reset();

  const std::vector<SpdyWebSocketStreamEvent>& block_events =
      block_delegate.GetSeenEvents();
  ASSERT_EQ(0U, block_events.size());

  const std::vector<SpdyWebSocketStreamEvent>& events =
      delegate.GetSeenEvents();
  ASSERT_EQ(8U, events.size());
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CREATED,
            events[0].event_type);
  EXPECT_EQ(0, events[0].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_HEADERS,
            events[1].event_type);
  EXPECT_LT(0, events[1].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_HEADER,
            events[2].event_type);
  EXPECT_EQ(OK, events[2].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
            events[3].event_type);
  EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[3].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
            events[4].event_type);
  EXPECT_EQ(static_cast<int>(kMessageFrameLength), events[4].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_SENT_DATA,
            events[5].event_type);
  EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[5].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_RECEIVED_DATA,
            events[6].event_type);
  EXPECT_EQ(static_cast<int>(kClosingFrameLength), events[6].result);
  EXPECT_EQ(SpdyWebSocketStreamEvent::EVENT_CLOSE,
            events[7].event_type);
  EXPECT_EQ(OK, events[7].result);

  // EOF close SPDY session.
  EXPECT_TRUE(!http_session_->spdy_session_pool()->HasSession(
      host_port_proxy_pair_));
  EXPECT_TRUE(data()->at_read_eof());
  EXPECT_TRUE(data()->at_write_eof());
}

}  // namespace net
