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

#include "jingle/glue/network_service_async_socket.h"

#include <stddef.h>

#include <memory>
#include <string>
#include <utility>

#include "base/containers/circular_deque.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_pump_default.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
#include "net/base/address_list.h"
#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/http/transport_security_state.h"
#include "net/log/net_log_source.h"
#include "net/socket/socket_test_util.h"
#include "net/socket/ssl_client_socket.h"
#include "net/ssl/ssl_config_service.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request_test_util.h"
#include "services/network/proxy_resolving_socket_factory_mojo.h"
#include "services/network/public/mojom/proxy_resolving_socket.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/webrtc/rtc_base/ipaddress.h"
#include "third_party/webrtc/rtc_base/socketaddress.h"
#include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h"

namespace jingle_glue {

namespace {

// Data provider that handles reads/writes for NetworkServiceAsyncSocket.
class AsyncSocketDataProvider : public net::SocketDataProvider {
 public:
  AsyncSocketDataProvider() : has_pending_read_(false) {}

  ~AsyncSocketDataProvider() override {
    EXPECT_TRUE(writes_.empty());
    EXPECT_TRUE(reads_.empty());
  }

  // If there's no read, sets the "has pending read" flag.  Otherwise,
  // pops the next read.
  net::MockRead OnRead() override {
    if (reads_.empty()) {
      DCHECK(!has_pending_read_);
      has_pending_read_ = true;
      const net::MockRead pending_read(net::SYNCHRONOUS, net::ERR_IO_PENDING);
      return pending_read;
    }
    net::MockRead mock_read = reads_.front();
    reads_.pop_front();
    return mock_read;
  }

  void CancelPendingRead() override {
    DCHECK(has_pending_read_);
    has_pending_read_ = false;
  }

  // Simply pops the next write and, if applicable, compares it to
  // |data|.
  net::MockWriteResult OnWrite(const std::string& data) override {
    DCHECK(!writes_.empty());
    net::MockWrite mock_write = writes_.front();
    writes_.pop_front();
    if (mock_write.result != net::OK) {
      return net::MockWriteResult(mock_write.mode, mock_write.result);
    }
    std::string expected_data(mock_write.data, mock_write.data_len);
    EXPECT_EQ(expected_data, data);
    if (expected_data != data) {
      return net::MockWriteResult(net::SYNCHRONOUS, net::ERR_UNEXPECTED);
    }
    return net::MockWriteResult(mock_write.mode, data.size());
  }

  // We ignore resets so we can pre-load the socket data provider with
  // read/write events.
  void Reset() override {}

  // If there is a pending read, completes it with the given read.
  // Otherwise, queues up the given read.
  void AddRead(const net::MockRead& mock_read) {
    DCHECK_NE(mock_read.result, net::ERR_IO_PENDING);
    if (has_pending_read_) {
      has_pending_read_ = false;
      socket()->OnReadComplete(mock_read);
      return;
    }
    reads_.push_back(mock_read);
  }

  // Simply queues up the given write.
  void AddWrite(const net::MockWrite& mock_write) {
    writes_.push_back(mock_write);
  }

  bool AllReadDataConsumed() const override { return reads_.empty(); }

  bool AllWriteDataConsumed() const override { return writes_.empty(); }

 private:
  base::circular_deque<net::MockRead> reads_;
  bool has_pending_read_;

  base::circular_deque<net::MockWrite> writes_;

  DISALLOW_COPY_AND_ASSIGN(AsyncSocketDataProvider);
};

class MockProxyResolvingSocket : public network::mojom::ProxyResolvingSocket {
 public:
  enum Event {
    // These names are from the perspective of the client, not the socket.
    kRead,
    kWrite,
    kCloseReadPipe,
    kCloseWritePipe,
    kReadError,
    kReadErrorInvalid,
    kWriteError,
    kWriteErrorInvalid,
    kReadEofError,
    kCloseObserverPipe,
  };

  MockProxyResolvingSocket() {}
  ~MockProxyResolvingSocket() override {}

  void Connect(network::mojom::SocketObserverPtr observer,
               network::mojom::ProxyResolvingSocketFactory::
                   CreateProxyResolvingSocketCallback callback) {
    mojo::DataPipe send_pipe;
    mojo::DataPipe receive_pipe;

    observer_ = std::move(observer);
    receive_pipe_handle_ = std::move(receive_pipe.producer_handle);
    send_pipe_handle_ = std::move(send_pipe.consumer_handle);

    std::move(callback).Run(net::OK, base::nullopt, base::nullopt,
                            std::move(receive_pipe.consumer_handle),
                            std::move(send_pipe.producer_handle));
  }

  void RunEvents(std::vector<Event>&& events);

  // mojom::ProxyResolvingSocket implementation.
  void UpgradeToTLS(
      const net::HostPortPair& host_port_pair,
      const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
      network::mojom::TLSClientSocketRequest request,
      network::mojom::SocketObserverPtr observer,
      network::mojom::ProxyResolvingSocket::UpgradeToTLSCallback callback)
      override {
    NOTREACHED();
  }

 private:
  network::mojom::SocketObserverPtr observer_;
  mojo::ScopedDataPipeProducerHandle receive_pipe_handle_;
  mojo::ScopedDataPipeConsumerHandle send_pipe_handle_;

  DISALLOW_COPY_AND_ASSIGN(MockProxyResolvingSocket);
};

class MockProxyResolvingSocketFactory
    : public network::mojom::ProxyResolvingSocketFactory {
 public:
  explicit MockProxyResolvingSocketFactory() : socket_raw_(nullptr) {}
  ~MockProxyResolvingSocketFactory() override {}

  // mojom::ProxyResolvingSocketFactory implementation.
  void CreateProxyResolvingSocket(
      const GURL& url,
      network::mojom::ProxyResolvingSocketOptionsPtr options,
      const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
      network::mojom::ProxyResolvingSocketRequest request,
      network::mojom::SocketObserverPtr observer,
      CreateProxyResolvingSocketCallback callback) override {
    auto socket = std::make_unique<MockProxyResolvingSocket>();
    socket_raw_ = socket.get();
    proxy_resolving_socket_bindings_.AddBinding(std::move(socket),
                                                std::move(request));
    socket_raw_->Connect(std::move(observer), std::move(callback));
  }

  MockProxyResolvingSocket* socket() { return socket_raw_; }

 private:
  mojo::StrongBindingSet<network::mojom::ProxyResolvingSocket>
      proxy_resolving_socket_bindings_;

  // Owned by |proxy_resolving_socket_bindings_|.
  MockProxyResolvingSocket* socket_raw_;

  DISALLOW_COPY_AND_ASSIGN(MockProxyResolvingSocketFactory);
};

void MockProxyResolvingSocket::RunEvents(std::vector<Event>&& events) {
  for (Event ev : events) {
    switch (ev) {
      case kRead:
        mojo::BlockingCopyFromString("data", receive_pipe_handle_);
        break;
      case kWrite: {
        std::string written;
        while (true) {
          char read_buffer[1024];
          uint32_t read_size = sizeof(read_buffer);
          MojoResult result = send_pipe_handle_->ReadData(
              read_buffer, &read_size, MOJO_READ_DATA_FLAG_NONE);
          if (result != MOJO_RESULT_OK)
            break;
          written.append(read_buffer, read_size);
        }

        EXPECT_EQ("atad", written);
        break;
      }
      case kCloseReadPipe:
        receive_pipe_handle_.reset();
        break;
      case kCloseWritePipe:
        send_pipe_handle_.reset();
        break;
      case kReadError:
        observer_->OnReadError(net::ERR_OUT_OF_MEMORY);
        observer_.FlushForTesting();
        break;
      case kReadErrorInvalid:
        observer_->OnReadError(42);
        observer_.FlushForTesting();
        break;
      case kWriteError:
        observer_->OnWriteError(net::ERR_ACCESS_DENIED);
        observer_.FlushForTesting();
        break;
      case kWriteErrorInvalid:
        observer_->OnWriteError(net::ERR_IO_PENDING);
        observer_.FlushForTesting();
        break;
      case kReadEofError:
        observer_->OnReadError(0);
        observer_.FlushForTesting();
        break;
      case kCloseObserverPipe:
        observer_.reset();
        break;
    }
    // Make sure the event is actually delivered.
    base::RunLoop().RunUntilIdle();
  }
}

class NetworkServiceAsyncSocketTest : public testing::Test,
                                      public sigslot::has_slots<> {
 protected:
  explicit NetworkServiceAsyncSocketTest(bool use_mojo_level_mock = false)
      : ssl_socket_data_provider_(net::ASYNC, net::OK),
        use_mojo_level_mock_(use_mojo_level_mock),
        mock_proxy_resolving_socket_factory_(nullptr),
        addr_("localhost", 35) {
    // GTest death tests by default execute in a fork()ed but not exec()ed
    // process. On macOS, a CoreFoundation-backed MessageLoop will exit with a
    // __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__
    // when called. Use the threadsafe mode to avoid this problem.
    testing::GTEST_FLAG(death_test_style) = "threadsafe";
  }

  ~NetworkServiceAsyncSocketTest() override {}

  void SetUp() override {
    mock_client_socket_factory_ =
        std::make_unique<net::MockClientSocketFactory>();
    mock_client_socket_factory_->set_enable_read_if_ready(true);
    mock_client_socket_factory_->AddSocketDataProvider(
        &async_socket_data_provider_);
    mock_client_socket_factory_->AddSSLSocketDataProvider(
        &ssl_socket_data_provider_);

    test_url_request_context_ =
        std::make_unique<net::TestURLRequestContext>(true /* delay init */);
    test_url_request_context_->set_client_socket_factory(
        mock_client_socket_factory_.get());
    test_url_request_context_->Init();

    if (use_mojo_level_mock_) {
      auto mock_proxy_resolving_socket_factory =
          std::make_unique<MockProxyResolvingSocketFactory>();
      mock_proxy_resolving_socket_factory_ =
          mock_proxy_resolving_socket_factory.get();
      proxy_resolving_socket_factory_ =
          std::move(mock_proxy_resolving_socket_factory);
    } else {
      mock_proxy_resolving_socket_factory_ = nullptr;
      proxy_resolving_socket_factory_ =
          std::make_unique<network::ProxyResolvingSocketFactoryMojo>(
              test_url_request_context_.get());
    }

    ns_async_socket_.reset(new NetworkServiceAsyncSocket(
        base::BindRepeating(
            &NetworkServiceAsyncSocketTest::BindToProxyResolvingSocketFactory,
            base::Unretained(this)),
        false, /* use_fake_tls_handshake */
        14, 20, TRAFFIC_ANNOTATION_FOR_TESTS));

    ns_async_socket_->SignalConnected.connect(
        this, &NetworkServiceAsyncSocketTest::OnConnect);
    ns_async_socket_->SignalSSLConnected.connect(
        this, &NetworkServiceAsyncSocketTest::OnSSLConnect);
    ns_async_socket_->SignalClosed.connect(
        this, &NetworkServiceAsyncSocketTest::OnClose);
    ns_async_socket_->SignalRead.connect(
        this, &NetworkServiceAsyncSocketTest::OnRead);
    ns_async_socket_->SignalError.connect(
        this, &NetworkServiceAsyncSocketTest::OnError);
  }

  void TearDown() override {
    // Run any tasks that we forgot to pump.
    base::RunLoop().RunUntilIdle();
    ExpectClosed();
    ExpectNoSignal();
    ns_async_socket_.reset();
  }

  void BindToProxyResolvingSocketFactory(
      network::mojom::ProxyResolvingSocketFactoryRequest request) {
    proxy_resolving_socket_factory_binding_ = std::make_unique<
        mojo::Binding<network::mojom::ProxyResolvingSocketFactory>>(
        proxy_resolving_socket_factory_.get());
    proxy_resolving_socket_factory_binding_->Bind(std::move(request));
  }

  enum Signal {
    SIGNAL_CONNECT,
    SIGNAL_SSL_CONNECT,
    SIGNAL_CLOSE,
    SIGNAL_READ,
    SIGNAL_ERROR,
  };

  // Helper struct that records the state at the time of a signal.

  struct SignalSocketState {
    SignalSocketState()
        : signal(SIGNAL_ERROR),
          state(NetworkServiceAsyncSocket::STATE_CLOSED),
          error(NetworkServiceAsyncSocket::ERROR_NONE),
          net_error(net::OK) {}

    SignalSocketState(Signal signal,
                      NetworkServiceAsyncSocket::State state,
                      NetworkServiceAsyncSocket::Error error,
                      net::Error net_error)
        : signal(signal), state(state), error(error), net_error(net_error) {}

    bool IsEqual(const SignalSocketState& other) const {
      return (signal == other.signal) && (state == other.state) &&
             (error == other.error) && (net_error == other.net_error);
    }

    static SignalSocketState FromAsyncSocket(Signal signal,
                                             buzz::AsyncSocket* async_socket) {
      return SignalSocketState(
          signal, async_socket->state(), async_socket->error(),
          static_cast<net::Error>(async_socket->GetError()));
    }

    static SignalSocketState NoError(Signal signal,
                                     buzz::AsyncSocket::State state) {
      return SignalSocketState(signal, state, buzz::AsyncSocket::ERROR_NONE,
                               net::OK);
    }

    std::string ToString() const {
      return base::StrCat(
          {"(", base::IntToString(signal), ",", base::IntToString(state), ",",
           base::IntToString(error), ",", base::IntToString(net_error), ")"});
    }

    Signal signal;
    NetworkServiceAsyncSocket::State state;
    NetworkServiceAsyncSocket::Error error;
    net::Error net_error;
  };

  void CaptureSocketState(Signal signal) {
    signal_socket_states_.push_back(
        SignalSocketState::FromAsyncSocket(signal, ns_async_socket_.get()));
  }

  void OnConnect() { CaptureSocketState(SIGNAL_CONNECT); }

  void OnSSLConnect() { CaptureSocketState(SIGNAL_SSL_CONNECT); }

  void OnClose() { CaptureSocketState(SIGNAL_CLOSE); }

  void OnRead() { CaptureSocketState(SIGNAL_READ); }

  void OnError() { ADD_FAILURE(); }

  // State expect functions.

  void ExpectState(NetworkServiceAsyncSocket::State state,
                   NetworkServiceAsyncSocket::Error error,
                   net::Error net_error) {
    EXPECT_EQ(state, ns_async_socket_->state());
    EXPECT_EQ(error, ns_async_socket_->error());
    EXPECT_EQ(net_error, ns_async_socket_->GetError());
  }

  void ExpectNonErrorState(NetworkServiceAsyncSocket::State state) {
    ExpectState(state, NetworkServiceAsyncSocket::ERROR_NONE, net::OK);
  }

  void ExpectErrorState(NetworkServiceAsyncSocket::State state,
                        NetworkServiceAsyncSocket::Error error) {
    ExpectState(state, error, net::OK);
  }

  void ExpectClosed() {
    ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_CLOSED);
  }

  // Signal expect functions.

  void ExpectNoSignal() {
    if (!signal_socket_states_.empty()) {
      ADD_FAILURE() << signal_socket_states_.front().signal;
    }
  }

  void ExpectSignalSocketState(SignalSocketState expected_signal_socket_state) {
    if (signal_socket_states_.empty()) {
      ADD_FAILURE() << expected_signal_socket_state.signal;
      return;
    }
    EXPECT_TRUE(
        expected_signal_socket_state.IsEqual(signal_socket_states_.front()))
        << "Expected signal:" << expected_signal_socket_state.ToString()
        << " actual signal: " << signal_socket_states_.front().ToString();
    signal_socket_states_.pop_front();
  }

  void ExpectReadSignal() {
    ExpectSignalSocketState(SignalSocketState::NoError(
        SIGNAL_READ, NetworkServiceAsyncSocket::STATE_OPEN));
  }

  void ExpectSSLConnectSignal() {
    ExpectSignalSocketState(SignalSocketState::NoError(
        SIGNAL_SSL_CONNECT, NetworkServiceAsyncSocket::STATE_TLS_OPEN));
  }

  void ExpectSSLReadSignal() {
    ExpectSignalSocketState(SignalSocketState::NoError(
        SIGNAL_READ, NetworkServiceAsyncSocket::STATE_TLS_OPEN));
  }

  // Open/close utility functions.

  void DoOpenClosed() {
    ExpectClosed();
    async_socket_data_provider_.set_connect_data(
        net::MockConnect(net::SYNCHRONOUS, net::OK));
    EXPECT_TRUE(ns_async_socket_->Connect(addr_));
    ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_CONNECTING);

    base::RunLoop().RunUntilIdle();
    // We may not necessarily be open; may have been other events
    // queued up.
    ExpectSignalSocketState(SignalSocketState::NoError(
        SIGNAL_CONNECT, NetworkServiceAsyncSocket::STATE_OPEN));
  }

  void DoCloseOpened(SignalSocketState expected_signal_socket_state) {
    // We may be in an error state, so just compare state().
    EXPECT_EQ(NetworkServiceAsyncSocket::STATE_OPEN, ns_async_socket_->state());
    EXPECT_TRUE(ns_async_socket_->Close());
    ExpectSignalSocketState(expected_signal_socket_state);
    ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_CLOSED);
  }

  void DoCloseOpenedNoError() {
    DoCloseOpened(SignalSocketState::NoError(
        SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED));
  }

  void DoSSLOpenClosed() {
    const char kDummyData[] = "dummy_data";
    async_socket_data_provider_.AddRead(net::MockRead(kDummyData));
    DoOpenClosed();
    ExpectReadSignal();
    EXPECT_EQ(kDummyData, DrainRead(1));

    EXPECT_TRUE(ns_async_socket_->StartTls("fakedomain.com"));
    base::RunLoop().RunUntilIdle();
    ExpectSSLConnectSignal();
    ExpectNoSignal();
    ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_TLS_OPEN);
  }

  void DoSSLCloseOpened(SignalSocketState expected_signal_socket_state) {
    // We may be in an error state, so just compare state().
    EXPECT_EQ(NetworkServiceAsyncSocket::STATE_TLS_OPEN,
              ns_async_socket_->state());
    EXPECT_TRUE(ns_async_socket_->Close());
    ExpectSignalSocketState(expected_signal_socket_state);
    ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_CLOSED);
  }

  void DoSSLCloseOpenedNoError() {
    DoSSLCloseOpened(SignalSocketState::NoError(
        SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED));
  }

  // Read utility functions.

  std::string DrainRead(size_t buf_size) {
    std::string read;
    std::unique_ptr<char[]> buf(new char[buf_size]);
    size_t len_read;
    while (true) {
      bool success = ns_async_socket_->Read(buf.get(), buf_size, &len_read);
      if (!success) {
        ADD_FAILURE();
        break;
      }
      if (len_read == 0U) {
        break;
      }
      read.append(buf.get(), len_read);
    }
    return read;
  }

  // Need a message loop for both the socket and Mojo.
  base::MessageLoop message_loop_;

  AsyncSocketDataProvider async_socket_data_provider_;
  net::SSLSocketDataProvider ssl_socket_data_provider_;

  bool use_mojo_level_mock_;

  std::unique_ptr<net::MockClientSocketFactory> mock_client_socket_factory_;
  std::unique_ptr<net::TestURLRequestContext> test_url_request_context_;
  // Either null or owned by proxy_resolving_socket_factory_.
  MockProxyResolvingSocketFactory* mock_proxy_resolving_socket_factory_;
  std::unique_ptr<network::mojom::ProxyResolvingSocketFactory>
      proxy_resolving_socket_factory_;
  std::unique_ptr<mojo::Binding<network::mojom::ProxyResolvingSocketFactory>>
      proxy_resolving_socket_factory_binding_;

  std::unique_ptr<NetworkServiceAsyncSocket> ns_async_socket_;
  base::circular_deque<SignalSocketState> signal_socket_states_;
  const rtc::SocketAddress addr_;

 private:
  DISALLOW_COPY_AND_ASSIGN(NetworkServiceAsyncSocketTest);
};

TEST_F(NetworkServiceAsyncSocketTest, InitialState) {
  ExpectClosed();
  ExpectNoSignal();
}

TEST_F(NetworkServiceAsyncSocketTest, EmptyClose) {
  ExpectClosed();
  EXPECT_TRUE(ns_async_socket_->Close());
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketTest, ImmediateConnectAndClose) {
  DoOpenClosed();

  ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_OPEN);

  DoCloseOpenedNoError();
}

// After this, no need to test immediate successful connect and
// Close() so thoroughly.

TEST_F(NetworkServiceAsyncSocketTest, DoubleClose) {
  DoOpenClosed();

  EXPECT_TRUE(ns_async_socket_->Close());
  ExpectClosed();
  ExpectSignalSocketState(SignalSocketState::NoError(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED));

  EXPECT_TRUE(ns_async_socket_->Close());
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketTest, NoHostnameConnect) {
  rtc::IPAddress ip_address;
  EXPECT_TRUE(rtc::IPFromString("127.0.0.1", &ip_address));
  const rtc::SocketAddress no_hostname_addr(ip_address, addr_.port());
  EXPECT_FALSE(ns_async_socket_->Connect(no_hostname_addr));
  ExpectErrorState(NetworkServiceAsyncSocket::STATE_CLOSED,
                   NetworkServiceAsyncSocket::ERROR_DNS);

  EXPECT_TRUE(ns_async_socket_->Close());
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketTest, ZeroPortConnect) {
  const rtc::SocketAddress zero_port_addr(addr_.hostname(), 0);
  EXPECT_FALSE(ns_async_socket_->Connect(zero_port_addr));
  ExpectErrorState(NetworkServiceAsyncSocket::STATE_CLOSED,
                   NetworkServiceAsyncSocket::ERROR_DNS);

  EXPECT_TRUE(ns_async_socket_->Close());
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketTest, DoubleConnect) {
  EXPECT_DEBUG_DEATH(
      {
        DoOpenClosed();

        EXPECT_FALSE(ns_async_socket_->Connect(addr_));
        ExpectErrorState(NetworkServiceAsyncSocket::STATE_OPEN,
                         NetworkServiceAsyncSocket::ERROR_WRONGSTATE);

        DoCloseOpened(SignalSocketState(
            SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
            NetworkServiceAsyncSocket::ERROR_WRONGSTATE, net::OK));
      },
      "non-closed socket");
}

TEST_F(NetworkServiceAsyncSocketTest, ImmediateConnectCloseBeforeRead) {
  DoOpenClosed();

  EXPECT_TRUE(ns_async_socket_->Close());
  ExpectClosed();
  ExpectSignalSocketState(SignalSocketState::NoError(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED));

  base::RunLoop().RunUntilIdle();
}

TEST_F(NetworkServiceAsyncSocketTest, HangingConnect) {
  EXPECT_TRUE(ns_async_socket_->Connect(addr_));
  ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_CONNECTING);
  ExpectNoSignal();

  EXPECT_TRUE(ns_async_socket_->Close());
  ExpectClosed();
  ExpectSignalSocketState(SignalSocketState::NoError(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED));
}

TEST_F(NetworkServiceAsyncSocketTest, PendingConnect) {
  async_socket_data_provider_.set_connect_data(
      net::MockConnect(net::ASYNC, net::OK));
  EXPECT_TRUE(ns_async_socket_->Connect(addr_));
  ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_CONNECTING);
  ExpectNoSignal();

  base::RunLoop().RunUntilIdle();
  ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_OPEN);
  ExpectSignalSocketState(SignalSocketState::NoError(
      SIGNAL_CONNECT, NetworkServiceAsyncSocket::STATE_OPEN));
  ExpectNoSignal();

  base::RunLoop().RunUntilIdle();

  DoCloseOpenedNoError();
}

// After this no need to test successful pending connect so
// thoroughly.

TEST_F(NetworkServiceAsyncSocketTest, PendingConnectCloseBeforeRead) {
  async_socket_data_provider_.set_connect_data(
      net::MockConnect(net::ASYNC, net::OK));
  EXPECT_TRUE(ns_async_socket_->Connect(addr_));

  base::RunLoop().RunUntilIdle();
  ExpectSignalSocketState(SignalSocketState::NoError(
      SIGNAL_CONNECT, NetworkServiceAsyncSocket::STATE_OPEN));

  DoCloseOpenedNoError();

  base::RunLoop().RunUntilIdle();
}

TEST_F(NetworkServiceAsyncSocketTest, PendingConnectError) {
  async_socket_data_provider_.set_connect_data(
      net::MockConnect(net::ASYNC, net::ERR_TIMED_OUT));
  EXPECT_TRUE(ns_async_socket_->Connect(addr_));

  base::RunLoop().RunUntilIdle();

  ExpectSignalSocketState(SignalSocketState(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
      NetworkServiceAsyncSocket::ERROR_WINSOCK, net::ERR_TIMED_OUT));
}

// After this we can assume Connect() and Close() work as expected.

TEST_F(NetworkServiceAsyncSocketTest, EmptyRead) {
  DoOpenClosed();

  char buf[4096];
  size_t len_read = 10000U;
  EXPECT_TRUE(ns_async_socket_->Read(buf, sizeof(buf), &len_read));
  EXPECT_EQ(0U, len_read);

  DoCloseOpenedNoError();
}

TEST_F(NetworkServiceAsyncSocketTest, WrongRead) {
  EXPECT_DEBUG_DEATH(
      {
        async_socket_data_provider_.set_connect_data(
            net::MockConnect(net::ASYNC, net::OK));
        EXPECT_TRUE(ns_async_socket_->Connect(addr_));
        ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_CONNECTING);
        ExpectNoSignal();

        char buf[4096];
        size_t len_read;
        EXPECT_FALSE(ns_async_socket_->Read(buf, sizeof(buf), &len_read));
        ExpectErrorState(NetworkServiceAsyncSocket::STATE_CONNECTING,
                         NetworkServiceAsyncSocket::ERROR_WRONGSTATE);
        EXPECT_TRUE(ns_async_socket_->Close());
        ExpectSignalSocketState(SignalSocketState(
            SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
            NetworkServiceAsyncSocket::ERROR_WRONGSTATE, net::OK));
      },
      "non-open");
}

TEST_F(NetworkServiceAsyncSocketTest, WrongReadClosed) {
  char buf[4096];
  size_t len_read;
  EXPECT_FALSE(ns_async_socket_->Read(buf, sizeof(buf), &len_read));
  ExpectErrorState(NetworkServiceAsyncSocket::STATE_CLOSED,
                   NetworkServiceAsyncSocket::ERROR_WRONGSTATE);
  EXPECT_TRUE(ns_async_socket_->Close());
}

const char kReadData[] = "mydatatoread";

TEST_F(NetworkServiceAsyncSocketTest, Read) {
  async_socket_data_provider_.AddRead(net::MockRead(kReadData));
  DoOpenClosed();

  ExpectReadSignal();
  ExpectNoSignal();

  EXPECT_EQ(kReadData, DrainRead(1));

  base::RunLoop().RunUntilIdle();

  DoCloseOpenedNoError();
}

TEST_F(NetworkServiceAsyncSocketTest, ReadTwice) {
  async_socket_data_provider_.AddRead(net::MockRead(kReadData));
  DoOpenClosed();

  ExpectReadSignal();
  ExpectNoSignal();

  EXPECT_EQ(kReadData, DrainRead(1));

  base::RunLoop().RunUntilIdle();

  const char kReadData2[] = "mydatatoread2";
  async_socket_data_provider_.AddRead(net::MockRead(kReadData2));
  base::RunLoop().RunUntilIdle();

  ExpectReadSignal();
  ExpectNoSignal();

  EXPECT_EQ(kReadData2, DrainRead(1));

  DoCloseOpenedNoError();
}

TEST_F(NetworkServiceAsyncSocketTest, ReadError) {
  async_socket_data_provider_.AddRead(net::MockRead(kReadData));
  DoOpenClosed();

  ExpectReadSignal();
  ExpectNoSignal();

  EXPECT_EQ(kReadData, DrainRead(1));

  base::RunLoop().RunUntilIdle();

  async_socket_data_provider_.AddRead(
      net::MockRead(net::SYNCHRONOUS, net::ERR_TIMED_OUT));
  base::RunLoop().RunUntilIdle();

  ExpectSignalSocketState(SignalSocketState(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
      NetworkServiceAsyncSocket::ERROR_WINSOCK, net::ERR_TIMED_OUT));
}

TEST_F(NetworkServiceAsyncSocketTest, ReadEOF) {
  async_socket_data_provider_.AddRead(net::MockRead(kReadData));
  DoOpenClosed();

  ExpectReadSignal();
  ExpectNoSignal();

  EXPECT_EQ(kReadData, DrainRead(1));

  base::RunLoop().RunUntilIdle();

  async_socket_data_provider_.AddRead(net::MockRead(net::SYNCHRONOUS, net::OK));
  base::RunLoop().RunUntilIdle();
  ExpectSignalSocketState(SignalSocketState::NoError(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED));
}

TEST_F(NetworkServiceAsyncSocketTest, ReadEmpty) {
  async_socket_data_provider_.AddRead(net::MockRead(""));
  DoOpenClosed();

  ExpectSignalSocketState(SignalSocketState::NoError(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED));
}

TEST_F(NetworkServiceAsyncSocketTest, PendingRead) {
  DoOpenClosed();

  ExpectNoSignal();

  async_socket_data_provider_.AddRead(net::MockRead(kReadData));
  base::RunLoop().RunUntilIdle();

  ExpectSignalSocketState(SignalSocketState::NoError(
      SIGNAL_READ, NetworkServiceAsyncSocket::STATE_OPEN));
  ExpectNoSignal();

  EXPECT_EQ(kReadData, DrainRead(1));

  base::RunLoop().RunUntilIdle();

  DoCloseOpenedNoError();
}

TEST_F(NetworkServiceAsyncSocketTest, PendingEmptyRead) {
  DoOpenClosed();

  ExpectNoSignal();

  async_socket_data_provider_.AddRead(net::MockRead(""));
  base::RunLoop().RunUntilIdle();

  ExpectSignalSocketState(SignalSocketState::NoError(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED));
}

TEST_F(NetworkServiceAsyncSocketTest, PendingReadError) {
  DoOpenClosed();

  ExpectNoSignal();

  async_socket_data_provider_.AddRead(
      net::MockRead(net::ASYNC, net::ERR_TIMED_OUT));
  base::RunLoop().RunUntilIdle();

  ExpectSignalSocketState(SignalSocketState(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
      NetworkServiceAsyncSocket::ERROR_WINSOCK, net::ERR_TIMED_OUT));
}

// After this we can assume non-SSL Read() works as expected.

TEST_F(NetworkServiceAsyncSocketTest, WrongWrite) {
  EXPECT_DEBUG_DEATH(
      {
        std::string data("foo");
        EXPECT_FALSE(ns_async_socket_->Write(data.data(), data.size()));
        ExpectErrorState(NetworkServiceAsyncSocket::STATE_CLOSED,
                         NetworkServiceAsyncSocket::ERROR_WRONGSTATE);
        EXPECT_TRUE(ns_async_socket_->Close());
      },
      "non-open");
}

const char kWriteData[] = "mydatatowrite";

TEST_F(NetworkServiceAsyncSocketTest, SyncWrite) {
  async_socket_data_provider_.AddWrite(
      net::MockWrite(net::SYNCHRONOUS, kWriteData, 3));
  async_socket_data_provider_.AddWrite(
      net::MockWrite(net::SYNCHRONOUS, kWriteData + 3, 5));
  async_socket_data_provider_.AddWrite(net::MockWrite(
      net::SYNCHRONOUS, kWriteData + 8, base::size(kWriteData) - 8));
  DoOpenClosed();

  EXPECT_TRUE(ns_async_socket_->Write(kWriteData, 3));
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(ns_async_socket_->Write(kWriteData + 3, 5));
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(
      ns_async_socket_->Write(kWriteData + 8, base::size(kWriteData) - 8));
  base::RunLoop().RunUntilIdle();

  ExpectNoSignal();

  DoCloseOpenedNoError();
}

TEST_F(NetworkServiceAsyncSocketTest, AsyncWrite) {
  DoOpenClosed();

  async_socket_data_provider_.AddWrite(
      net::MockWrite(net::ASYNC, kWriteData, 3));
  async_socket_data_provider_.AddWrite(
      net::MockWrite(net::ASYNC, kWriteData + 3, 5));
  async_socket_data_provider_.AddWrite(
      net::MockWrite(net::ASYNC, kWriteData + 8, base::size(kWriteData) - 8));

  EXPECT_TRUE(ns_async_socket_->Write(kWriteData, 3));
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(ns_async_socket_->Write(kWriteData + 3, 5));
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(
      ns_async_socket_->Write(kWriteData + 8, base::size(kWriteData) - 8));
  base::RunLoop().RunUntilIdle();

  ExpectNoSignal();

  DoCloseOpenedNoError();
}

TEST_F(NetworkServiceAsyncSocketTest, AsyncWriteError) {
  DoOpenClosed();

  async_socket_data_provider_.AddWrite(
      net::MockWrite(net::ASYNC, kWriteData, 3));
  async_socket_data_provider_.AddWrite(
      net::MockWrite(net::ASYNC, kWriteData + 3, 5));
  async_socket_data_provider_.AddWrite(
      net::MockWrite(net::ASYNC, net::ERR_TIMED_OUT));

  EXPECT_TRUE(ns_async_socket_->Write(kWriteData, 3));
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(ns_async_socket_->Write(kWriteData + 3, 5));
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(
      ns_async_socket_->Write(kWriteData + 8, base::size(kWriteData) - 8));
  base::RunLoop().RunUntilIdle();

  ExpectSignalSocketState(SignalSocketState(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
      NetworkServiceAsyncSocket::ERROR_WINSOCK, net::ERR_TIMED_OUT));
}

TEST_F(NetworkServiceAsyncSocketTest, LargeWrite) {
  EXPECT_DEBUG_DEATH(
      {
        DoOpenClosed();

        std::string large_data(100, 'x');
        EXPECT_FALSE(
            ns_async_socket_->Write(large_data.data(), large_data.size()));
        ExpectState(NetworkServiceAsyncSocket::STATE_OPEN,
                    NetworkServiceAsyncSocket::ERROR_WINSOCK,
                    net::ERR_INSUFFICIENT_RESOURCES);
        DoCloseOpened(SignalSocketState(
            SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
            NetworkServiceAsyncSocket::ERROR_WINSOCK,
            net::ERR_INSUFFICIENT_RESOURCES));
      },
      "exceed the max write buffer");
}

TEST_F(NetworkServiceAsyncSocketTest, LargeAccumulatedWrite) {
  EXPECT_DEBUG_DEATH(
      {
        DoOpenClosed();

        std::string data(15, 'x');
        EXPECT_TRUE(ns_async_socket_->Write(data.data(), data.size()));
        EXPECT_FALSE(ns_async_socket_->Write(data.data(), data.size()));
        ExpectState(NetworkServiceAsyncSocket::STATE_OPEN,
                    NetworkServiceAsyncSocket::ERROR_WINSOCK,
                    net::ERR_INSUFFICIENT_RESOURCES);
        DoCloseOpened(SignalSocketState(
            SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
            NetworkServiceAsyncSocket::ERROR_WINSOCK,
            net::ERR_INSUFFICIENT_RESOURCES));
      },
      "exceed the max write buffer");
}

// After this we can assume non-SSL I/O works as expected.

TEST_F(NetworkServiceAsyncSocketTest, HangingSSLConnect) {
  async_socket_data_provider_.AddRead(net::MockRead(kReadData));
  DoOpenClosed();
  ExpectReadSignal();

  EXPECT_TRUE(ns_async_socket_->StartTls("fakedomain.com"));
  ExpectNoSignal();

  ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_TLS_CONNECTING);
  EXPECT_TRUE(ns_async_socket_->Close());
  ExpectSignalSocketState(SignalSocketState::NoError(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED));
  ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_CLOSED);
}

TEST_F(NetworkServiceAsyncSocketTest, ImmediateSSLConnect) {
  async_socket_data_provider_.AddRead(net::MockRead(kReadData));
  DoOpenClosed();
  ExpectReadSignal();

  EXPECT_TRUE(ns_async_socket_->StartTls("fakedomain.com"));
  base::RunLoop().RunUntilIdle();
  ExpectSSLConnectSignal();
  ExpectNoSignal();
  ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_TLS_OPEN);

  DoSSLCloseOpenedNoError();
}

TEST_F(NetworkServiceAsyncSocketTest, DoubleSSLConnect) {
  EXPECT_DEBUG_DEATH(
      {
        async_socket_data_provider_.AddRead(net::MockRead(kReadData));
        DoOpenClosed();
        ExpectReadSignal();

        EXPECT_TRUE(ns_async_socket_->StartTls("fakedomain.com"));
        base::RunLoop().RunUntilIdle();
        ExpectSSLConnectSignal();
        ExpectNoSignal();
        ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_TLS_OPEN);

        EXPECT_FALSE(ns_async_socket_->StartTls("fakedomain.com"));

        DoSSLCloseOpened(SignalSocketState(
            SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
            NetworkServiceAsyncSocket::ERROR_WRONGSTATE, net::OK));
      },
      "wrong state");
}

TEST_F(NetworkServiceAsyncSocketTest, FailedSSLConnect) {
  ssl_socket_data_provider_.connect =
      net::MockConnect(net::ASYNC, net::ERR_CERT_COMMON_NAME_INVALID),

  async_socket_data_provider_.AddRead(net::MockRead(kReadData));
  DoOpenClosed();
  ExpectReadSignal();

  EXPECT_TRUE(ns_async_socket_->StartTls("fakedomain.com"));
  base::RunLoop().RunUntilIdle();
  ExpectSignalSocketState(
      SignalSocketState(SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
                        NetworkServiceAsyncSocket::ERROR_WINSOCK,
                        net::ERR_CERT_COMMON_NAME_INVALID));

  EXPECT_TRUE(ns_async_socket_->Close());
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketTest, ReadDuringSSLConnecting) {
  async_socket_data_provider_.AddRead(net::MockRead(kReadData));
  DoOpenClosed();
  ExpectReadSignal();
  EXPECT_EQ(kReadData, DrainRead(1));

  EXPECT_TRUE(ns_async_socket_->StartTls("fakedomain.com"));
  ExpectNoSignal();

  // Shouldn't do anything.
  async_socket_data_provider_.AddRead(net::MockRead(kReadData));

  char buf[4096];
  size_t len_read = 10000U;
  EXPECT_TRUE(ns_async_socket_->Read(buf, sizeof(buf), &len_read));
  EXPECT_EQ(0U, len_read);

  base::RunLoop().RunUntilIdle();
  ExpectSSLConnectSignal();
  ExpectSSLReadSignal();
  ExpectNoSignal();
  ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_TLS_OPEN);

  len_read = 10000U;
  EXPECT_TRUE(ns_async_socket_->Read(buf, sizeof(buf), &len_read));
  EXPECT_EQ(kReadData, std::string(buf, len_read));

  DoSSLCloseOpenedNoError();
}

TEST_F(NetworkServiceAsyncSocketTest, WriteDuringSSLConnecting) {
  async_socket_data_provider_.AddRead(net::MockRead(kReadData));
  DoOpenClosed();
  ExpectReadSignal();

  EXPECT_TRUE(ns_async_socket_->StartTls("fakedomain.com"));
  ExpectNoSignal();
  ExpectNonErrorState(NetworkServiceAsyncSocket::STATE_TLS_CONNECTING);

  async_socket_data_provider_.AddWrite(
      net::MockWrite(net::ASYNC, kWriteData, 3));

  // Shouldn't do anything.
  EXPECT_TRUE(ns_async_socket_->Write(kWriteData, 3));

  // TODO(akalin): Figure out how to test that the write happens
  // *after* the SSL connect.

  base::RunLoop().RunUntilIdle();
  ExpectSSLConnectSignal();
  ExpectNoSignal();

  base::RunLoop().RunUntilIdle();

  DoSSLCloseOpenedNoError();
}

// After this we can assume SSL connect works as expected.

TEST_F(NetworkServiceAsyncSocketTest, SSLRead) {
  DoSSLOpenClosed();
  async_socket_data_provider_.AddRead(net::MockRead(kReadData));
  base::RunLoop().RunUntilIdle();

  ExpectSSLReadSignal();
  ExpectNoSignal();

  EXPECT_EQ(kReadData, DrainRead(1));

  base::RunLoop().RunUntilIdle();

  DoSSLCloseOpenedNoError();
}

TEST_F(NetworkServiceAsyncSocketTest, SSLSyncWrite) {
  async_socket_data_provider_.AddWrite(
      net::MockWrite(net::SYNCHRONOUS, kWriteData, 3));
  async_socket_data_provider_.AddWrite(
      net::MockWrite(net::SYNCHRONOUS, kWriteData + 3, 5));
  async_socket_data_provider_.AddWrite(net::MockWrite(
      net::SYNCHRONOUS, kWriteData + 8, base::size(kWriteData) - 8));
  DoSSLOpenClosed();

  EXPECT_TRUE(ns_async_socket_->Write(kWriteData, 3));
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(ns_async_socket_->Write(kWriteData + 3, 5));
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(
      ns_async_socket_->Write(kWriteData + 8, base::size(kWriteData) - 8));
  base::RunLoop().RunUntilIdle();

  ExpectNoSignal();

  DoSSLCloseOpenedNoError();
}

TEST_F(NetworkServiceAsyncSocketTest, SSLAsyncWrite) {
  DoSSLOpenClosed();

  async_socket_data_provider_.AddWrite(
      net::MockWrite(net::ASYNC, kWriteData, 3));
  async_socket_data_provider_.AddWrite(
      net::MockWrite(net::ASYNC, kWriteData + 3, 5));
  async_socket_data_provider_.AddWrite(
      net::MockWrite(net::ASYNC, kWriteData + 8, base::size(kWriteData) - 8));

  EXPECT_TRUE(ns_async_socket_->Write(kWriteData, 3));
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(ns_async_socket_->Write(kWriteData + 3, 5));
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(
      ns_async_socket_->Write(kWriteData + 8, base::size(kWriteData) - 8));
  base::RunLoop().RunUntilIdle();

  ExpectNoSignal();

  DoSSLCloseOpenedNoError();
}

class NetworkServiceAsyncSocketMojoTest : public NetworkServiceAsyncSocketTest {
 protected:
  NetworkServiceAsyncSocketMojoTest()
      : NetworkServiceAsyncSocketTest(true /* use_mojo_level_mock */) {}
  ~NetworkServiceAsyncSocketMojoTest() override {}
};

TEST_F(NetworkServiceAsyncSocketMojoTest, ReadEOF1) {
  DoOpenClosed();
  mock_proxy_resolving_socket_factory_->socket()->RunEvents(
      {MockProxyResolvingSocket::kRead,
       MockProxyResolvingSocket::kCloseReadPipe,
       MockProxyResolvingSocket::kReadEofError,
       MockProxyResolvingSocket::kCloseObserverPipe});

  ExpectReadSignal();
  ExpectNoSignal();
  EXPECT_EQ("data", DrainRead(1));

  base::RunLoop().RunUntilIdle();
  ExpectSignalSocketState(SignalSocketState::NoError(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED));
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketMojoTest, ReadEOF2) {
  DoOpenClosed();
  mock_proxy_resolving_socket_factory_->socket()->RunEvents(
      {MockProxyResolvingSocket::kReadEofError,
       MockProxyResolvingSocket::kCloseObserverPipe,
       MockProxyResolvingSocket::kRead,
       MockProxyResolvingSocket::kCloseReadPipe});

  ExpectReadSignal();
  ExpectNoSignal();
  EXPECT_EQ("data", DrainRead(1));

  base::RunLoop().RunUntilIdle();
  ExpectSignalSocketState(SignalSocketState::NoError(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED));
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketMojoTest, ReadError1) {
  DoOpenClosed();
  mock_proxy_resolving_socket_factory_->socket()->RunEvents(
      {MockProxyResolvingSocket::kRead,
       MockProxyResolvingSocket::kCloseReadPipe,
       MockProxyResolvingSocket::kReadError,
       MockProxyResolvingSocket::kCloseObserverPipe});

  ExpectReadSignal();
  ExpectNoSignal();
  EXPECT_EQ("data", DrainRead(1));

  base::RunLoop().RunUntilIdle();
  ExpectSignalSocketState(SignalSocketState(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
      NetworkServiceAsyncSocket::ERROR_WINSOCK, net::ERR_OUT_OF_MEMORY));
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketMojoTest, ReadError2) {
  DoOpenClosed();
  mock_proxy_resolving_socket_factory_->socket()->RunEvents(
      {MockProxyResolvingSocket::kReadError,
       MockProxyResolvingSocket::kCloseObserverPipe,
       MockProxyResolvingSocket::kRead,
       MockProxyResolvingSocket::kCloseReadPipe});

  ExpectReadSignal();
  ExpectNoSignal();
  EXPECT_EQ("data", DrainRead(1));

  base::RunLoop().RunUntilIdle();
  ExpectSignalSocketState(SignalSocketState(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
      NetworkServiceAsyncSocket::ERROR_WINSOCK, net::ERR_OUT_OF_MEMORY));
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketMojoTest, ReadErrorDouble) {
  DoOpenClosed();
  mock_proxy_resolving_socket_factory_->socket()->RunEvents(
      {MockProxyResolvingSocket::kReadError,
       MockProxyResolvingSocket::kReadError,
       MockProxyResolvingSocket::kCloseObserverPipe,
       MockProxyResolvingSocket::kRead,
       MockProxyResolvingSocket::kCloseReadPipe});

  ExpectReadSignal();
  ExpectNoSignal();
  EXPECT_EQ("data", DrainRead(1));

  base::RunLoop().RunUntilIdle();
  ExpectSignalSocketState(SignalSocketState(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
      NetworkServiceAsyncSocket::ERROR_WINSOCK, net::ERR_OUT_OF_MEMORY));
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketMojoTest, ReadErrorDoubleInvalid) {
  DoOpenClosed();
  mock_proxy_resolving_socket_factory_->socket()->RunEvents(
      {MockProxyResolvingSocket::kReadError,
       MockProxyResolvingSocket::kReadErrorInvalid,
       MockProxyResolvingSocket::kCloseObserverPipe,
       MockProxyResolvingSocket::kRead,
       MockProxyResolvingSocket::kCloseReadPipe});

  ExpectReadSignal();
  ExpectNoSignal();
  EXPECT_EQ("data", DrainRead(1));

  base::RunLoop().RunUntilIdle();
  ExpectSignalSocketState(SignalSocketState(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
      NetworkServiceAsyncSocket::ERROR_WINSOCK, net::ERR_OUT_OF_MEMORY));
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketMojoTest, ReadErrorDoubleInvalid2) {
  DoOpenClosed();
  mock_proxy_resolving_socket_factory_->socket()->RunEvents(
      {MockProxyResolvingSocket::kReadErrorInvalid,
       MockProxyResolvingSocket::kReadError,
       MockProxyResolvingSocket::kCloseObserverPipe,
       MockProxyResolvingSocket::kRead,
       MockProxyResolvingSocket::kCloseReadPipe});

  ExpectReadSignal();
  ExpectNoSignal();
  EXPECT_EQ("data", DrainRead(1));

  base::RunLoop().RunUntilIdle();
  ExpectSignalSocketState(SignalSocketState(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
      NetworkServiceAsyncSocket::ERROR_WINSOCK, net::ERR_FAILED));
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketMojoTest, ReadErrorClosedObserverPipe) {
  DoOpenClosed();
  mock_proxy_resolving_socket_factory_->socket()->RunEvents(
      {MockProxyResolvingSocket::kRead,
       MockProxyResolvingSocket::kCloseObserverPipe});
  // Can't run kCloseReadPipe since it'll already be closed.

  ExpectReadSignal();
  // Since this is a misbehaving network service process scenario, no attempt
  // to recover the data is made.
  ExpectSignalSocketState(SignalSocketState(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
      NetworkServiceAsyncSocket::ERROR_WINSOCK, net::ERR_FAILED));
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketMojoTest, WriteError1) {
  DoOpenClosed();
  ExpectNoSignal();
  ns_async_socket_->Write("atad", 4);
  base::RunLoop().RunUntilIdle();

  mock_proxy_resolving_socket_factory_->socket()->RunEvents(
      {MockProxyResolvingSocket::kWrite,
       MockProxyResolvingSocket::kCloseWritePipe,
       MockProxyResolvingSocket::kWriteError});
  // Cannot close the observer pipe here at the end since the other size
  // would have closed it already.

  base::RunLoop().RunUntilIdle();
  ExpectSignalSocketState(SignalSocketState(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
      NetworkServiceAsyncSocket::ERROR_WINSOCK, net::ERR_ACCESS_DENIED));
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketMojoTest, WriteError2) {
  DoOpenClosed();
  ExpectNoSignal();
  ns_async_socket_->Write("atad", 4);
  base::RunLoop().RunUntilIdle();

  mock_proxy_resolving_socket_factory_->socket()->RunEvents(
      {MockProxyResolvingSocket::kWriteError,
       MockProxyResolvingSocket::kCloseObserverPipe,
       MockProxyResolvingSocket::kWrite,
       MockProxyResolvingSocket::kCloseWritePipe});

  base::RunLoop().RunUntilIdle();
  ExpectSignalSocketState(SignalSocketState(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
      NetworkServiceAsyncSocket::ERROR_WINSOCK, net::ERR_ACCESS_DENIED));
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketMojoTest, WriteErrorDouble) {
  DoOpenClosed();
  ExpectNoSignal();
  ns_async_socket_->Write("atad", 4);
  base::RunLoop().RunUntilIdle();

  mock_proxy_resolving_socket_factory_->socket()->RunEvents(
      {MockProxyResolvingSocket::kWriteError,
       MockProxyResolvingSocket::kWriteError,
       MockProxyResolvingSocket::kCloseObserverPipe,
       MockProxyResolvingSocket::kWrite,
       MockProxyResolvingSocket::kCloseWritePipe});

  base::RunLoop().RunUntilIdle();
  ExpectSignalSocketState(SignalSocketState(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
      NetworkServiceAsyncSocket::ERROR_WINSOCK, net::ERR_ACCESS_DENIED));
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketMojoTest, WriteErrorDoubleInvalid) {
  DoOpenClosed();
  ExpectNoSignal();
  ns_async_socket_->Write("atad", 4);
  base::RunLoop().RunUntilIdle();

  mock_proxy_resolving_socket_factory_->socket()->RunEvents(
      {MockProxyResolvingSocket::kWriteError,
       MockProxyResolvingSocket::kWriteErrorInvalid,
       MockProxyResolvingSocket::kCloseObserverPipe,
       MockProxyResolvingSocket::kWrite,
       MockProxyResolvingSocket::kCloseWritePipe});

  base::RunLoop().RunUntilIdle();
  ExpectSignalSocketState(SignalSocketState(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
      NetworkServiceAsyncSocket::ERROR_WINSOCK, net::ERR_ACCESS_DENIED));
  ExpectClosed();
}

TEST_F(NetworkServiceAsyncSocketMojoTest, WriteErrorDoubleInvalid2) {
  DoOpenClosed();
  ExpectNoSignal();
  ns_async_socket_->Write("atad", 4);
  base::RunLoop().RunUntilIdle();

  mock_proxy_resolving_socket_factory_->socket()->RunEvents(
      {MockProxyResolvingSocket::kWriteErrorInvalid,
       MockProxyResolvingSocket::kWriteError,
       MockProxyResolvingSocket::kCloseObserverPipe,
       MockProxyResolvingSocket::kWrite,
       MockProxyResolvingSocket::kCloseWritePipe});

  base::RunLoop().RunUntilIdle();
  ExpectSignalSocketState(SignalSocketState(
      SIGNAL_CLOSE, NetworkServiceAsyncSocket::STATE_CLOSED,
      NetworkServiceAsyncSocket::ERROR_WINSOCK, net::ERR_FAILED));
  ExpectClosed();
}

}  // namespace

}  // namespace jingle_glue
