Index: chrome/browser/sync/tools/chrome_async_socket_unittest.cc |
diff --git a/chrome/browser/sync/tools/chrome_async_socket_unittest.cc b/chrome/browser/sync/tools/chrome_async_socket_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..225a215af52b02cda10e5ad600e8534ed02f0cf6 |
--- /dev/null |
+++ b/chrome/browser/sync/tools/chrome_async_socket_unittest.cc |
@@ -0,0 +1,981 @@ |
+// Copyright (c) 2010 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 "chrome/browser/sync/tools/chrome_async_socket.h" |
+ |
+#include <deque> |
+#include <string> |
+ |
+#include "base/basictypes.h" |
+#include "base/logging.h" |
+#include "base/message_loop.h" |
+#include "net/base/ssl_config_service.h" |
+#include "net/base/capturing_net_log.h" |
+#include "net/base/net_errors.h" |
+#include "net/socket/socket_test_util.h" |
+#include "talk/base/sigslot.h" |
+#include "talk/base/socketaddress.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace sync_tools { |
+ |
+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() { |
+ if (reads_.empty()) { |
+ DCHECK(!has_pending_read_); |
+ has_pending_read_ = true; |
+ const net::MockRead pending_read(false, 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) { |
+ DCHECK(!writes_.empty()); |
+ net::MockWrite mock_write = writes_.front(); |
+ writes_.pop_front(); |
+ if (mock_write.result != net::OK) { |
+ return net::MockWriteResult(mock_write.async, 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(false, net::ERR_UNEXPECTED); |
+ } |
+ return net::MockWriteResult(mock_write.async, data.size()); |
+ } |
+ |
+ // We ignore resets so we can pre-load the socket data provider with |
+ // read/write events. |
+ virtual void Reset() {} |
+ |
+ // 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 ChromeAsyncSocketTest |
+ : public testing::Test, |
+ public sigslot::has_slots<> { |
+ protected: |
+ // TODO(akalin): test SSL states other than connection success. |
+ ChromeAsyncSocketTest() |
+ : ssl_socket_data_provider_(true, net::OK), |
+ capturing_net_log_(net::CapturingNetLog::kUnbounded), |
+ chrome_async_socket_(&mock_client_socket_factory_, |
+ ssl_config_, 14, 20, &capturing_net_log_), |
+ addr_(0xaabbccdd, 35) {} |
+ |
+ virtual ~ChromeAsyncSocketTest() {} |
+ |
+ virtual void SetUp() { |
+ mock_client_socket_factory_.AddSocketDataProvider( |
+ &async_socket_data_provider_); |
+ mock_client_socket_factory_.AddSSLSocketDataProvider( |
+ &ssl_socket_data_provider_); |
+ |
+ 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_.RunAllPending(); |
+ ExpectClosed(); |
+ ExpectNoSignal(); |
+ chrome_async_socket_.SignalConnected.disconnect(this); |
+ chrome_async_socket_.SignalSSLConnected.disconnect(this); |
+ chrome_async_socket_.SignalClosed.disconnect(this); |
+ chrome_async_socket_.SignalRead.disconnect(this); |
+ chrome_async_socket_.SignalError.disconnect(this); |
+ } |
+ |
+ 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_)); |
+ } |
+ |
+ 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(false, net::OK)); |
+ EXPECT_TRUE(chrome_async_socket_.Connect(addr_)); |
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_CONNECTING); |
+ |
+ message_loop_.RunAllPending(); |
+ // 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_.RunAllPending(); |
+ 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_array<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 == 0) { |
+ break; |
+ } |
+ read.append(buf.get(), len_read); |
+ } |
+ return read; |
+ } |
+ |
+ // ChromeAsyncSocket expects a message loop. |
+ MessageLoop message_loop_; |
+ |
+ net::MockClientSocketFactory mock_client_socket_factory_; |
+ AsyncSocketDataProvider async_socket_data_provider_; |
+ net::SSLSocketDataProvider ssl_socket_data_provider_; |
+ |
+ net::CapturingNetLog capturing_net_log_; |
+ net::SSLConfig ssl_config_; |
+ 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, UnresolvedConnect) { |
+ const talk_base::SocketAddress unresolved_addr(0, 0); |
+ EXPECT_FALSE(chrome_async_socket_.Connect(unresolved_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_.RunAllPending(); |
+} |
+ |
+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(true, net::OK)); |
+ EXPECT_TRUE(chrome_async_socket_.Connect(addr_)); |
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_CONNECTING); |
+ ExpectNoSignal(); |
+ |
+ message_loop_.RunAllPending(); |
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_OPEN); |
+ ExpectSignalSocketState( |
+ SignalSocketState::NoError( |
+ SIGNAL_CONNECT, ChromeAsyncSocket::STATE_OPEN)); |
+ ExpectNoSignal(); |
+ |
+ message_loop_.RunAllPending(); |
+ |
+ 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(true, net::OK)); |
+ EXPECT_TRUE(chrome_async_socket_.Connect(addr_)); |
+ |
+ message_loop_.RunAllPending(); |
+ ExpectSignalSocketState( |
+ SignalSocketState::NoError( |
+ SIGNAL_CONNECT, ChromeAsyncSocket::STATE_OPEN)); |
+ |
+ DoCloseOpenedNoError(); |
+ |
+ message_loop_.RunAllPending(); |
+} |
+ |
+TEST_F(ChromeAsyncSocketTest, PendingConnectError) { |
+ async_socket_data_provider_.set_connect_data( |
+ net::MockConnect(true, net::ERR_TIMED_OUT)); |
+ EXPECT_TRUE(chrome_async_socket_.Connect(addr_)); |
+ |
+ message_loop_.RunAllPending(); |
+ |
+ 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 = 10000; |
+ EXPECT_TRUE(chrome_async_socket_.Read(buf, sizeof(buf), &len_read)); |
+ EXPECT_EQ(0, len_read); |
+ |
+ DoCloseOpenedNoError(); |
+} |
+ |
+TEST_F(ChromeAsyncSocketTest, WrongRead) { |
+ EXPECT_DEBUG_DEATH({ |
+ 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()); |
+ }, "non-open"); |
+} |
+ |
+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_.RunAllPending(); |
+ |
+ DoCloseOpenedNoError(); |
+} |
+ |
+TEST_F(ChromeAsyncSocketTest, ReadTwice) { |
+ async_socket_data_provider_.AddRead(net::MockRead(kReadData)); |
+ DoOpenClosed(); |
+ |
+ ExpectReadSignal(); |
+ ExpectNoSignal(); |
+ |
+ EXPECT_EQ(kReadData, DrainRead(1)); |
+ |
+ message_loop_.RunAllPending(); |
+ |
+ 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_.RunAllPending(); |
+ |
+ async_socket_data_provider_.AddRead( |
+ net::MockRead(false, 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_.RunAllPending(); |
+ |
+ 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(true, 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(false, kWriteData, 3)); |
+ async_socket_data_provider_.AddWrite( |
+ net::MockWrite(false, kWriteData + 3, 5)); |
+ async_socket_data_provider_.AddWrite( |
+ net::MockWrite(false, kWriteData + 8, arraysize(kWriteData) - 8)); |
+ DoOpenClosed(); |
+ |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData, 3)); |
+ message_loop_.RunAllPending(); |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData + 3, 5)); |
+ message_loop_.RunAllPending(); |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData + 8, |
+ arraysize(kWriteData) - 8)); |
+ message_loop_.RunAllPending(); |
+ |
+ ExpectNoSignal(); |
+ |
+ DoCloseOpenedNoError(); |
+} |
+ |
+TEST_F(ChromeAsyncSocketTest, AsyncWrite) { |
+ DoOpenClosed(); |
+ |
+ async_socket_data_provider_.AddWrite( |
+ net::MockWrite(true, kWriteData, 3)); |
+ async_socket_data_provider_.AddWrite( |
+ net::MockWrite(true, kWriteData + 3, 5)); |
+ async_socket_data_provider_.AddWrite( |
+ net::MockWrite(true, kWriteData + 8, arraysize(kWriteData) - 8)); |
+ |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData, 3)); |
+ message_loop_.RunAllPending(); |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData + 3, 5)); |
+ message_loop_.RunAllPending(); |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData + 8, |
+ arraysize(kWriteData) - 8)); |
+ message_loop_.RunAllPending(); |
+ |
+ ExpectNoSignal(); |
+ |
+ DoCloseOpenedNoError(); |
+} |
+ |
+TEST_F(ChromeAsyncSocketTest, AsyncWriteError) { |
+ DoOpenClosed(); |
+ |
+ async_socket_data_provider_.AddWrite( |
+ net::MockWrite(true, kWriteData, 3)); |
+ async_socket_data_provider_.AddWrite( |
+ net::MockWrite(true, kWriteData + 3, 5)); |
+ async_socket_data_provider_.AddWrite( |
+ net::MockWrite(true, net::ERR_TIMED_OUT)); |
+ |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData, 3)); |
+ message_loop_.RunAllPending(); |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData + 3, 5)); |
+ message_loop_.RunAllPending(); |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData + 8, |
+ arraysize(kWriteData) - 8)); |
+ message_loop_.RunAllPending(); |
+ |
+ 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_.RunAllPending(); |
+ 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_.RunAllPending(); |
+ 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, 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 = 10000; |
+ EXPECT_TRUE(chrome_async_socket_.Read(buf, sizeof(buf), &len_read)); |
+ EXPECT_EQ(0, len_read); |
+ |
+ message_loop_.RunAllPending(); |
+ ExpectSSLConnectSignal(); |
+ ExpectSSLReadSignal(); |
+ ExpectNoSignal(); |
+ ExpectNonErrorState(ChromeAsyncSocket::STATE_TLS_OPEN); |
+ |
+ len_read = 10000; |
+ 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(true, 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_.RunAllPending(); |
+ ExpectSSLConnectSignal(); |
+ ExpectNoSignal(); |
+ |
+ message_loop_.RunAllPending(); |
+ |
+ 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(true, kWriteData, 3)); |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData, 3)); |
+ |
+ EXPECT_FALSE(chrome_async_socket_.StartTls("fakedomain.com")); |
+ |
+ message_loop_.RunAllPending(); |
+ |
+ 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_.RunAllPending(); |
+ |
+ ExpectSSLReadSignal(); |
+ ExpectNoSignal(); |
+ |
+ EXPECT_EQ(kReadData, DrainRead(1)); |
+ |
+ message_loop_.RunAllPending(); |
+ |
+ DoSSLCloseOpenedNoError(); |
+} |
+ |
+TEST_F(ChromeAsyncSocketTest, SSLSyncWrite) { |
+ async_socket_data_provider_.AddWrite( |
+ net::MockWrite(false, kWriteData, 3)); |
+ async_socket_data_provider_.AddWrite( |
+ net::MockWrite(false, kWriteData + 3, 5)); |
+ async_socket_data_provider_.AddWrite( |
+ net::MockWrite(false, kWriteData + 8, arraysize(kWriteData) - 8)); |
+ DoSSLOpenClosed(); |
+ |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData, 3)); |
+ message_loop_.RunAllPending(); |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData + 3, 5)); |
+ message_loop_.RunAllPending(); |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData + 8, |
+ arraysize(kWriteData) - 8)); |
+ message_loop_.RunAllPending(); |
+ |
+ ExpectNoSignal(); |
+ |
+ DoSSLCloseOpenedNoError(); |
+} |
+ |
+TEST_F(ChromeAsyncSocketTest, SSLAsyncWrite) { |
+ DoSSLOpenClosed(); |
+ |
+ async_socket_data_provider_.AddWrite( |
+ net::MockWrite(true, kWriteData, 3)); |
+ async_socket_data_provider_.AddWrite( |
+ net::MockWrite(true, kWriteData + 3, 5)); |
+ async_socket_data_provider_.AddWrite( |
+ net::MockWrite(true, kWriteData + 8, arraysize(kWriteData) - 8)); |
+ |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData, 3)); |
+ message_loop_.RunAllPending(); |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData + 3, 5)); |
+ message_loop_.RunAllPending(); |
+ EXPECT_TRUE(chrome_async_socket_.Write(kWriteData + 8, |
+ arraysize(kWriteData) - 8)); |
+ message_loop_.RunAllPending(); |
+ |
+ ExpectNoSignal(); |
+ |
+ DoSSLCloseOpenedNoError(); |
+} |
+ |
+} // namespace |
+ |
+} // namespace sync_tools |