blob: 39f7137ef8b554f615f32e02f8baed5d0ed63182 [file] [log] [blame]
// 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/macros.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/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, arraysize(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, arraysize(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, arraysize(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, arraysize(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, arraysize(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, arraysize(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, arraysize(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, arraysize(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, arraysize(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