socket_stream_unittest.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/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:
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit SocketStreamEventRecorder(const CompletionCallback& callback)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : callback_(callback) {}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SocketStreamEventRecorder() {}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnStartOpenConnection(
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Callback<int(SocketStreamEvent*)>& callback) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_start_open_connection_ = callback;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnConnected(
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Callback<void(SocketStreamEvent*)>& callback) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_connected_ = callback;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnSentData(
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Callback<void(SocketStreamEvent*)>& callback) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_sent_data_ = callback;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnReceivedData(
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Callback<void(SocketStreamEvent*)>& callback) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_received_data_ = callback;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnClose(const base::Callback<void(SocketStreamEvent*)>& callback) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_close_ = callback;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnAuthRequired(
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Callback<void(SocketStreamEvent*)>& callback) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_auth_required_ = callback;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnError(const base::Callback<void(SocketStreamEvent*)>& callback) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_error_ = callback;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int OnStartOpenConnection(
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SocketStream* socket,
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const CompletionCallback& callback) OVERRIDE {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connection_callback_ = callback;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamEvent(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          socket, 0, std::string(), NULL, OK));
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_start_open_connection_.is_null())
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return on_start_open_connection_.Run(&events_.back());
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return OK;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnConnected(SocketStream* socket,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int num_pending_send_allowed) OVERRIDE {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamEvent(SocketStreamEvent::EVENT_CONNECTED,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          socket, num_pending_send_allowed, std::string(),
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          NULL, OK));
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_connected_.is_null())
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_connected_.Run(&events_.back());
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnSentData(SocketStream* socket,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          int amount_sent) OVERRIDE {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamEvent(SocketStreamEvent::EVENT_SENT_DATA, socket,
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          amount_sent, std::string(), NULL, OK));
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_sent_data_.is_null())
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_sent_data_.Run(&events_.back());
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnReceivedData(SocketStream* socket,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const char* data, int len) OVERRIDE {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamEvent(SocketStreamEvent::EVENT_RECEIVED_DATA, socket, len,
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          std::string(data, len), NULL, OK));
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_received_data_.is_null())
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_received_data_.Run(&events_.back());
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnClose(SocketStream* socket) OVERRIDE {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamEvent(SocketStreamEvent::EVENT_CLOSE, socket, 0,
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          std::string(), NULL, OK));
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_close_.is_null())
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_close_.Run(&events_.back());
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback_.is_null())
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback_.Run(OK);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnAuthRequired(SocketStream* socket,
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              AuthChallengeInfo* auth_info) OVERRIDE {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamEvent(SocketStreamEvent::EVENT_AUTH_REQUIRED, socket, 0,
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          std::string(), auth_info, OK));
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_auth_required_.is_null())
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_auth_required_.Run(&events_.back());
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnError(const SocketStream* socket, int error) OVERRIDE {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SocketStreamEvent(SocketStreamEvent::EVENT_ERROR, NULL, 0,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          std::string(), NULL, error));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_error_.is_null())
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_error_.Run(&events_.back());
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback_.is_null())
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_.Run(error);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoClose(SocketStreamEvent* event) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->socket->Close();
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoRestartWithAuth(SocketStreamEvent* event) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "RestartWithAuth username=" << credentials_.username()
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << " password=" << credentials_.password();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->socket->RestartWithAuth(credentials_);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetAuthInfo(const AuthCredentials& credentials) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    credentials_ = credentials;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CompleteConnection(int result) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connection_callback_.Run(result);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& GetSeenEvents() const {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return events_;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SocketStreamEvent> events_;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Callback<int(SocketStreamEvent*)> on_start_open_connection_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Callback<void(SocketStreamEvent*)> on_connected_;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Callback<void(SocketStreamEvent*)> on_sent_data_;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Callback<void(SocketStreamEvent*)> on_received_data_;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Callback<void(SocketStreamEvent*)> on_close_;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Callback<void(SocketStreamEvent*)> on_auth_required_;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Callback<void(SocketStreamEvent*)> on_error_;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const CompletionCallback callback_;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CompletionCallback connection_callback_;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AuthCredentials credentials_;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SocketStreamEventRecorder);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// This is used for the test OnErrorDetachDelegate.
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class SelfDeletingDelegate : public SocketStream::Delegate {
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // |callback| must cause the test message loop to exit when called.
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  explicit SelfDeletingDelegate(const CompletionCallback& callback)
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      : socket_stream_(), callback_(callback) {}
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~SelfDeletingDelegate() {}
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Call DetachDelegate(), delete |this|, then run the callback.
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void OnError(const SocketStream* socket, int error) OVERRIDE {
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // callback_ will be deleted when we delete |this|, so copy it to call it
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // afterwards.
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CompletionCallback callback = callback_;
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    socket_stream_->DetachDelegate();
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    delete this;
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback.Run(OK);
20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // This can't be passed in the constructor because this object needs to be
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // created before SocketStream.
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void set_socket_stream(const scoped_refptr<SocketStream>& socket_stream) {
20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    socket_stream_ = socket_stream;
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    EXPECT_EQ(socket_stream_->delegate(), this);
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void OnConnected(SocketStream* socket, int max_pending_send_allowed)
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      OVERRIDE {
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ADD_FAILURE() << "OnConnected() should not be called";
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void OnSentData(SocketStream* socket, int amount_sent) OVERRIDE {
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ADD_FAILURE() << "OnSentData() should not be called";
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void OnReceivedData(SocketStream* socket, const char* data, int len)
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      OVERRIDE {
21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ADD_FAILURE() << "OnReceivedData() should not be called";
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void OnClose(SocketStream* socket) OVERRIDE {
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ADD_FAILURE() << "OnClose() should not be called";
22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
22690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<SocketStream> socket_stream_;
22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const CompletionCallback callback_;
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SelfDeletingDelegate);
23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestURLRequestContextWithProxy : public TestURLRequestContext {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit TestURLRequestContextWithProxy(const std::string& proxy)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : TestURLRequestContext(true) {
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context_storage_.set_proxy_service(ProxyService::CreateFixed(proxy));
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Init();
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TestURLRequestContextWithProxy() {}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestSocketStreamNetworkDelegate : public TestNetworkDelegate {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSocketStreamNetworkDelegate()
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : before_connect_result_(OK) {}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TestSocketStreamNetworkDelegate() {}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int OnBeforeSocketStreamConnect(
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SocketStream* stream,
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const CompletionCallback& callback) OVERRIDE {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return before_connect_result_;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetBeforeConnectResult(int result) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    before_connect_result_ = result;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int before_connect_result_;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SocketStreamTest : public PlatformTest {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SocketStreamTest() {}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_socket_factory_.reset();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handshake_request_ = kWebSocketHandshakeRequest;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handshake_response_ = kWebSocketHandshakeResponse;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_socket_factory_.reset();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetWebSocketHandshakeMessage(
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char* request, const char* response) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handshake_request_ = request;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    handshake_response_ = response;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddWebSocketMessage(const std::string& message) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    messages_.push_back(message);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual MockClientSocketFactory* GetMockClientSocketFactory() {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mock_socket_factory_.reset(new MockClientSocketFactory);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return mock_socket_factory_.get();
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DoSendWebSocketHandshake(SocketStreamEvent* event) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->socket->SendData(
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        handshake_request_.data(), handshake_request_.size());
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DoCloseFlushPendingWriteTest(SocketStreamEvent* event) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // handshake response received.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < messages_.size(); i++) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<char> frame;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame.push_back('\0');
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame.insert(frame.end(), messages_[i].begin(), messages_[i].end());
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame.push_back('\xff');
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(event->socket->SendData(&frame[0], frame.size()));
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Actual StreamSocket close must happen after all frames queued by
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SendData above are sent out.
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->socket->Close();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void DoFailByTooBigDataAndClose(SocketStreamEvent* event) {
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string frame(event->number + 1, 0x00);
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VLOG(1) << event->number;
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_FALSE(event->socket->SendData(&frame[0], frame.size()));
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    event->socket->Close();
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int DoSwitchToSpdyTest(SocketStreamEvent* event) {
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ERR_PROTOCOL_SWITCHED;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int DoIOPending(SocketStreamEvent* event) {
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    io_test_callback_.callback().Run(OK);
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ERR_IO_PENDING;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kWebSocketHandshakeRequest[];
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kWebSocketHandshakeResponse[];
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback io_test_callback_;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string handshake_request_;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string handshake_response_;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> messages_;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MockClientSocketFactory> mock_socket_factory_;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char SocketStreamTest::kWebSocketHandshakeRequest[] =
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "GET /demo HTTP/1.1\r\n"
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Host: example.com\r\n"
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Connection: Upgrade\r\n"
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Protocol: sample\r\n"
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Upgrade: WebSocket\r\n"
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Origin: http://example.com\r\n"
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\r\n"
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "^n:ds[4U";
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char SocketStreamTest::kWebSocketHandshakeResponse[] =
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Upgrade: WebSocket\r\n"
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Connection: Upgrade\r\n"
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Origin: http://example.com\r\n"
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Location: ws://example.com/demo\r\n"
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Protocol: sample\r\n"
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\r\n"
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "8jKS'y:G*Co,Wxa-";
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, CloseFlushPendingWrite) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnConnected(base::Bind(
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this)));
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnReceivedData(base::Bind(
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SocketStreamTest::DoCloseFlushPendingWriteTest,
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Unretained(this)));
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContext context;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes[] = {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(SocketStreamTest::kWebSocketHandshakeRequest),
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, "\0message1\xff", 10),
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, "\0message2\xff", 10)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads[] = {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SocketStreamTest::kWebSocketHandshakeResponse),
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Server doesn't close the connection after handshake.
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddWebSocketMessage("message1");
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddWebSocketMessage("message2");
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data_provider(
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1, data_reads, arraysize(data_reads),
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_writes, arraysize(data_writes));
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockClientSocketFactory* mock_socket_factory =
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetMockClientSocketFactory();
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory->AddSocketDataProvider(&data_provider);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->SetClientSocketFactory(mock_socket_factory);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_callback.WaitForResult();
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(7U, events.size());
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[2].event_type);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[4].event_type);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[5].event_type);
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[6].event_type);
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(SocketStreamTest, ExceedMaxPendingSendAllowed) {
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback test_callback;
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  delegate->SetOnConnected(base::Bind(
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &SocketStreamTest::DoFailByTooBigDataAndClose, base::Unretained(this)));
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestURLRequestContext context;
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  socket_stream->set_context(&context);
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DelayedSocketData data_provider(1, NULL, 0, NULL, 0);
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockClientSocketFactory* mock_socket_factory =
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetMockClientSocketFactory();
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mock_socket_factory->AddSocketDataProvider(&data_provider);
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  socket_stream->SetClientSocketFactory(mock_socket_factory);
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  socket_stream->Connect();
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  test_callback.WaitForResult();
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(4U, events.size());
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            events[0].event_type);
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[2].event_type);
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, BasicAuthProxy) {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockClientSocketFactory mock_socket_factory;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes1[] = {
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Host: example.com\r\n"
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Connection: keep-alive\r\n\r\n"),
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads1[] = {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("\r\n"),
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 data_writes1, arraysize(data_writes1));
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSocketDataProvider(&data1);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes2[] = {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Host: example.com\r\n"
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Connection: keep-alive\r\n"
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads2[] = {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("HTTP/1.1 200 Connection Established\r\n"),
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("Proxy-agent: Apache/2.2.8\r\n"),
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("\r\n"),
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SocketStream::DoClose is run asynchronously.  Socket can be read after
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "\r\n".  We have to give ERR_IO_PENDING to SocketStream then to indicate
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // server doesn't close the connection.
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 data_writes2, arraysize(data_writes2));
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSocketDataProvider(&data2);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      base::Unretained(delegate.get())));
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delegate->SetAuthInfo(AuthCredentials(ASCIIToUTF16("foo"),
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        ASCIIToUTF16("bar")));
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnAuthRequired(base::Bind(
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SocketStreamEventRecorder::DoRestartWithAuth,
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Unretained(delegate.get())));
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContextWithProxy context("myproxy:70");
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->SetClientSocketFactory(&mock_socket_factory);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_callback.WaitForResult();
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(5U, events.size());
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_AUTH_REQUIRED, events[1].event_type);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[2].event_type);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[3].event_type);
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_ABORTED, events[3].error_code);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[4].event_type);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(eroman): Add back NetLogTest here...
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, BasicAuthProxyWithAuthCache) {
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockClientSocketFactory mock_socket_factory;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes[] = {
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // WebSocket(SocketStream) always uses CONNECT when it is configured to use
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // proxy so the port may not be 443.
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Host: example.com\r\n"
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Connection: keep-alive\r\n"
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads[] = {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("HTTP/1.1 200 Connection Established\r\n"),
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("Proxy-agent: Apache/2.2.8\r\n"),
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("\r\n"),
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 data_writes, arraysize(data_writes));
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSocketDataProvider(&data);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose,
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      base::Unretained(delegate.get())));
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContextWithProxy context("myproxy:70");
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpAuthCache* auth_cache =
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context.http_transaction_factory()->GetSession()->http_auth_cache();
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_cache->Add(GURL("http://myproxy:70"),
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "MyRealm1",
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  HttpAuth::AUTH_SCHEME_BASIC,
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "Basic realm=MyRealm1",
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  AuthCredentials(ASCIIToUTF16("foo"),
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  ASCIIToUTF16("bar")),
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "/");
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->SetClientSocketFactory(&mock_socket_factory);
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_callback.WaitForResult();
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(4U, events.size());
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_ABORTED, events[2].error_code);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type);
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, WSSBasicAuthProxyWithAuthCache) {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockClientSocketFactory mock_socket_factory;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes1[] = {
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite("CONNECT example.com:443 HTTP/1.1\r\n"
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Host: example.com\r\n"
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Connection: keep-alive\r\n"
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads1[] = {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("HTTP/1.1 200 Connection Established\r\n"),
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("Proxy-agent: Apache/2.2.8\r\n"),
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("\r\n"),
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 data_writes1, arraysize(data_writes1));
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSocketDataProvider(&data1);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider data2(ASYNC, OK);
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSSLSocketDataProvider(&data2);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose,
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      base::Unretained(delegate.get())));
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("wss://example.com/demo"), delegate.get()));
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContextWithProxy context("myproxy:70");
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpAuthCache* auth_cache =
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context.http_transaction_factory()->GetSession()->http_auth_cache();
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_cache->Add(GURL("http://myproxy:70"),
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "MyRealm1",
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  HttpAuth::AUTH_SCHEME_BASIC,
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "Basic realm=MyRealm1",
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  AuthCredentials(ASCIIToUTF16("foo"),
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  ASCIIToUTF16("bar")),
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "/");
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->SetClientSocketFactory(&mock_socket_factory);
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_callback.WaitForResult();
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(4U, events.size());
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_ABORTED, events[2].error_code);
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type);
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, IOPending) {
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnConnected(base::Bind(
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this)));
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnReceivedData(base::Bind(
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SocketStreamTest::DoCloseFlushPendingWriteTest,
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Unretained(this)));
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnStartOpenConnection(base::Bind(
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SocketStreamTest::DoIOPending, base::Unretained(this)));
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContext context;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes[] = {
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(SocketStreamTest::kWebSocketHandshakeRequest),
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, "\0message1\xff", 10),
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC, "\0message2\xff", 10)
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads[] = {
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SocketStreamTest::kWebSocketHandshakeResponse),
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Server doesn't close the connection after handshake.
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddWebSocketMessage("message1");
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddWebSocketMessage("message2");
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayedSocketData data_provider(
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      1, data_reads, arraysize(data_reads),
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_writes, arraysize(data_writes));
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockClientSocketFactory* mock_socket_factory =
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetMockClientSocketFactory();
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory->AddSocketDataProvider(&data_provider);
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->SetClientSocketFactory(mock_socket_factory);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_test_callback_.WaitForResult();
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(SocketStream::STATE_RESOLVE_PROTOCOL_COMPLETE,
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            socket_stream->next_state_);
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delegate->CompleteConnection(OK);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(OK, test_callback.WaitForResult());
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(7U, events.size());
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[2].event_type);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type);
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[4].event_type);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[5].event_type);
703c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[6].event_type);
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, SwitchToSpdy) {
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnStartOpenConnection(base::Bind(
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SocketStreamTest::DoSwitchToSpdyTest, base::Unretained(this)));
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContext context;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_PROTOCOL_SWITCHED, test_callback.WaitForResult());
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2U, events.size());
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[1].event_type);
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_PROTOCOL_SWITCHED, events[1].error_code);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, SwitchAfterPending) {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnStartOpenConnection(base::Bind(
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SocketStreamTest::DoIOPending, base::Unretained(this)));
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContext context;
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
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(ERR_PROTOCOL_SWITCHED);
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_PROTOCOL_SWITCHED, test_callback.WaitForResult());
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2U, events.size());
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[1].event_type);
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_PROTOCOL_SWITCHED, events[1].error_code);
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test a connection though a secure proxy.
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, SecureProxyConnectError) {
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockClientSocketFactory mock_socket_factory;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes[] = {
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Host: example.com\r\n"
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Connection: keep-alive\r\n\r\n")
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads[] = {
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("HTTP/1.1 200 Connection Established\r\n"),
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("Proxy-agent: Apache/2.2.8\r\n"),
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("\r\n"),
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SocketStream::DoClose is run asynchronously.  Socket can be read after
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "\r\n".  We have to give ERR_IO_PENDING to SocketStream then to indicate
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // server doesn't close the connection.
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                data_writes, arraysize(data_writes));
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSocketDataProvider(&data);
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSSLSocketDataProvider(&ssl);
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContextWithProxy context("https://myproxy:70");
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose,
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      base::Unretained(delegate.get())));
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->SetClientSocketFactory(&mock_socket_factory);
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_callback.WaitForResult();
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(3U, events.size());
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[1].event_type);
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, events[1].error_code);
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[2].event_type);
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test a connection though a secure proxy.
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, SecureProxyConnect) {
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockClientSocketFactory mock_socket_factory;
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes[] = {
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite("CONNECT example.com:80 HTTP/1.1\r\n"
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Host: example.com\r\n"
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              "Proxy-Connection: keep-alive\r\n\r\n")
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads[] = {
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("HTTP/1.1 200 Connection Established\r\n"),
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("Proxy-agent: Apache/2.2.8\r\n"),
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead("\r\n"),
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SocketStream::DoClose is run asynchronously.  Socket can be read after
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "\r\n".  We have to give ERR_IO_PENDING to SocketStream then to indicate
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // server doesn't close the connection.
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC, ERR_IO_PENDING)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                data_writes, arraysize(data_writes));
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSocketDataProvider(&data);
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mock_socket_factory.AddSSLSocketDataProvider(&ssl);
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContextWithProxy context("https://myproxy:70");
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose,
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      base::Unretained(delegate.get())));
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->SetClientSocketFactory(&mock_socket_factory);
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_callback.WaitForResult();
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(4U, events.size());
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            events[0].event_type);
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[2].event_type);
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_ABORTED, events[2].error_code);
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type);
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SocketStreamTest, BeforeConnectFailed) {
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback test_callback;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketStreamEventRecorder> delegate(
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStreamEventRecorder(test_callback.callback()));
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContext context;
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSocketStreamNetworkDelegate network_delegate;
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  network_delegate.SetBeforeConnectResult(ERR_ACCESS_DENIED);
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context.set_network_delegate(&network_delegate);
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->set_context(&context);
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_stream->Connect();
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_callback.WaitForResult();
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2U, events.size());
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[0].event_type);
8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_ACCESS_DENIED, events[0].error_code);
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[1].event_type);
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
89790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Check that a connect failure, followed by the delegate calling DetachDelegate
89890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// and deleting itself in the OnError callback, is handled correctly.
89990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(SocketStreamTest, OnErrorDetachDelegate) {
90090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MockClientSocketFactory mock_socket_factory;
90190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  TestCompletionCallback test_callback;
90290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
90390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // SelfDeletingDelegate is self-owning; we just need a pointer to it to
90490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // connect it and the SocketStream.
90590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SelfDeletingDelegate* delegate =
90690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      new SelfDeletingDelegate(test_callback.callback());
90790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
90890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StaticSocketDataProvider data;
90990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.set_connect_data(mock_connect);
91090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  mock_socket_factory.AddSocketDataProvider(&data);
91190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
91290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  TestURLRequestContext context;
91390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<SocketStream> socket_stream(
91490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      new SocketStream(GURL("ws://localhost:9998/echo"), delegate));
91590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  socket_stream->set_context(&context);
91690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  socket_stream->SetClientSocketFactory(&mock_socket_factory);
91790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  delegate->set_socket_stream(socket_stream);
91890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The delegate pointer will become invalid during the test. Set it to NULL to
91990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // avoid holding a dangling pointer.
92090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  delegate = NULL;
92190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
92290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  socket_stream->Connect();
92390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
92490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(OK, test_callback.WaitForResult());
92590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
92690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
928