summaryrefslogtreecommitdiff
path: root/chromium/jingle/glue/chrome_async_socket_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/jingle/glue/chrome_async_socket_unittest.cc')
-rw-r--r--chromium/jingle/glue/chrome_async_socket_unittest.cc1083
1 files changed, 1083 insertions, 0 deletions
diff --git a/chromium/jingle/glue/chrome_async_socket_unittest.cc b/chromium/jingle/glue/chrome_async_socket_unittest.cc
new file mode 100644
index 00000000000..db3d2b09c9f
--- /dev/null
+++ b/chromium/jingle/glue/chrome_async_socket_unittest.cc
@@ -0,0 +1,1083 @@
+// 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/chrome_async_socket.h"
+
+#include <deque>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "jingle/glue/resolving_client_socket_factory.h"
+#include "net/base/address_list.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "net/cert/mock_cert_verifier.h"
+#include "net/http/transport_security_state.h"
+#include "net/socket/socket_test_util.h"
+#include "net/socket/ssl_client_socket.h"
+#include "net/ssl/ssl_config_service.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libjingle/source/talk/base/ipaddress.h"
+#include "third_party/libjingle/source/talk/base/sigslot.h"
+#include "third_party/libjingle/source/talk/base/socketaddress.h"
+
+namespace jingle_glue {
+
+namespace {
+
+// Data provider that handles reads/writes for ChromeAsyncSocket.
+class AsyncSocketDataProvider : public net::SocketDataProvider {
+ public:
+ AsyncSocketDataProvider() : has_pending_read_(false) {}
+
+ virtual ~AsyncSocketDataProvider() {
+ EXPECT_TRUE(writes_.empty());
+ EXPECT_TRUE(reads_.empty());
+ }
+
+ // If there's no read, sets the "has pending read" flag. Otherwise,
+ // pops the next read.
+ virtual net::MockRead GetNextRead() 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;
+ }
+
+ // Simply pops the next write and, if applicable, compares it to
+ // |data|.
+ virtual 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.
+ virtual 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_) {
+ socket()->OnReadComplete(mock_read);
+ has_pending_read_ = false;
+ return;
+ }
+ reads_.push_back(mock_read);
+ }
+
+ // Simply queues up the given write.
+ void AddWrite(const net::MockWrite& mock_write) {
+ writes_.push_back(mock_write);
+ }
+
+ private:
+ std::deque<net::MockRead> reads_;
+ bool has_pending_read_;
+
+ std::deque<net::MockWrite> writes_;
+
+ DISALLOW_COPY_AND_ASSIGN(AsyncSocketDataProvider);
+};
+
+class MockXmppClientSocketFactory : public ResolvingClientSocketFactory {
+ public:
+ MockXmppClientSocketFactory(
+ net::ClientSocketFactory* mock_client_socket_factory,
+ const net::AddressList& address_list)
+ : mock_client_socket_factory_(mock_client_socket_factory),
+ address_list_(address_list),
+ cert_verifier_(new net::MockCertVerifier),
+ transport_security_state_(new net::TransportSecurityState) {
+ }
+
+ // ResolvingClientSocketFactory implementation.
+ virtual scoped_ptr<net::StreamSocket> CreateTransportClientSocket(
+ const net::HostPortPair& host_and_port) OVERRIDE {
+ return mock_client_socket_factory_->CreateTransportClientSocket(
+ address_list_, NULL, net::NetLog::Source());
+ }
+
+ virtual scoped_ptr<net::SSLClientSocket> CreateSSLClientSocket(
+ scoped_ptr<net::ClientSocketHandle> transport_socket,
+ const net::HostPortPair& host_and_port) OVERRIDE {
+ net::SSLClientSocketContext context;
+ context.cert_verifier = cert_verifier_.get();
+ context.transport_security_state = transport_security_state_.get();
+ return mock_client_socket_factory_->CreateSSLClientSocket(
+ transport_socket.Pass(), host_and_port, ssl_config_, context);
+ }
+
+ private:
+ scoped_ptr<net::ClientSocketFactory> mock_client_socket_factory_;
+ net::AddressList address_list_;
+ net::SSLConfig ssl_config_;
+ scoped_ptr<net::CertVerifier> cert_verifier_;
+ scoped_ptr<net::TransportSecurityState> transport_security_state_;
+};
+
+class ChromeAsyncSocketTest
+ : public testing::Test,
+ public sigslot::has_slots<> {
+ protected:
+ ChromeAsyncSocketTest()
+ : ssl_socket_data_provider_(net::ASYNC, net::OK),
+ addr_("localhost", 35) {}
+
+ virtual ~ChromeAsyncSocketTest() {}
+
+ virtual void SetUp() {
+ scoped_ptr<net::MockClientSocketFactory> mock_client_socket_factory(
+ new net::MockClientSocketFactory());
+ mock_client_socket_factory->AddSocketDataProvider(
+ &async_socket_data_provider_);
+ mock_client_socket_factory->AddSSLSocketDataProvider(
+ &ssl_socket_data_provider_);
+
+ // Fake DNS resolution for |addr_| and pass it to the factory.
+ net::IPAddressNumber resolved_addr;
+ EXPECT_TRUE(net::ParseIPLiteralToNumber("127.0.0.1", &resolved_addr));
+ const net::AddressList address_list =
+ net::AddressList::CreateFromIPAddress(resolved_addr, addr_.port());
+ scoped_ptr<MockXmppClientSocketFactory> mock_xmpp_client_socket_factory(
+ new MockXmppClientSocketFactory(
+ mock_client_socket_factory.release(),
+ address_list));
+ chrome_async_socket_.reset(
+ new ChromeAsyncSocket(mock_xmpp_client_socket_factory.release(),
+ 14, 20)),
+
+ chrome_async_socket_->SignalConnected.connect(
+ this, &ChromeAsyncSocketTest::OnConnect);
+ chrome_async_socket_->SignalSSLConnected.connect(
+ this, &ChromeAsyncSocketTest::OnSSLConnect);
+ chrome_async_socket_->SignalClosed.connect(
+ this, &ChromeAsyncSocketTest::OnClose);
+ chrome_async_socket_->SignalRead.connect(
+ this, &ChromeAsyncSocketTest::OnRead);
+ chrome_async_socket_->SignalError.connect(
+ this, &ChromeAsyncSocketTest::OnError);
+ }
+
+ virtual void TearDown() {
+ // Run any tasks that we forgot to pump.
+ message_loop_.RunUntilIdle();
+ ExpectClosed();
+ ExpectNoSignal();
+ chrome_async_socket_.reset();
+ }
+
+ 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(ChromeAsyncSocket::STATE_CLOSED),
+ error(ChromeAsyncSocket::ERROR_NONE),
+ net_error(net::OK) {}
+
+ SignalSocketState(
+ Signal signal,
+ ChromeAsyncSocket::State state,
+ ChromeAsyncSocket::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);
+ }
+
+ Signal signal;
+ ChromeAsyncSocket::State state;
+ ChromeAsyncSocket::Error error;
+ net::Error net_error;
+ };
+
+ void CaptureSocketState(Signal signal) {
+ signal_socket_states_.push_back(
+ SignalSocketState::FromAsyncSocket(
+ signal, chrome_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(ChromeAsyncSocket::State state,
+ ChromeAsyncSocket::Error error,
+ net::Error net_error) {
+ EXPECT_EQ(state, chrome_async_socket_->state());
+ EXPECT_EQ(error, chrome_async_socket_->error());
+ EXPECT_EQ(net_error, chrome_async_socket_->GetError());
+ }
+
+ void ExpectNonErrorState(ChromeAsyncSocket::State state) {
+ ExpectState(state, ChromeAsyncSocket::ERROR_NONE, net::OK);
+ }
+
+ void ExpectErrorState(ChromeAsyncSocket::State state,
+ ChromeAsyncSocket::Error error) {
+ ExpectState(state, error, net::OK);
+ }
+
+ void ExpectClosed() {
+ ExpectNonErrorState(ChromeAsyncSocket::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()))
+ << signal_socket_states_.front().signal;
+ signal_socket_states_.pop_front();
+ }
+
+ void ExpectReadSignal() {
+ ExpectSignalSocketState(
+ SignalSocketState::NoError(
+ SIGNAL_READ, ChromeAsyncSocket::STATE_OPEN));
+ }
+
+ void ExpectSSLConnectSignal() {
+ ExpectSignalSocketState(
+ SignalSocketState::NoError(SIGNAL_SSL_CONNECT,
+ ChromeAsyncSocket::STATE_TLS_OPEN));
+ }
+
+ void ExpectSSLReadSignal() {
+ ExpectSignalSocketState(
+ SignalSocketState::NoError(
+ SIGNAL_READ, ChromeAsyncSocket::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(chrome_async_socket_->Connect(addr_));
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_CONNECTING);
+
+ message_loop_.RunUntilIdle();
+ // We may not necessarily be open; may have been other events
+ // queued up.
+ ExpectSignalSocketState(
+ SignalSocketState::NoError(
+ SIGNAL_CONNECT, ChromeAsyncSocket::STATE_OPEN));
+ }
+
+ void DoCloseOpened(SignalSocketState expected_signal_socket_state) {
+ // We may be in an error state, so just compare state().
+ EXPECT_EQ(ChromeAsyncSocket::STATE_OPEN, chrome_async_socket_->state());
+ EXPECT_TRUE(chrome_async_socket_->Close());
+ ExpectSignalSocketState(expected_signal_socket_state);
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_CLOSED);
+ }
+
+ void DoCloseOpenedNoError() {
+ DoCloseOpened(
+ SignalSocketState::NoError(
+ SIGNAL_CLOSE, ChromeAsyncSocket::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(chrome_async_socket_->StartTls("fakedomain.com"));
+ message_loop_.RunUntilIdle();
+ ExpectSSLConnectSignal();
+ ExpectNoSignal();
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_TLS_OPEN);
+ }
+
+ void DoSSLCloseOpened(SignalSocketState expected_signal_socket_state) {
+ // We may be in an error state, so just compare state().
+ EXPECT_EQ(ChromeAsyncSocket::STATE_TLS_OPEN,
+ chrome_async_socket_->state());
+ EXPECT_TRUE(chrome_async_socket_->Close());
+ ExpectSignalSocketState(expected_signal_socket_state);
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_CLOSED);
+ }
+
+ void DoSSLCloseOpenedNoError() {
+ DoSSLCloseOpened(
+ SignalSocketState::NoError(
+ SIGNAL_CLOSE, ChromeAsyncSocket::STATE_CLOSED));
+ }
+
+ // Read utility fucntions.
+
+ std::string DrainRead(size_t buf_size) {
+ std::string read;
+ scoped_ptr<char[]> buf(new char[buf_size]);
+ size_t len_read;
+ while (true) {
+ bool success =
+ chrome_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;
+ }
+
+ // ChromeAsyncSocket expects a message loop.
+ base::MessageLoop message_loop_;
+
+ AsyncSocketDataProvider async_socket_data_provider_;
+ net::SSLSocketDataProvider ssl_socket_data_provider_;
+
+ scoped_ptr<ChromeAsyncSocket> chrome_async_socket_;
+ std::deque<SignalSocketState> signal_socket_states_;
+ const talk_base::SocketAddress addr_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ChromeAsyncSocketTest);
+};
+
+TEST_F(ChromeAsyncSocketTest, InitialState) {
+ ExpectClosed();
+ ExpectNoSignal();
+}
+
+TEST_F(ChromeAsyncSocketTest, EmptyClose) {
+ ExpectClosed();
+ EXPECT_TRUE(chrome_async_socket_->Close());
+ ExpectClosed();
+}
+
+TEST_F(ChromeAsyncSocketTest, ImmediateConnectAndClose) {
+ DoOpenClosed();
+
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_OPEN);
+
+ DoCloseOpenedNoError();
+}
+
+// After this, no need to test immediate successful connect and
+// Close() so thoroughly.
+
+TEST_F(ChromeAsyncSocketTest, DoubleClose) {
+ DoOpenClosed();
+
+ EXPECT_TRUE(chrome_async_socket_->Close());
+ ExpectClosed();
+ ExpectSignalSocketState(
+ SignalSocketState::NoError(
+ SIGNAL_CLOSE, ChromeAsyncSocket::STATE_CLOSED));
+
+ EXPECT_TRUE(chrome_async_socket_->Close());
+ ExpectClosed();
+}
+
+TEST_F(ChromeAsyncSocketTest, NoHostnameConnect) {
+ talk_base::IPAddress ip_address;
+ EXPECT_TRUE(talk_base::IPFromString("127.0.0.1", &ip_address));
+ const talk_base::SocketAddress no_hostname_addr(ip_address, addr_.port());
+ EXPECT_FALSE(chrome_async_socket_->Connect(no_hostname_addr));
+ ExpectErrorState(ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::ERROR_DNS);
+
+ EXPECT_TRUE(chrome_async_socket_->Close());
+ ExpectClosed();
+}
+
+TEST_F(ChromeAsyncSocketTest, ZeroPortConnect) {
+ const talk_base::SocketAddress zero_port_addr(addr_.hostname(), 0);
+ EXPECT_FALSE(chrome_async_socket_->Connect(zero_port_addr));
+ ExpectErrorState(ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::ERROR_DNS);
+
+ EXPECT_TRUE(chrome_async_socket_->Close());
+ ExpectClosed();
+}
+
+TEST_F(ChromeAsyncSocketTest, DoubleConnect) {
+ EXPECT_DEBUG_DEATH({
+ DoOpenClosed();
+
+ EXPECT_FALSE(chrome_async_socket_->Connect(addr_));
+ ExpectErrorState(ChromeAsyncSocket::STATE_OPEN,
+ ChromeAsyncSocket::ERROR_WRONGSTATE);
+
+ DoCloseOpened(
+ SignalSocketState(SIGNAL_CLOSE,
+ ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::ERROR_WRONGSTATE,
+ net::OK));
+ }, "non-closed socket");
+}
+
+TEST_F(ChromeAsyncSocketTest, ImmediateConnectCloseBeforeRead) {
+ DoOpenClosed();
+
+ EXPECT_TRUE(chrome_async_socket_->Close());
+ ExpectClosed();
+ ExpectSignalSocketState(
+ SignalSocketState::NoError(
+ SIGNAL_CLOSE, ChromeAsyncSocket::STATE_CLOSED));
+
+ message_loop_.RunUntilIdle();
+}
+
+TEST_F(ChromeAsyncSocketTest, HangingConnect) {
+ EXPECT_TRUE(chrome_async_socket_->Connect(addr_));
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_CONNECTING);
+ ExpectNoSignal();
+
+ EXPECT_TRUE(chrome_async_socket_->Close());
+ ExpectClosed();
+ ExpectSignalSocketState(
+ SignalSocketState::NoError(
+ SIGNAL_CLOSE, ChromeAsyncSocket::STATE_CLOSED));
+}
+
+TEST_F(ChromeAsyncSocketTest, PendingConnect) {
+ async_socket_data_provider_.set_connect_data(
+ net::MockConnect(net::ASYNC, net::OK));
+ EXPECT_TRUE(chrome_async_socket_->Connect(addr_));
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_CONNECTING);
+ ExpectNoSignal();
+
+ message_loop_.RunUntilIdle();
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_OPEN);
+ ExpectSignalSocketState(
+ SignalSocketState::NoError(
+ SIGNAL_CONNECT, ChromeAsyncSocket::STATE_OPEN));
+ ExpectNoSignal();
+
+ message_loop_.RunUntilIdle();
+
+ DoCloseOpenedNoError();
+}
+
+// After this no need to test successful pending connect so
+// thoroughly.
+
+TEST_F(ChromeAsyncSocketTest, PendingConnectCloseBeforeRead) {
+ async_socket_data_provider_.set_connect_data(
+ net::MockConnect(net::ASYNC, net::OK));
+ EXPECT_TRUE(chrome_async_socket_->Connect(addr_));
+
+ message_loop_.RunUntilIdle();
+ ExpectSignalSocketState(
+ SignalSocketState::NoError(
+ SIGNAL_CONNECT, ChromeAsyncSocket::STATE_OPEN));
+
+ DoCloseOpenedNoError();
+
+ message_loop_.RunUntilIdle();
+}
+
+TEST_F(ChromeAsyncSocketTest, PendingConnectError) {
+ async_socket_data_provider_.set_connect_data(
+ net::MockConnect(net::ASYNC, net::ERR_TIMED_OUT));
+ EXPECT_TRUE(chrome_async_socket_->Connect(addr_));
+
+ message_loop_.RunUntilIdle();
+
+ ExpectSignalSocketState(
+ SignalSocketState(
+ SIGNAL_CLOSE, ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::ERROR_WINSOCK, net::ERR_TIMED_OUT));
+}
+
+// After this we can assume Connect() and Close() work as expected.
+
+TEST_F(ChromeAsyncSocketTest, EmptyRead) {
+ DoOpenClosed();
+
+ char buf[4096];
+ size_t len_read = 10000U;
+ EXPECT_TRUE(chrome_async_socket_->Read(buf, sizeof(buf), &len_read));
+ EXPECT_EQ(0U, len_read);
+
+ DoCloseOpenedNoError();
+}
+
+TEST_F(ChromeAsyncSocketTest, WrongRead) {
+ EXPECT_DEBUG_DEATH({
+ async_socket_data_provider_.set_connect_data(
+ net::MockConnect(net::ASYNC, net::OK));
+ EXPECT_TRUE(chrome_async_socket_->Connect(addr_));
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_CONNECTING);
+ ExpectNoSignal();
+
+ char buf[4096];
+ size_t len_read;
+ EXPECT_FALSE(chrome_async_socket_->Read(buf, sizeof(buf), &len_read));
+ ExpectErrorState(ChromeAsyncSocket::STATE_CONNECTING,
+ ChromeAsyncSocket::ERROR_WRONGSTATE);
+ EXPECT_TRUE(chrome_async_socket_->Close());
+ ExpectSignalSocketState(
+ SignalSocketState(
+ SIGNAL_CLOSE, ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::ERROR_WRONGSTATE, net::OK));
+ }, "non-open");
+}
+
+TEST_F(ChromeAsyncSocketTest, WrongReadClosed) {
+ char buf[4096];
+ size_t len_read;
+ EXPECT_FALSE(chrome_async_socket_->Read(buf, sizeof(buf), &len_read));
+ ExpectErrorState(ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::ERROR_WRONGSTATE);
+ EXPECT_TRUE(chrome_async_socket_->Close());
+}
+
+const char kReadData[] = "mydatatoread";
+
+TEST_F(ChromeAsyncSocketTest, Read) {
+ async_socket_data_provider_.AddRead(net::MockRead(kReadData));
+ DoOpenClosed();
+
+ ExpectReadSignal();
+ ExpectNoSignal();
+
+ EXPECT_EQ(kReadData, DrainRead(1));
+
+ message_loop_.RunUntilIdle();
+
+ DoCloseOpenedNoError();
+}
+
+TEST_F(ChromeAsyncSocketTest, ReadTwice) {
+ async_socket_data_provider_.AddRead(net::MockRead(kReadData));
+ DoOpenClosed();
+
+ ExpectReadSignal();
+ ExpectNoSignal();
+
+ EXPECT_EQ(kReadData, DrainRead(1));
+
+ message_loop_.RunUntilIdle();
+
+ const char kReadData2[] = "mydatatoread2";
+ async_socket_data_provider_.AddRead(net::MockRead(kReadData2));
+
+ ExpectReadSignal();
+ ExpectNoSignal();
+
+ EXPECT_EQ(kReadData2, DrainRead(1));
+
+ DoCloseOpenedNoError();
+}
+
+TEST_F(ChromeAsyncSocketTest, ReadError) {
+ async_socket_data_provider_.AddRead(net::MockRead(kReadData));
+ DoOpenClosed();
+
+ ExpectReadSignal();
+ ExpectNoSignal();
+
+ EXPECT_EQ(kReadData, DrainRead(1));
+
+ message_loop_.RunUntilIdle();
+
+ async_socket_data_provider_.AddRead(
+ net::MockRead(net::SYNCHRONOUS, net::ERR_TIMED_OUT));
+
+ ExpectSignalSocketState(
+ SignalSocketState(
+ SIGNAL_CLOSE, ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::ERROR_WINSOCK, net::ERR_TIMED_OUT));
+}
+
+TEST_F(ChromeAsyncSocketTest, ReadEmpty) {
+ async_socket_data_provider_.AddRead(net::MockRead(""));
+ DoOpenClosed();
+
+ ExpectSignalSocketState(
+ SignalSocketState::NoError(
+ SIGNAL_CLOSE, ChromeAsyncSocket::STATE_CLOSED));
+}
+
+TEST_F(ChromeAsyncSocketTest, PendingRead) {
+ DoOpenClosed();
+
+ ExpectNoSignal();
+
+ async_socket_data_provider_.AddRead(net::MockRead(kReadData));
+
+ ExpectSignalSocketState(
+ SignalSocketState::NoError(
+ SIGNAL_READ, ChromeAsyncSocket::STATE_OPEN));
+ ExpectNoSignal();
+
+ EXPECT_EQ(kReadData, DrainRead(1));
+
+ message_loop_.RunUntilIdle();
+
+ DoCloseOpenedNoError();
+}
+
+TEST_F(ChromeAsyncSocketTest, PendingEmptyRead) {
+ DoOpenClosed();
+
+ ExpectNoSignal();
+
+ async_socket_data_provider_.AddRead(net::MockRead(""));
+
+ ExpectSignalSocketState(
+ SignalSocketState::NoError(
+ SIGNAL_CLOSE, ChromeAsyncSocket::STATE_CLOSED));
+}
+
+TEST_F(ChromeAsyncSocketTest, PendingReadError) {
+ DoOpenClosed();
+
+ ExpectNoSignal();
+
+ async_socket_data_provider_.AddRead(
+ net::MockRead(net::ASYNC, net::ERR_TIMED_OUT));
+
+ ExpectSignalSocketState(
+ SignalSocketState(
+ SIGNAL_CLOSE, ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::ERROR_WINSOCK, net::ERR_TIMED_OUT));
+}
+
+// After this we can assume non-SSL Read() works as expected.
+
+TEST_F(ChromeAsyncSocketTest, WrongWrite) {
+ EXPECT_DEBUG_DEATH({
+ std::string data("foo");
+ EXPECT_FALSE(chrome_async_socket_->Write(data.data(), data.size()));
+ ExpectErrorState(ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::ERROR_WRONGSTATE);
+ EXPECT_TRUE(chrome_async_socket_->Close());
+ }, "non-open");
+}
+
+const char kWriteData[] = "mydatatowrite";
+
+TEST_F(ChromeAsyncSocketTest, 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(chrome_async_socket_->Write(kWriteData, 3));
+ message_loop_.RunUntilIdle();
+ EXPECT_TRUE(chrome_async_socket_->Write(kWriteData + 3, 5));
+ message_loop_.RunUntilIdle();
+ EXPECT_TRUE(chrome_async_socket_->Write(kWriteData + 8,
+ arraysize(kWriteData) - 8));
+ message_loop_.RunUntilIdle();
+
+ ExpectNoSignal();
+
+ DoCloseOpenedNoError();
+}
+
+TEST_F(ChromeAsyncSocketTest, 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(chrome_async_socket_->Write(kWriteData, 3));
+ message_loop_.RunUntilIdle();
+ EXPECT_TRUE(chrome_async_socket_->Write(kWriteData + 3, 5));
+ message_loop_.RunUntilIdle();
+ EXPECT_TRUE(chrome_async_socket_->Write(kWriteData + 8,
+ arraysize(kWriteData) - 8));
+ message_loop_.RunUntilIdle();
+
+ ExpectNoSignal();
+
+ DoCloseOpenedNoError();
+}
+
+TEST_F(ChromeAsyncSocketTest, 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(chrome_async_socket_->Write(kWriteData, 3));
+ message_loop_.RunUntilIdle();
+ EXPECT_TRUE(chrome_async_socket_->Write(kWriteData + 3, 5));
+ message_loop_.RunUntilIdle();
+ EXPECT_TRUE(chrome_async_socket_->Write(kWriteData + 8,
+ arraysize(kWriteData) - 8));
+ message_loop_.RunUntilIdle();
+
+ ExpectSignalSocketState(
+ SignalSocketState(
+ SIGNAL_CLOSE, ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::ERROR_WINSOCK, net::ERR_TIMED_OUT));
+}
+
+TEST_F(ChromeAsyncSocketTest, LargeWrite) {
+ EXPECT_DEBUG_DEATH({
+ DoOpenClosed();
+
+ std::string large_data(100, 'x');
+ EXPECT_FALSE(chrome_async_socket_->Write(large_data.data(),
+ large_data.size()));
+ ExpectState(ChromeAsyncSocket::STATE_OPEN,
+ ChromeAsyncSocket::ERROR_WINSOCK,
+ net::ERR_INSUFFICIENT_RESOURCES);
+ DoCloseOpened(
+ SignalSocketState(
+ SIGNAL_CLOSE, ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::ERROR_WINSOCK,
+ net::ERR_INSUFFICIENT_RESOURCES));
+ }, "exceed the max write buffer");
+}
+
+TEST_F(ChromeAsyncSocketTest, LargeAccumulatedWrite) {
+ EXPECT_DEBUG_DEATH({
+ DoOpenClosed();
+
+ std::string data(15, 'x');
+ EXPECT_TRUE(chrome_async_socket_->Write(data.data(), data.size()));
+ EXPECT_FALSE(chrome_async_socket_->Write(data.data(), data.size()));
+ ExpectState(ChromeAsyncSocket::STATE_OPEN,
+ ChromeAsyncSocket::ERROR_WINSOCK,
+ net::ERR_INSUFFICIENT_RESOURCES);
+ DoCloseOpened(
+ SignalSocketState(
+ SIGNAL_CLOSE, ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::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(ChromeAsyncSocketTest, HangingSSLConnect) {
+ async_socket_data_provider_.AddRead(net::MockRead(kReadData));
+ DoOpenClosed();
+ ExpectReadSignal();
+
+ EXPECT_TRUE(chrome_async_socket_->StartTls("fakedomain.com"));
+ ExpectNoSignal();
+
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_TLS_CONNECTING);
+ EXPECT_TRUE(chrome_async_socket_->Close());
+ ExpectSignalSocketState(
+ SignalSocketState::NoError(SIGNAL_CLOSE,
+ ChromeAsyncSocket::STATE_CLOSED));
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_CLOSED);
+}
+
+TEST_F(ChromeAsyncSocketTest, ImmediateSSLConnect) {
+ async_socket_data_provider_.AddRead(net::MockRead(kReadData));
+ DoOpenClosed();
+ ExpectReadSignal();
+
+ EXPECT_TRUE(chrome_async_socket_->StartTls("fakedomain.com"));
+ message_loop_.RunUntilIdle();
+ ExpectSSLConnectSignal();
+ ExpectNoSignal();
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_TLS_OPEN);
+
+ DoSSLCloseOpenedNoError();
+}
+
+TEST_F(ChromeAsyncSocketTest, DoubleSSLConnect) {
+ EXPECT_DEBUG_DEATH({
+ async_socket_data_provider_.AddRead(net::MockRead(kReadData));
+ DoOpenClosed();
+ ExpectReadSignal();
+
+ EXPECT_TRUE(chrome_async_socket_->StartTls("fakedomain.com"));
+ message_loop_.RunUntilIdle();
+ ExpectSSLConnectSignal();
+ ExpectNoSignal();
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_TLS_OPEN);
+
+ EXPECT_FALSE(chrome_async_socket_->StartTls("fakedomain.com"));
+
+ DoSSLCloseOpened(
+ SignalSocketState(SIGNAL_CLOSE,
+ ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::ERROR_WRONGSTATE,
+ net::OK));
+ }, "wrong state");
+}
+
+TEST_F(ChromeAsyncSocketTest, 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(chrome_async_socket_->StartTls("fakedomain.com"));
+ message_loop_.RunUntilIdle();
+ ExpectSignalSocketState(
+ SignalSocketState(
+ SIGNAL_CLOSE, ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::ERROR_WINSOCK,
+ net::ERR_CERT_COMMON_NAME_INVALID));
+
+ EXPECT_TRUE(chrome_async_socket_->Close());
+ ExpectClosed();
+}
+
+TEST_F(ChromeAsyncSocketTest, ReadDuringSSLConnecting) {
+ async_socket_data_provider_.AddRead(net::MockRead(kReadData));
+ DoOpenClosed();
+ ExpectReadSignal();
+ EXPECT_EQ(kReadData, DrainRead(1));
+
+ EXPECT_TRUE(chrome_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(chrome_async_socket_->Read(buf, sizeof(buf), &len_read));
+ EXPECT_EQ(0U, len_read);
+
+ message_loop_.RunUntilIdle();
+ ExpectSSLConnectSignal();
+ ExpectSSLReadSignal();
+ ExpectNoSignal();
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_TLS_OPEN);
+
+ len_read = 10000U;
+ EXPECT_TRUE(chrome_async_socket_->Read(buf, sizeof(buf), &len_read));
+ EXPECT_EQ(kReadData, std::string(buf, len_read));
+
+ DoSSLCloseOpenedNoError();
+}
+
+TEST_F(ChromeAsyncSocketTest, WriteDuringSSLConnecting) {
+ async_socket_data_provider_.AddRead(net::MockRead(kReadData));
+ DoOpenClosed();
+ ExpectReadSignal();
+
+ EXPECT_TRUE(chrome_async_socket_->StartTls("fakedomain.com"));
+ ExpectNoSignal();
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_TLS_CONNECTING);
+
+ async_socket_data_provider_.AddWrite(
+ net::MockWrite(net::ASYNC, kWriteData, 3));
+
+ // Shouldn't do anything.
+ EXPECT_TRUE(chrome_async_socket_->Write(kWriteData, 3));
+
+ // TODO(akalin): Figure out how to test that the write happens
+ // *after* the SSL connect.
+
+ message_loop_.RunUntilIdle();
+ ExpectSSLConnectSignal();
+ ExpectNoSignal();
+
+ message_loop_.RunUntilIdle();
+
+ DoSSLCloseOpenedNoError();
+}
+
+TEST_F(ChromeAsyncSocketTest, SSLConnectDuringPendingRead) {
+ EXPECT_DEBUG_DEATH({
+ DoOpenClosed();
+
+ EXPECT_FALSE(chrome_async_socket_->StartTls("fakedomain.com"));
+
+ DoCloseOpened(
+ SignalSocketState(SIGNAL_CLOSE,
+ ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::ERROR_WRONGSTATE,
+ net::OK));
+ }, "wrong state");
+}
+
+TEST_F(ChromeAsyncSocketTest, SSLConnectDuringPostedWrite) {
+ EXPECT_DEBUG_DEATH({
+ DoOpenClosed();
+
+ async_socket_data_provider_.AddWrite(
+ net::MockWrite(net::ASYNC, kWriteData, 3));
+ EXPECT_TRUE(chrome_async_socket_->Write(kWriteData, 3));
+
+ EXPECT_FALSE(chrome_async_socket_->StartTls("fakedomain.com"));
+
+ message_loop_.RunUntilIdle();
+
+ DoCloseOpened(
+ SignalSocketState(SIGNAL_CLOSE,
+ ChromeAsyncSocket::STATE_CLOSED,
+ ChromeAsyncSocket::ERROR_WRONGSTATE,
+ net::OK));
+ }, "wrong state");
+}
+
+// After this we can assume SSL connect works as expected.
+
+TEST_F(ChromeAsyncSocketTest, SSLRead) {
+ DoSSLOpenClosed();
+ async_socket_data_provider_.AddRead(net::MockRead(kReadData));
+ message_loop_.RunUntilIdle();
+
+ ExpectSSLReadSignal();
+ ExpectNoSignal();
+
+ EXPECT_EQ(kReadData, DrainRead(1));
+
+ message_loop_.RunUntilIdle();
+
+ DoSSLCloseOpenedNoError();
+}
+
+TEST_F(ChromeAsyncSocketTest, 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(chrome_async_socket_->Write(kWriteData, 3));
+ message_loop_.RunUntilIdle();
+ EXPECT_TRUE(chrome_async_socket_->Write(kWriteData + 3, 5));
+ message_loop_.RunUntilIdle();
+ EXPECT_TRUE(chrome_async_socket_->Write(kWriteData + 8,
+ arraysize(kWriteData) - 8));
+ message_loop_.RunUntilIdle();
+
+ ExpectNoSignal();
+
+ DoSSLCloseOpenedNoError();
+}
+
+TEST_F(ChromeAsyncSocketTest, 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(chrome_async_socket_->Write(kWriteData, 3));
+ message_loop_.RunUntilIdle();
+ EXPECT_TRUE(chrome_async_socket_->Write(kWriteData + 3, 5));
+ message_loop_.RunUntilIdle();
+ EXPECT_TRUE(chrome_async_socket_->Write(kWriteData + 8,
+ arraysize(kWriteData) - 8));
+ message_loop_.RunUntilIdle();
+
+ ExpectNoSignal();
+
+ DoSSLCloseOpenedNoError();
+}
+
+} // namespace
+
+} // namespace jingle_glue