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 "net/socket_stream/socket_stream.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/auth.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log_unittest.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/test_completion_callback.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/dns/mock_host_resolver.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_session.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_service.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/socket_test_util.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_test_util.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/platform_test.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace net {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SocketStreamEvent {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum EventType {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EVENT_START_OPEN_CONNECTION, EVENT_CONNECTED, EVENT_SENT_DATA,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EVENT_RECEIVED_DATA, EVENT_CLOSE, EVENT_AUTH_REQUIRED, EVENT_ERROR,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SocketStreamEvent(EventType type,
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    SocketStream* socket_stream,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    int num,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& str,
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    AuthChallengeInfo* auth_challenge_info,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    int error)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : event_type(type), socket(socket_stream), number(num), data(str),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        auth_info(auth_challenge_info), error_code(error) {}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventType event_type;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SocketStream* socket;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int number;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<AuthChallengeInfo> auth_info;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error_code;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SocketStreamEventRecorder : public SocketStream::Delegate {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // |callback| will be run when the OnClose() or OnError() method is called.
567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // For OnClose(), |callback| is called with OK. For OnError(), it's called
577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // with the error code.
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit SocketStreamEventRecorder(const CompletionCallback& callback)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : callback_(callback) {}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SocketStreamEventRecorder() {}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnStartOpenConnection(
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Callback<int(SocketStreamEvent*)>& callback) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_start_open_connection_ = callback;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnConnected(
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Callback<void(SocketStreamEvent*)>& callback) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_connected_ = callback;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnSentData(
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Callback<void(SocketStreamEvent*)>& callback) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_sent_data_ = callback;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnReceivedData(
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Callback<void(SocketStreamEvent*)>& callback) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_received_data_ = callback;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnClose(const base::Callback<void(SocketStreamEvent*)>& callback) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_close_ = callback;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnAuthRequired(
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Callback<void(SocketStreamEvent*)>& callback) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_auth_required_ = callback;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnError(const base::Callback<void(SocketStreamEvent*)>& callback) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_error_ = callback;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int OnStartOpenConnection(
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SocketStream* socket,
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const CompletionCallback& callback) OVERRIDE {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connection_callback_ = callback;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamEvent(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          socket, 0, std::string(), NULL, OK));
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_start_open_connection_.is_null())
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return on_start_open_connection_.Run(&events_.back());
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return OK;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnConnected(SocketStream* socket,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int num_pending_send_allowed) OVERRIDE {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamEvent(SocketStreamEvent::EVENT_CONNECTED,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          socket, num_pending_send_allowed, std::string(),
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          NULL, OK));
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_connected_.is_null())
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_connected_.Run(&events_.back());
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnSentData(SocketStream* socket,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          int amount_sent) OVERRIDE {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamEvent(SocketStreamEvent::EVENT_SENT_DATA, socket,
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          amount_sent, std::string(), NULL, OK));
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_sent_data_.is_null())
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_sent_data_.Run(&events_.back());
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnReceivedData(SocketStream* socket,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const char* data, int len) OVERRIDE {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamEvent(SocketStreamEvent::EVENT_RECEIVED_DATA, socket, len,
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          std::string(data, len), NULL, OK));
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_received_data_.is_null())
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_received_data_.Run(&events_.back());
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnClose(SocketStream* socket) OVERRIDE {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamEvent(SocketStreamEvent::EVENT_CLOSE, socket, 0,
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          std::string(), NULL, OK));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_close_.is_null())
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_close_.Run(&events_.back());
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback_.is_null())
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback_.Run(OK);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAuthRequired(SocketStream* socket,
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              AuthChallengeInfo* auth_info) OVERRIDE {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamEvent(SocketStreamEvent::EVENT_AUTH_REQUIRED, socket, 0,
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          std::string(), auth_info, OK));
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_auth_required_.is_null())
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_auth_required_.Run(&events_.back());
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnError(const SocketStream* socket, int error) OVERRIDE {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamEvent(SocketStreamEvent::EVENT_ERROR, NULL, 0,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          std::string(), NULL, error));
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_error_.is_null())
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_error_.Run(&events_.back());
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback_.is_null())
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_.Run(error);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoClose(SocketStreamEvent* event) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->socket->Close();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoRestartWithAuth(SocketStreamEvent* event) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "RestartWithAuth username=" << credentials_.username()
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << " password=" << credentials_.password();
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->socket->RestartWithAuth(credentials_);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetAuthInfo(const AuthCredentials& credentials) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    credentials_ = credentials;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Wakes up the SocketStream waiting for completion of OnStartOpenConnection()
1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // of its delegate.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CompleteConnection(int result) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connection_callback_.Run(result);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& GetSeenEvents() const {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return events_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SocketStreamEvent> events_;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Callback<int(SocketStreamEvent*)> on_start_open_connection_;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Callback<void(SocketStreamEvent*)> on_connected_;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Callback<void(SocketStreamEvent*)> on_sent_data_;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Callback<void(SocketStreamEvent*)> on_received_data_;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Callback<void(SocketStreamEvent*)> on_close_;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Callback<void(SocketStreamEvent*)> on_auth_required_;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Callback<void(SocketStreamEvent*)> on_error_;
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const CompletionCallback callback_;
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CompletionCallback connection_callback_;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AuthCredentials credentials_;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SocketStreamEventRecorder);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// This is used for the test OnErrorDetachDelegate.
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class SelfDeletingDelegate : public SocketStream::Delegate {
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // |callback| must cause the test message loop to exit when called.
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  explicit SelfDeletingDelegate(const CompletionCallback& callback)
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      : socket_stream_(), callback_(callback) {}
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~SelfDeletingDelegate() {}
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Call DetachDelegate(), delete |this|, then run the callback.
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void OnError(const SocketStream* socket, int error) OVERRIDE {
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // callback_ will be deleted when we delete |this|, so copy it to call it
20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // afterwards.
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CompletionCallback callback = callback_;
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    socket_stream_->DetachDelegate();
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    delete this;
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(OK);
20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // This can't be passed in the constructor because this object needs to be
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // created before SocketStream.
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void set_socket_stream(const scoped_refptr<SocketStream>& socket_stream) {
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    socket_stream_ = socket_stream;
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    EXPECT_EQ(socket_stream_->delegate(), this);
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void OnConnected(SocketStream* socket, int max_pending_send_allowed)
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      OVERRIDE {
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ADD_FAILURE() << "OnConnected() should not be called";
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void OnSentData(SocketStream* socket, int amount_sent) OVERRIDE {
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ADD_FAILURE() << "OnSentData() should not be called";
22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void OnReceivedData(SocketStream* socket, const char* data, int len)
22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      OVERRIDE {
22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ADD_FAILURE() << "OnReceivedData() should not be called";
22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
22690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void OnClose(SocketStream* socket) OVERRIDE {
22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ADD_FAILURE() << "OnClose() should not be called";
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<SocketStream> socket_stream_;
23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const CompletionCallback callback_;
23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SelfDeletingDelegate);
23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestURLRequestContextWithProxy : public TestURLRequestContext {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit TestURLRequestContextWithProxy(const std::string& proxy)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : TestURLRequestContext(true) {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context_storage_.set_proxy_service(ProxyService::CreateFixed(proxy));
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Init();
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TestURLRequestContextWithProxy() {}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestSocketStreamNetworkDelegate : public TestNetworkDelegate {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSocketStreamNetworkDelegate()
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : before_connect_result_(OK) {}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TestSocketStreamNetworkDelegate() {}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int OnBeforeSocketStreamConnect(
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SocketStream* stream,
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const CompletionCallback& callback) OVERRIDE {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return before_connect_result_;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetBeforeConnectResult(int result) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    before_connect_result_ = result;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int before_connect_result_;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SocketStreamTest : public PlatformTest {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SocketStreamTest() {}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_socket_factory_.reset();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handshake_request_ = kWebSocketHandshakeRequest;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handshake_response_ = kWebSocketHandshakeResponse;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_socket_factory_.reset();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetWebSocketHandshakeMessage(
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char* request, const char* response) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handshake_request_ = request;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handshake_response_ = response;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddWebSocketMessage(const std::string& message) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    messages_.push_back(message);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual MockClientSocketFactory* GetMockClientSocketFactory() {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_socket_factory_.reset(new MockClientSocketFactory);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return mock_socket_factory_.get();
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Functions for SocketStreamEventRecorder to handle calls to the
2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // SocketStream::Delegate methods from the SocketStream.
2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DoSendWebSocketHandshake(SocketStreamEvent* event) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->socket->SendData(
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        handshake_request_.data(), handshake_request_.size());
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DoCloseFlushPendingWriteTest(SocketStreamEvent* event) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // handshake response received.
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < messages_.size(); i++) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<char> frame;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame.push_back('\0');
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame.insert(frame.end(), messages_[i].begin(), messages_[i].end());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame.push_back('\xff');
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(event->socket->SendData(&frame[0], frame.size()));
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Actual StreamSocket close must happen after all frames queued by
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SendData above are sent out.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->socket->Close();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual void DoCloseFlushPendingWriteTestWithSetContextNull(
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      SocketStreamEvent* event) {
3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    event->socket->set_context(NULL);
32068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // handshake response received.
32168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    for (size_t i = 0; i < messages_.size(); i++) {
32268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      std::vector<char> frame;
32368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      frame.push_back('\0');
32468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      frame.insert(frame.end(), messages_[i].begin(), messages_[i].end());
32568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      frame.push_back('\xff');
32668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EXPECT_TRUE(event->socket->SendData(&frame[0], frame.size()));
32768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
32868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Actual StreamSocket close must happen after all frames queued by
32968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // SendData above are sent out.
33068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    event->socket->Close();
33168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
33268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void DoFailByTooBigDataAndClose(SocketStreamEvent* event) {
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string frame(event->number + 1, 0x00);
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VLOG(1) << event->number;
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_FALSE(event->socket->SendData(&frame[0], frame.size()));
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    event->socket->Close();
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int DoSwitchToSpdyTest(SocketStreamEvent* event) {
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ERR_PROTOCOL_SWITCHED;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Notifies |io_test_callback_| of that this method is called, and keeps the
3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // SocketStream waiting.
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int DoIOPending(SocketStreamEvent* event) {
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    io_test_callback_.callback().Run(OK);
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ERR_IO_PENDING;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kWebSocketHandshakeRequest[];
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kWebSocketHandshakeResponse[];
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback io_test_callback_;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string handshake_request_;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string handshake_response_;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> messages_;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MockClientSocketFactory> mock_socket_factory_;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char SocketStreamTest::kWebSocketHandshakeRequest[] =
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "GET /demo HTTP/1.1\r\n"
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Host: example.com\r\n"
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Connection: Upgrade\r\n"
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Protocol: sample\r\n"
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Upgrade: WebSocket\r\n"
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Origin: http://example.com\r\n"
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\r\n"
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "^n:ds[4U";
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char SocketStreamTest::kWebSocketHandshakeResponse[] =
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Upgrade: WebSocket\r\n"
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Connection: Upgrade\r\n"
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Origin: http://example.com\r\n"
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Location: ws://example.com/demo\r\n"
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Protocol: sample\r\n"
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\r\n"
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "8jKS'y:G*Co,Wxa-";
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, CloseFlushPendingWrite) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnConnected(base::Bind(
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this)));
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnReceivedData(base::Bind(
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SocketStreamTest::DoCloseFlushPendingWriteTest,
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Unretained(this)));
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContext context;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes[] = {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(SocketStreamTest::kWebSocketHandshakeRequest),
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, "\0message1\xff", 10),
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, "\0message2\xff", 10)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads[] = {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SocketStreamTest::kWebSocketHandshakeResponse),
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Server doesn't close the connection after handshake.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddWebSocketMessage("message1");
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddWebSocketMessage("message2");
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data_provider(
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1, data_reads, arraysize(data_reads),
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_writes, arraysize(data_writes));
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockClientSocketFactory* mock_socket_factory =
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetMockClientSocketFactory();
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory->AddSocketDataProvider(&data_provider);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->SetClientSocketFactory(mock_socket_factory);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_callback.WaitForResult();
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(data_provider.at_read_eof());
4334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(data_provider.at_write_eof());
4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(7U, events.size());
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[2].event_type);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[4].event_type);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[5].event_type);
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[6].event_type);
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_F(SocketStreamTest, ResolveFailure) {
449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TestCompletionCallback test_callback;
450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Make resolver fail.
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TestURLRequestContext context;
459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<MockHostResolver> mock_host_resolver(
460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new MockHostResolver());
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  mock_host_resolver->rules()->AddSimulatedFailure("example.com");
462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  context.set_host_resolver(mock_host_resolver.get());
463868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  socket_stream->set_context(&context);
464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // No read/write on socket is expected.
466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StaticSocketDataProvider data_provider(NULL, 0, NULL, 0);
467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  MockClientSocketFactory* mock_socket_factory =
468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      GetMockClientSocketFactory();
469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  mock_socket_factory->AddSocketDataProvider(&data_provider);
470868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  socket_stream->SetClientSocketFactory(mock_socket_factory);
471868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  socket_stream->Connect();
473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
474868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  test_callback.WaitForResult();
475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_EQ(2U, events.size());
478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[0].event_type);
480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[1].event_type);
481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(SocketStreamTest, ExceedMaxPendingSendAllowed) {
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback test_callback;
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  delegate->SetOnConnected(base::Bind(
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &SocketStreamTest::DoFailByTooBigDataAndClose, base::Unretained(this)));
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestURLRequestContext context;
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  socket_stream->set_context(&context);
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DelayedSocketData data_provider(1, NULL, 0, NULL, 0);
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockClientSocketFactory* mock_socket_factory =
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetMockClientSocketFactory();
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mock_socket_factory->AddSocketDataProvider(&data_provider);
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  socket_stream->SetClientSocketFactory(mock_socket_factory);
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  socket_stream->Connect();
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  test_callback.WaitForResult();
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(4U, events.size());
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            events[0].event_type);
515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[2].event_type);
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, BasicAuthProxy) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockClientSocketFactory mock_socket_factory;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes1[] = {
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Host: example.com\r\n"
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Connection: keep-alive\r\n\r\n"),
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads1[] = {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("\r\n"),
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 data_writes1, arraysize(data_writes1));
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSocketDataProvider(&data1);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes2[] = {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Host: example.com\r\n"
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Connection: keep-alive\r\n"
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads2[] = {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("HTTP/1.1 200 Connection Established\r\n"),
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("Proxy-agent: Apache/2.2.8\r\n"),
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("\r\n"),
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SocketStream::DoClose is run asynchronously.  Socket can be read after
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "\r\n".  We have to give ERR_IO_PENDING to SocketStream then to indicate
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // server doesn't close the connection.
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 data_writes2, arraysize(data_writes2));
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSocketDataProvider(&data2);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose,
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      base::Unretained(delegate.get())));
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delegate->SetAuthInfo(AuthCredentials(ASCIIToUTF16("foo"),
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        ASCIIToUTF16("bar")));
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnAuthRequired(base::Bind(
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SocketStreamEventRecorder::DoRestartWithAuth,
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Unretained(delegate.get())));
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContextWithProxy context("myproxy:70");
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->SetClientSocketFactory(&mock_socket_factory);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_callback.WaitForResult();
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(5U, events.size());
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_AUTH_REQUIRED, events[1].event_type);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[2].event_type);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[3].event_type);
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_ABORTED, events[3].error_code);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[4].event_type);
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(eroman): Add back NetLogTest here...
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, BasicAuthProxyWithAuthCache) {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockClientSocketFactory mock_socket_factory;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes[] = {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // WebSocket(SocketStream) always uses CONNECT when it is configured to use
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // proxy so the port may not be 443.
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Host: example.com\r\n"
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Connection: keep-alive\r\n"
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads[] = {
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("HTTP/1.1 200 Connection Established\r\n"),
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("Proxy-agent: Apache/2.2.8\r\n"),
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("\r\n"),
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 data_writes, arraysize(data_writes));
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSocketDataProvider(&data);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose,
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      base::Unretained(delegate.get())));
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContextWithProxy context("myproxy:70");
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpAuthCache* auth_cache =
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context.http_transaction_factory()->GetSession()->http_auth_cache();
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_cache->Add(GURL("http://myproxy:70"),
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "MyRealm1",
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  HttpAuth::AUTH_SCHEME_BASIC,
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "Basic realm=MyRealm1",
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  AuthCredentials(ASCIIToUTF16("foo"),
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  ASCIIToUTF16("bar")),
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "/");
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->SetClientSocketFactory(&mock_socket_factory);
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_callback.WaitForResult();
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(4U, events.size());
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_ABORTED, events[2].error_code);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type);
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, WSSBasicAuthProxyWithAuthCache) {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockClientSocketFactory mock_socket_factory;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes1[] = {
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite("CONNECT example.com:443 HTTP/1.1\r\n"
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Host: example.com\r\n"
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Connection: keep-alive\r\n"
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads1[] = {
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("HTTP/1.1 200 Connection Established\r\n"),
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("Proxy-agent: Apache/2.2.8\r\n"),
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("\r\n"),
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 data_writes1, arraysize(data_writes1));
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSocketDataProvider(&data1);
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider data2(ASYNC, OK);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSSLSocketDataProvider(&data2);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose,
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      base::Unretained(delegate.get())));
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("wss://example.com/demo"), delegate.get()));
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContextWithProxy context("myproxy:70");
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpAuthCache* auth_cache =
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context.http_transaction_factory()->GetSession()->http_auth_cache();
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_cache->Add(GURL("http://myproxy:70"),
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "MyRealm1",
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  HttpAuth::AUTH_SCHEME_BASIC,
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "Basic realm=MyRealm1",
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  AuthCredentials(ASCIIToUTF16("foo"),
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  ASCIIToUTF16("bar")),
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "/");
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->SetClientSocketFactory(&mock_socket_factory);
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_callback.WaitForResult();
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(4U, events.size());
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_ABORTED, events[2].error_code);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type);
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, IOPending) {
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
7114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  delegate->SetOnStartOpenConnection(base::Bind(
7124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      &SocketStreamTest::DoIOPending, base::Unretained(this)));
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnConnected(base::Bind(
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this)));
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnReceivedData(base::Bind(
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SocketStreamTest::DoCloseFlushPendingWriteTest,
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Unretained(this)));
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContext context;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes[] = {
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(SocketStreamTest::kWebSocketHandshakeRequest),
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, "\0message1\xff", 10),
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, "\0message2\xff", 10)
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads[] = {
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SocketStreamTest::kWebSocketHandshakeResponse),
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Server doesn't close the connection after handshake.
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddWebSocketMessage("message1");
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddWebSocketMessage("message2");
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data_provider(
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1, data_reads, arraysize(data_reads),
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_writes, arraysize(data_writes));
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockClientSocketFactory* mock_socket_factory =
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetMockClientSocketFactory();
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory->AddSocketDataProvider(&data_provider);
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->SetClientSocketFactory(mock_socket_factory);
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_test_callback_.WaitForResult();
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SocketStream::STATE_RESOLVE_PROTOCOL_COMPLETE,
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            socket_stream->next_state_);
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delegate->CompleteConnection(OK);
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, test_callback.WaitForResult());
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(data_provider.at_read_eof());
7584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(data_provider.at_write_eof());
7594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
761c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(7U, events.size());
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[2].event_type);
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type);
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[4].event_type);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[5].event_type);
770c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[6].event_type);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, SwitchToSpdy) {
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnStartOpenConnection(base::Bind(
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SocketStreamTest::DoSwitchToSpdyTest, base::Unretained(this)));
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContext context;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_PROTOCOL_SWITCHED, test_callback.WaitForResult());
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2U, events.size());
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[1].event_type);
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_PROTOCOL_SWITCHED, events[1].error_code);
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, SwitchAfterPending) {
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnStartOpenConnection(base::Bind(
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SocketStreamTest::DoIOPending, base::Unretained(this)));
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContext context;
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_test_callback_.WaitForResult();
8184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SocketStream::STATE_RESOLVE_PROTOCOL_COMPLETE,
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            socket_stream->next_state_);
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delegate->CompleteConnection(ERR_PROTOCOL_SWITCHED);
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_PROTOCOL_SWITCHED, test_callback.WaitForResult());
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2U, events.size());
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[1].event_type);
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_PROTOCOL_SWITCHED, events[1].error_code);
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test a connection though a secure proxy.
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, SecureProxyConnectError) {
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockClientSocketFactory mock_socket_factory;
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes[] = {
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Host: example.com\r\n"
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Connection: keep-alive\r\n\r\n")
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads[] = {
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("HTTP/1.1 200 Connection Established\r\n"),
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("Proxy-agent: Apache/2.2.8\r\n"),
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("\r\n"),
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SocketStream::DoClose is run asynchronously.  Socket can be read after
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "\r\n".  We have to give ERR_IO_PENDING to SocketStream then to indicate
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // server doesn't close the connection.
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING)
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                data_writes, arraysize(data_writes));
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSocketDataProvider(&data);
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSSLSocketDataProvider(&ssl);
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContextWithProxy context("https://myproxy:70");
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose,
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      base::Unretained(delegate.get())));
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->SetClientSocketFactory(&mock_socket_factory);
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_callback.WaitForResult();
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(3U, events.size());
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[1].event_type);
8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, events[1].error_code);
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[2].event_type);
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test a connection though a secure proxy.
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, SecureProxyConnect) {
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockClientSocketFactory mock_socket_factory;
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes[] = {
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Host: example.com\r\n"
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Connection: keep-alive\r\n\r\n")
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads[] = {
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("HTTP/1.1 200 Connection Established\r\n"),
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("Proxy-agent: Apache/2.2.8\r\n"),
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("\r\n"),
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SocketStream::DoClose is run asynchronously.  Socket can be read after
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "\r\n".  We have to give ERR_IO_PENDING to SocketStream then to indicate
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // server doesn't close the connection.
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING)
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                data_writes, arraysize(data_writes));
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSocketDataProvider(&data);
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSSLSocketDataProvider(&ssl);
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContextWithProxy context("https://myproxy:70");
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose,
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      base::Unretained(delegate.get())));
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->SetClientSocketFactory(&mock_socket_factory);
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_callback.WaitForResult();
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(4U, events.size());
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[2].event_type);
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_ABORTED, events[2].error_code);
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type);
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, BeforeConnectFailed) {
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContext context;
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSocketStreamNetworkDelegate network_delegate;
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  network_delegate.SetBeforeConnectResult(ERR_ACCESS_DENIED);
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context.set_network_delegate(&network_delegate);
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_callback.WaitForResult();
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2U, events.size());
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[0].event_type);
9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_ACCESS_DENIED, events[0].error_code);
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[1].event_type);
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
96590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Check that a connect failure, followed by the delegate calling DetachDelegate
96690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// and deleting itself in the OnError callback, is handled correctly.
96790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(SocketStreamTest, OnErrorDetachDelegate) {
96890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MockClientSocketFactory mock_socket_factory;
96990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  TestCompletionCallback test_callback;
97090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
97190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // SelfDeletingDelegate is self-owning; we just need a pointer to it to
97290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // connect it and the SocketStream.
97390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SelfDeletingDelegate* delegate =
97490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      new SelfDeletingDelegate(test_callback.callback());
97590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
97690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StaticSocketDataProvider data;
97790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.set_connect_data(mock_connect);
97890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  mock_socket_factory.AddSocketDataProvider(&data);
97990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
98090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  TestURLRequestContext context;
98190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
98290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      new SocketStream(GURL("ws://localhost:9998/echo"), delegate));
98390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  socket_stream->set_context(&context);
98490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  socket_stream->SetClientSocketFactory(&mock_socket_factory);
98590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  delegate->set_socket_stream(socket_stream);
98690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The delegate pointer will become invalid during the test. Set it to NULL to
98790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // avoid holding a dangling pointer.
98890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  delegate = NULL;
98990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
99090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  socket_stream->Connect();
99190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
99290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(OK, test_callback.WaitForResult());
99390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
99490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
99568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)TEST_F(SocketStreamTest, NullContextSocketStreamShouldNotCrash) {
99668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  TestCompletionCallback test_callback;
99768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
99868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
99968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
100068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  TestURLRequestContext context;
100168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
100268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
10034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  delegate->SetOnStartOpenConnection(base::Bind(
10044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      &SocketStreamTest::DoIOPending, base::Unretained(this)));
100568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  delegate->SetOnConnected(base::Bind(
100668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      &SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this)));
100768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  delegate->SetOnReceivedData(base::Bind(
100868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      &SocketStreamTest::DoCloseFlushPendingWriteTestWithSetContextNull,
10094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::Unretained(this)));
101068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
101168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  socket_stream->set_context(&context);
101268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
101368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  MockWrite data_writes[] = {
101468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    MockWrite(SocketStreamTest::kWebSocketHandshakeRequest),
101568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  };
101668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  MockRead data_reads[] = {
101768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    MockRead(SocketStreamTest::kWebSocketHandshakeResponse),
101868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  };
101968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  AddWebSocketMessage("message1");
102068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  AddWebSocketMessage("message2");
102168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
102268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DelayedSocketData data_provider(
102368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      1, data_reads, arraysize(data_reads),
102468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      data_writes, arraysize(data_writes));
102568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
102668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  MockClientSocketFactory* mock_socket_factory = GetMockClientSocketFactory();
102768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  mock_socket_factory->AddSocketDataProvider(&data_provider);
102868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  socket_stream->SetClientSocketFactory(mock_socket_factory);
102968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
103068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  socket_stream->Connect();
103168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  io_test_callback_.WaitForResult();
103268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  delegate->CompleteConnection(OK);
103368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_EQ(OK, test_callback.WaitForResult());
10344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(data_provider.at_read_eof());
10364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_TRUE(data_provider.at_write_eof());
10374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
10394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(5U, events.size());
10404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
10424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            events[0].event_type);
10434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
10444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[2].event_type);
10454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type);
10464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[4].event_type);
104768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
104868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1050