Index: chrome/browser/extensions/api/cast_channel/cast_socket_unittest.cc |
=================================================================== |
--- chrome/browser/extensions/api/cast_channel/cast_socket_unittest.cc (revision 243975) |
+++ chrome/browser/extensions/api/cast_channel/cast_socket_unittest.cc (working copy) |
@@ -4,6 +4,10 @@ |
#include "chrome/browser/extensions/api/cast_channel/cast_socket.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/run_loop.h" |
+#include "base/strings/string_number_conversions.h" |
+#include "base/sys_byteorder.h" |
#include "chrome/browser/extensions/api/cast_channel/cast_channel.pb.h" |
#include "chrome/browser/extensions/api/cast_channel/cast_message_util.h" |
#include "net/base/address_list.h" |
@@ -24,10 +28,49 @@ |
using ::testing::Return; |
using ::testing::SaveArg; |
+namespace { |
+const char* kTestData[4] = { |
+ "Hello, World!", |
+ "Goodbye, World!", |
+ "Hello, Sky!", |
+ "Goodbye, Volcano!", |
+}; |
+} // namespace |
+ |
namespace extensions { |
namespace api { |
namespace cast_channel { |
+// Fills in |message| with a string message. |
+static void CreateStringMessage(const std::string& namespace_, |
+ const std::string& source_id, |
+ const std::string& destination_id, |
+ const std::string& data, |
+ MessageInfo* message) { |
+ message->namespace_ = namespace_; |
+ message->source_id = source_id; |
+ message->destination_id = destination_id; |
+ message->data.reset(new base::StringValue(data)); |
+} |
+ |
+// Fills in |message| with a binary message. |
+static void CreateBinaryMessage(const std::string& namespace_, |
+ const std::string& source_id, |
+ const std::string& destination_id, |
+ const std::string& data, |
+ MessageInfo* message) { |
+ message->namespace_ = namespace_; |
+ message->source_id = source_id; |
+ message->destination_id = destination_id; |
+ message->data.reset(base::BinaryValue::CreateWithCopiedBuffer( |
+ data.c_str(), data.size())); |
+} |
+ |
+// Returns the size of the body (in bytes) of the given serialized message. |
+static size_t ComputeBodySize(const std::string& msg) { |
+ return msg.length() - kMessageHeaderSize; |
+} |
+ |
class MockCastSocketDelegate : public CastSocket::Delegate { |
public: |
MOCK_METHOD2(OnError, void(const CastSocket* socket, |
@@ -36,37 +79,45 @@ |
const MessageInfo& message)); |
}; |
-class MockTCPClientSocket : public net::TCPClientSocket { |
+class MockTCPSocket : public net::TCPClientSocket { |
public: |
- explicit MockTCPClientSocket() : |
- TCPClientSocket(net::AddressList(), NULL, net::NetLog::Source()) { } |
- virtual ~MockTCPClientSocket() { } |
+ explicit MockTCPSocket(const net::MockConnect& connect_data) : |
+ TCPClientSocket(net::AddressList(), NULL, net::NetLog::Source()), |
+ connect_data_(connect_data) { } |
- MOCK_METHOD1(Connect, int(const net::CompletionCallback& callback)); |
- MOCK_METHOD2(SetKeepAlive, bool(bool, int)); |
- MOCK_METHOD1(SetNoDelay, bool(bool)); |
- MOCK_METHOD3(Read, int(net::IOBuffer* buf, int buf_len, |
- const net::CompletionCallback& callback)); |
- MOCK_METHOD3(Write, int(net::IOBuffer* buf, int buf_len, |
- const net::CompletionCallback& callback)); |
- MOCK_METHOD0(Disconnect, void()); |
-}; |
+ virtual int Connect(const net::CompletionCallback& callback) OVERRIDE { |
+ if (connect_data_.mode == net::ASYNC) { |
+ CHECK_NE(connect_data_.result, net::ERR_IO_PENDING); |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, |
+ base::Bind(callback, connect_data_.result)); |
+ return net::ERR_IO_PENDING; |
+ } else { |
+ return connect_data_.result; |
+ } |
+ } |
-class MockSSLClientSocket : public net::MockClientSocket { |
- public: |
- MockSSLClientSocket() : MockClientSocket(net::BoundNetLog()) { } |
- virtual ~MockSSLClientSocket() { } |
+ virtual bool SetKeepAlive(bool enable, int delay) OVERRIDE { |
+ // Always return true in tests |
+ return true; |
+ } |
- MOCK_METHOD1(Connect, int(const net::CompletionCallback& callback)); |
- MOCK_METHOD3(Read, int(net::IOBuffer* buf, int buf_len, |
- const net::CompletionCallback& callback)); |
- MOCK_METHOD3(Write, int(net::IOBuffer* buf, int buf_len, |
- const net::CompletionCallback& callback)); |
- MOCK_METHOD0(Disconnect, void()); |
- MOCK_CONST_METHOD0(WasEverUsed, bool()); |
- MOCK_CONST_METHOD0(UsingTCPFastOpen, bool()); |
- MOCK_CONST_METHOD0(WasNpnNegotiated, bool()); |
- MOCK_METHOD1(GetSSLInfo, bool(net::SSLInfo*)); |
+ virtual bool SetNoDelay(bool no_delay) OVERRIDE { |
+ // Always return true in tests |
+ return true; |
+ } |
+ |
+ MOCK_METHOD3(Read, |
+ int(net::IOBuffer*, int, const net::CompletionCallback&)); |
+ MOCK_METHOD3(Write, |
+ int(net::IOBuffer*, int, const net::CompletionCallback&)); |
+ |
+ virtual void Disconnect() OVERRIDE { |
+ // Do nothing in tests |
+ } |
+ |
+ private: |
+ net::MockConnect connect_data_; |
}; |
class CompleteHandler { |
@@ -95,106 +146,140 @@ |
explicit TestCastSocket(MockCastSocketDelegate* delegate, |
const std::string& url) : |
- CastSocket("abcdefg", GURL(url), delegate, |
- &capturing_net_log_), |
- mock_tcp_socket_(new MockTCPClientSocket()), |
- mock_ssl_socket_(new MockSSLClientSocket()), |
- owns_tcp_socket_(true), |
- owns_ssl_socket_(true), |
- extract_cert_result_(true), |
- send_auth_challenge_result_(net::ERR_IO_PENDING), |
- read_auth_challenge_reply_result_(net::ERR_IO_PENDING), |
- challenge_reply_result_(true) { |
+ CastSocket("abcdefg", GURL(url), delegate, |
+ &capturing_net_log_), |
+ ip_(CreateIPEndPoint()), |
+ connect_index_(0), |
+ extract_cert_result_(true), |
+ verify_challenge_result_(true) { |
} |
+ static net::IPEndPoint CreateIPEndPoint() { |
+ net::IPAddressNumber number; |
+ number.push_back(192); |
+ number.push_back(0); |
+ number.push_back(0); |
+ number.push_back(1); |
+ return net::IPEndPoint(number, 8009); |
+ } |
+ |
virtual ~TestCastSocket() { |
- if (owns_tcp_socket_) { |
- DCHECK(mock_tcp_socket_); |
- delete mock_tcp_socket_; |
- } |
- if (owns_ssl_socket_) { |
- DCHECK(mock_ssl_socket_); |
- delete mock_ssl_socket_; |
- } |
} |
- virtual void Close(const net::CompletionCallback& callback) OVERRIDE { |
- if (!owns_tcp_socket_) |
- mock_tcp_socket_ = NULL; |
- if (!owns_ssl_socket_) |
- mock_ssl_socket_ = NULL; |
- CastSocket::Close(callback); |
+ // Helpers to set mock results for various operations. |
+ void SetupTcp1Connect(net::IoMode mode, int result) { |
+ tcp_connect_data_[0].reset(new net::MockConnect(mode, result)); |
} |
+ void SetupSsl1Connect(net::IoMode mode, int result) { |
+ ssl_connect_data_[0].reset(new net::MockConnect(mode, result)); |
+ } |
+ void SetupTcp2Connect(net::IoMode mode, int result) { |
+ tcp_connect_data_[1].reset(new net::MockConnect(mode, result)); |
+ } |
+ void SetupSsl2Connect(net::IoMode mode, int result) { |
+ ssl_connect_data_[1].reset(new net::MockConnect(mode, result)); |
+ } |
+ void AddWriteResult(const net::MockWrite& write) { |
+ writes_.push_back(write); |
+ } |
+ void AddWriteResult(net::IoMode mode, int result) { |
+ AddWriteResult(net::MockWrite(mode, result)); |
+ } |
+ void AddWriteResultForMessage(net::IoMode mode, const std::string& msg) { |
+ AddWriteResult(mode, msg.size()); |
+ } |
+ void AddWriteResultForMessage(net::IoMode mode, |
+ const std::string& msg, |
+ size_t ch_size) { |
+ size_t msg_size = msg.size(); |
+ for (size_t offset = 0; offset < msg_size; offset += ch_size) { |
+ if (offset + ch_size > msg_size) |
+ ch_size = msg_size - offset; |
+ AddWriteResult(mode, ch_size); |
+ } |
+ } |
- void CreateNewSockets() { |
- owns_tcp_socket_ = true; |
- mock_tcp_socket_ = new MockTCPClientSocket(); |
- owns_ssl_socket_ = true; |
- mock_ssl_socket_ = new MockSSLClientSocket(); |
+ void AddReadResult(const net::MockRead& read) { |
+ reads_.push_back(read); |
} |
+ void AddReadResult(net::IoMode mode, int result) { |
+ AddReadResult(net::MockRead(mode, result)); |
+ } |
+ void AddReadResult(net::IoMode mode, const char* data, int data_len) { |
+ AddReadResult(net::MockRead(mode, data, data_len)); |
+ } |
+ void AddReadResultForMessage(net::IoMode mode, const std::string& msg) { |
+ size_t body_size = ComputeBodySize(msg); |
+ const char* data = msg.c_str(); |
+ AddReadResult(mode, data, kMessageHeaderSize); |
+ AddReadResult(mode, data + kMessageHeaderSize, body_size); |
+ } |
+ void AddReadResultForMessage(net::IoMode mode, |
+ const std::string& msg, |
+ size_t ch_size) { |
+ size_t msg_size = msg.size(); |
+ const char* data = msg.c_str(); |
+ for (size_t offset = 0; offset < msg_size; offset += ch_size) { |
+ if (offset + ch_size > msg_size) |
+ ch_size = msg_size - offset; |
+ AddReadResult(mode, data + offset, ch_size); |
+ } |
+ } |
void SetExtractCertResult(bool value) { |
extract_cert_result_ = value; |
} |
- |
- void SetSendAuthChallengeResult(int result) { |
- send_auth_challenge_result_ = result; |
+ void SetVerifyChallengeResult(bool value) { |
+ verify_challenge_result_ = value; |
} |
- void SetReadAuthChallengeReplyResult(int result) { |
- read_auth_challenge_reply_result_ = result; |
+ private: |
+ virtual scoped_ptr<net::TCPClientSocket> CreateTcpSocket() OVERRIDE { |
+ net::MockConnect* connect_data = tcp_connect_data_[connect_index_].get(); |
+ connect_data->peer_addr = ip_; |
+ return scoped_ptr<net::TCPClientSocket>(new MockTCPSocket(*connect_data)); |
} |
- void SetChallengeReplyResult(bool value) { |
- challenge_reply_result_ = value; |
- } |
+ virtual scoped_ptr<net::SSLClientSocket> CreateSslSocket( |
+ scoped_ptr<net::StreamSocket> socket) OVERRIDE { |
+ net::MockConnect* connect_data = ssl_connect_data_[connect_index_].get(); |
+ connect_data->peer_addr = ip_; |
+ ++connect_index_; |
- MockTCPClientSocket* mock_tcp_socket_; |
- MockSSLClientSocket* mock_ssl_socket_; |
- |
- protected: |
- virtual scoped_ptr<net::TCPClientSocket> CreateTcpSocket() OVERRIDE { |
- owns_tcp_socket_ = false; |
- return scoped_ptr<net::TCPClientSocket>(mock_tcp_socket_); |
+ ssl_data_.reset(new net::StaticSocketDataProvider( |
+ reads_.data(), reads_.size(), writes_.data(), writes_.size())); |
+ ssl_data_->set_connect_data(*connect_data); |
+ // NOTE: net::MockTCPClientSocket inherits from net::SSLClientSocket !! |
+ return scoped_ptr<net::SSLClientSocket>( |
+ new net::MockTCPClientSocket( |
+ net::AddressList(), &capturing_net_log_, ssl_data_.get())); |
} |
- virtual scoped_ptr<net::SSLClientSocket> CreateSslSocket() OVERRIDE { |
- owns_ssl_socket_ = false; |
- return scoped_ptr<net::SSLClientSocket>(mock_ssl_socket_); |
- } |
- |
virtual bool ExtractPeerCert(std::string* cert) OVERRIDE { |
if (extract_cert_result_) |
cert->assign("dummy_test_cert"); |
return extract_cert_result_; |
} |
- virtual int SendAuthChallenge() OVERRIDE { |
- return send_auth_challenge_result_; |
- } |
- |
- virtual int ReadAuthChallengeReply() OVERRIDE { |
- return read_auth_challenge_reply_result_; |
- } |
- |
virtual bool VerifyChallengeReply() OVERRIDE { |
- return challenge_reply_result_; |
+ return verify_challenge_result_; |
} |
- private: |
net::CapturingNetLog capturing_net_log_; |
- // Whether this object or the parent owns |mock_tcp_socket_|. |
- bool owns_tcp_socket_; |
- // Whether this object or the parent owns |mock_ssl_socket_|. |
- bool owns_ssl_socket_; |
+ net::IPEndPoint ip_; |
+ // Simulated connect data |
+ scoped_ptr<net::MockConnect> tcp_connect_data_[2]; |
+ scoped_ptr<net::MockConnect> ssl_connect_data_[2]; |
+ // Simulated read / write data |
+ std::vector<net::MockWrite> writes_; |
+ std::vector<net::MockRead> reads_; |
+ scoped_ptr<net::SocketDataProvider> ssl_data_; |
+ // Number of times Connect method is called |
+ size_t connect_index_; |
// Simulated result of peer cert extraction. |
bool extract_cert_result_; |
- // Simulated result to be returned by SendAuthChallenge. |
- int send_auth_challenge_result_; |
- // Simulated result to be returned by ReadAuthChallengeReply. |
- int read_auth_challenge_reply_result_; |
// Simulated result of verifying challenge reply. |
- bool challenge_reply_result_; |
+ bool verify_challenge_result_; |
}; |
class CastSocketTest : public testing::Test { |
@@ -203,11 +288,30 @@ |
virtual ~CastSocketTest() {} |
virtual void SetUp() OVERRIDE { |
- test_message_.namespace_ = "urn:test"; |
- test_message_.source_id = "1"; |
- test_message_.destination_id = "2"; |
- test_message_.data.reset(new base::StringValue("Hello, World!")); |
- ASSERT_TRUE(MessageInfoToCastMessage(test_message_, &test_proto_)); |
+ // Create a few test messages |
+ for (size_t i = 0; i < arraysize(test_messages_); i++) { |
+ CreateStringMessage("urn:cast", "1", "2", kTestData[i], |
+ &test_messages_[i]); |
+ ASSERT_TRUE(MessageInfoToCastMessage( |
+ test_messages_[i], &test_protos_[i])); |
+ ASSERT_TRUE(CastSocket::Serialize(test_protos_[i], &test_proto_strs_[i])); |
+ } |
+ |
+ // Create a test auth request. |
+ CastMessage request; |
+ CreateAuthChallengeMessage(&request); |
+ ASSERT_TRUE(CastSocket::Serialize(request, &auth_request_)); |
+ |
+ // Create a test auth reply. |
+ MessageInfo reply; |
+ CreateBinaryMessage("urn:x-cast:com.google.cast.tp.deviceauth", |
+ "sender-0", |
+ "receiver-0", |
+ "abcd", |
+ &reply); |
+ CastMessage reply_msg; |
+ ASSERT_TRUE(MessageInfoToCastMessage(reply, &reply_msg)); |
+ ASSERT_TRUE(CastSocket::Serialize(reply_msg, &auth_reply_)); |
} |
virtual void TearDown() OVERRIDE { |
@@ -224,85 +328,36 @@ |
socket_ = TestCastSocket::CreateSecure(&mock_delegate_); |
} |
- // Sets an expectation that TCPClientSocket::Connect is called and |
- // returns |result| and stores the callback passed to it in |callback|. |
- void ExpectTcpConnect(net::CompletionCallback* callback, int result) { |
- EXPECT_CALL(mock_tcp_socket(), Connect(A<const net::CompletionCallback&>())) |
- .Times(1) |
- .WillOnce(DoAll(SaveArg<0>(callback), Return(result))); |
- EXPECT_CALL(mock_tcp_socket(), SetKeepAlive(_, _)) |
- .WillOnce(Return(true)); |
- } |
- |
- // Same as ExpectTcpConnect but to return net::ERR_IO_PENDING. |
- void ExpectTcpConnectPending(net::CompletionCallback* callback) { |
- ExpectTcpConnect(callback, net::ERR_IO_PENDING); |
- } |
- |
- // Sets an expectation that SSLClientSocket::Connect is called and |
- // returns |result| and stores the callback passed to it in |callback|. |
- void ExpectSslConnect(net::CompletionCallback* callback, int result) { |
- EXPECT_CALL(mock_ssl_socket(), Connect(A<const net::CompletionCallback&>())) |
- .Times(1) |
- .WillOnce(DoAll(SaveArg<0>(callback), Return(result))); |
- } |
- |
- // Same as ExpectSslConnect but to return net::ERR_IO_PENDING. |
- void ExpectSslConnectPending(net::CompletionCallback* callback) { |
- ExpectSslConnect(callback, net::ERR_IO_PENDING); |
- } |
- |
- // Sets an expectation that SSLClientSocket::Read is called |times| number |
- // of times and returns net::ERR_IO_PENDING. |
- void ExpectSslRead(int times) { |
- EXPECT_CALL(mock_ssl_socket(), Read(A<net::IOBuffer*>(), |
- A<int>(), |
- A<const net::CompletionCallback&>())) |
- .Times(times) |
- .WillOnce(Return(net::ERR_IO_PENDING)); |
- } |
- |
// Sets up CastSocket::Connect to succeed. |
- // Connecting the socket also starts the read loop; we expect the call to |
- // Read(), but never fire the read callback. |
+ // Connecting the socket also starts the read loop; so we add a mock |
+ // read result that returns IO_PENDING and callback is never fired. |
void ConnectHelper() { |
- net::CompletionCallback connect_callback1; |
- net::CompletionCallback connect_callback2; |
+ socket_->SetupTcp1Connect(net::SYNCHRONOUS, net::OK); |
+ socket_->SetupSsl1Connect(net::SYNCHRONOUS, net::OK); |
+ socket_->AddReadResult(net::ASYNC, net::ERR_IO_PENDING); |
- ExpectTcpConnect(&connect_callback1, net::OK); |
- ExpectSslConnect(&connect_callback2, net::OK); |
EXPECT_CALL(handler_, OnConnectComplete(net::OK)); |
- ExpectSslRead(1); |
- |
socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
base::Unretained(&handler_))); |
- |
- EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
- EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
+ RunPendingTasks(); |
} |
protected: |
- MockTCPClientSocket& mock_tcp_socket() { |
- MockTCPClientSocket* mock_socket = socket_->mock_tcp_socket_; |
- DCHECK(mock_socket); |
- return *mock_socket; |
+ // Runs all pending tasks in the message loop. |
+ void RunPendingTasks() { |
+ base::RunLoop run_loop; |
+ run_loop.RunUntilIdle(); |
} |
- MockSSLClientSocket& mock_ssl_socket() { |
- MockSSLClientSocket* mock_socket = socket_->mock_ssl_socket_; |
- DCHECK(mock_socket); |
- return *mock_socket; |
- } |
- |
- void CallOnChallengeEvent(int result) { |
- socket_->OnChallengeEvent(result); |
- } |
- |
+ base::MessageLoop message_loop_; |
MockCastSocketDelegate mock_delegate_; |
scoped_ptr<TestCastSocket> socket_; |
CompleteHandler handler_; |
- MessageInfo test_message_; |
- CastMessage test_proto_; |
+ MessageInfo test_messages_[arraysize(kTestData)]; |
+ CastMessage test_protos_[arraysize(kTestData)]; |
+ std::string test_proto_strs_[arraysize(kTestData)]; |
+ std::string auth_request_; |
+ std::string auth_reply_; |
}; |
// Tests URL parsing and validation. |
@@ -335,6 +390,8 @@ |
TEST_F(CastSocketTest, TestConnectAndClose) { |
CreateCastSocket(); |
ConnectHelper(); |
+ EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
EXPECT_CALL(handler_, OnCloseComplete(net::OK)); |
socket_->Close(base::Bind(&CompleteHandler::OnCloseComplete, |
@@ -348,19 +405,14 @@ |
// - SSL connection succeeds (async) |
TEST_F(CastSocketTest, TestConnect) { |
CreateCastSocket(); |
+ socket_->SetupTcp1Connect(net::ASYNC, net::OK); |
+ socket_->SetupSsl1Connect(net::ASYNC, net::OK); |
+ socket_->AddReadResult(net::ASYNC, net::ERR_IO_PENDING); |
- net::CompletionCallback connect_callback1; |
- net::CompletionCallback connect_callback2; |
- |
- ExpectTcpConnectPending(&connect_callback1); |
- ExpectSslConnectPending(&connect_callback2); |
EXPECT_CALL(handler_, OnConnectComplete(net::OK)); |
- ExpectSslRead(1); |
- |
socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
base::Unretained(&handler_))); |
- connect_callback1.Run(net::OK); |
- connect_callback2.Run(net::OK); |
+ RunPendingTasks(); |
EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
@@ -372,37 +424,19 @@ |
// - Cert is extracted successfully |
// - Second TCP connection succeeds (async) |
// - Second SSL connection succeeds (async) |
-TEST_F(CastSocketTest, TestTwoStepConnect) { |
+TEST_F(CastSocketTest, TestConnectTwoStep) { |
CreateCastSocket(); |
+ socket_->SetupTcp1Connect(net::ASYNC, net::OK); |
+ socket_->SetupSsl1Connect(net::ASYNC, net::ERR_CERT_AUTHORITY_INVALID); |
+ socket_->SetupTcp2Connect(net::ASYNC, net::OK); |
+ socket_->SetupSsl2Connect(net::ASYNC, net::OK); |
+ socket_->AddReadResult(net::ASYNC, net::ERR_IO_PENDING); |
- // Expectations for the initial connect call |
- net::CompletionCallback tcp_connect_callback1; |
- net::CompletionCallback ssl_connect_callback1; |
- |
- ExpectTcpConnectPending(&tcp_connect_callback1); |
- ExpectSslConnectPending(&ssl_connect_callback1); |
- |
- // Start connect flow |
+ EXPECT_CALL(handler_, OnConnectComplete(net::OK)); |
socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
base::Unretained(&handler_))); |
- tcp_connect_callback1.Run(net::OK); |
+ RunPendingTasks(); |
- // Expectations for the second connect call |
- socket_->CreateNewSockets(); |
- net::CompletionCallback tcp_connect_callback2; |
- net::CompletionCallback ssl_connect_callback2; |
- ExpectTcpConnectPending(&tcp_connect_callback2); |
- ExpectSslConnectPending(&ssl_connect_callback2); |
- EXPECT_CALL(handler_, OnConnectComplete(net::OK)); |
- ExpectSslRead(1); |
- |
- // Trigger callbacks for the first connect |
- ssl_connect_callback1.Run(net::ERR_CERT_AUTHORITY_INVALID); |
- |
- // Trigger callbacks for the second connect |
- tcp_connect_callback2.Run(net::OK); |
- ssl_connect_callback2.Run(net::OK); |
- |
EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
} |
@@ -414,377 +448,576 @@ |
// - Second TCP connection succeeds (async) |
// - Second SSL connection fails (async) |
// - The flow should NOT be tried again |
-TEST_F(CastSocketTest, TestMaxTwoConnectAttempts) { |
+TEST_F(CastSocketTest, TestConnectMaxTwoAttempts) { |
CreateCastSocket(); |
+ socket_->SetupTcp1Connect(net::ASYNC, net::OK); |
+ socket_->SetupSsl1Connect(net::ASYNC, net::ERR_CERT_AUTHORITY_INVALID); |
+ socket_->SetupTcp2Connect(net::ASYNC, net::OK); |
+ socket_->SetupSsl2Connect(net::ASYNC, net::ERR_CERT_AUTHORITY_INVALID); |
- net::CompletionCallback tcp_connect_callback1; |
- net::CompletionCallback ssl_connect_callback1; |
+ EXPECT_CALL(handler_, OnConnectComplete(net::ERR_CERT_AUTHORITY_INVALID)); |
+ socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
+ base::Unretained(&handler_))); |
+ RunPendingTasks(); |
- // Expectations for the initial connect call |
- ExpectTcpConnectPending(&tcp_connect_callback1); |
- ExpectSslConnectPending(&ssl_connect_callback1); |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_ERROR, socket_->error_state()); |
+} |
- // Start connect flow |
+// Tests that the following connection flow works: |
+// - TCP connection succeeds (async) |
+// - SSL connection fails with cert error (async) |
+// - Cert is extracted successfully |
+// - Second TCP connection succeeds (async) |
+// - Second SSL connection succeeds (async) |
+// - Challenge request is sent (async) |
+// - Challenge response is received (async) |
+// - Credentials are verified successfuly |
+TEST_F(CastSocketTest, TestConnectFullSecureFlowAsync) { |
+ CreateCastSocketSecure(); |
+ |
+ socket_->SetupTcp1Connect(net::ASYNC, net::OK); |
+ socket_->SetupSsl1Connect(net::ASYNC, net::ERR_CERT_AUTHORITY_INVALID); |
+ socket_->SetupTcp2Connect(net::ASYNC, net::OK); |
+ socket_->SetupSsl2Connect(net::ASYNC, net::OK); |
+ socket_->AddWriteResultForMessage(net::ASYNC, auth_request_); |
+ socket_->AddReadResultForMessage(net::ASYNC, auth_reply_); |
+ socket_->AddReadResult(net::ASYNC, net::ERR_IO_PENDING); |
+ |
+ EXPECT_CALL(handler_, OnConnectComplete(net::OK)); |
socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
base::Unretained(&handler_))); |
- tcp_connect_callback1.Run(net::OK); |
+ RunPendingTasks(); |
- socket_->CreateNewSockets(); |
- net::CompletionCallback tcp_connect_callback2; |
- net::CompletionCallback ssl_connect_callback2; |
+ EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
+} |
- // Expectations for the second connect call |
- ExpectTcpConnectPending(&tcp_connect_callback2); |
- ExpectSslConnectPending(&ssl_connect_callback2); |
- EXPECT_CALL(handler_, OnConnectComplete(net::ERR_CERT_AUTHORITY_INVALID)); |
+// Same as TestFullSecureConnectionFlowAsync, but operations are synchronous. |
+TEST_F(CastSocketTest, TestConnectFullSecureFlowSync) { |
+ CreateCastSocketSecure(); |
- // Trigger callbacks for the first connect |
- ssl_connect_callback1.Run(net::ERR_CERT_AUTHORITY_INVALID); |
+ socket_->SetupTcp1Connect(net::SYNCHRONOUS, net::OK); |
+ socket_->SetupSsl1Connect(net::SYNCHRONOUS, net::ERR_CERT_AUTHORITY_INVALID); |
+ socket_->SetupTcp2Connect(net::SYNCHRONOUS, net::OK); |
+ socket_->SetupSsl2Connect(net::SYNCHRONOUS, net::OK); |
+ socket_->AddWriteResultForMessage(net::SYNCHRONOUS, auth_request_); |
+ socket_->AddReadResultForMessage(net::SYNCHRONOUS, auth_reply_); |
+ socket_->AddReadResult(net::ASYNC, net::ERR_IO_PENDING); |
- // Trigger callbacks for the second connect |
- tcp_connect_callback2.Run(net::OK); |
- ssl_connect_callback2.Run(net::ERR_CERT_AUTHORITY_INVALID); |
+ EXPECT_CALL(handler_, OnConnectComplete(net::OK)); |
+ socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
+ base::Unretained(&handler_))); |
+ RunPendingTasks(); |
+ EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
+} |
+ |
+// Test connection error - TCP connect fails (async) |
+TEST_F(CastSocketTest, TestConnectTcpConnectErrorAsync) { |
+ CreateCastSocketSecure(); |
+ |
+ socket_->SetupTcp1Connect(net::ASYNC, net::ERR_FAILED); |
+ |
+ EXPECT_CALL(handler_, OnConnectComplete(net::ERR_FAILED)); |
+ socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
+ base::Unretained(&handler_))); |
+ RunPendingTasks(); |
+ |
EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_ERROR, socket_->error_state()); |
} |
-// Test that when cert extraction fails the connection flow stops. |
-TEST_F(CastSocketTest, TestCertExtractionFailure) { |
- CreateCastSocket(); |
+// Test connection error - TCP connect fails (sync) |
+TEST_F(CastSocketTest, TestConnectTcpConnectErrorSync) { |
+ CreateCastSocketSecure(); |
- net::CompletionCallback connect_callback1; |
- net::CompletionCallback connect_callback2; |
+ socket_->SetupTcp1Connect(net::SYNCHRONOUS, net::ERR_FAILED); |
- ExpectTcpConnectPending(&connect_callback1); |
- ExpectSslConnectPending(&connect_callback2); |
+ EXPECT_CALL(handler_, OnConnectComplete(net::ERR_FAILED)); |
+ socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
+ base::Unretained(&handler_))); |
+ RunPendingTasks(); |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_ERROR, socket_->error_state()); |
+} |
+ |
+// Test connection error - SSL connect fails (async) |
+TEST_F(CastSocketTest, TestConnectSslConnectErrorAsync) { |
+ CreateCastSocketSecure(); |
+ |
+ socket_->SetupTcp1Connect(net::SYNCHRONOUS, net::OK); |
+ socket_->SetupSsl1Connect(net::SYNCHRONOUS, net::ERR_FAILED); |
+ |
+ EXPECT_CALL(handler_, OnConnectComplete(net::ERR_FAILED)); |
socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
base::Unretained(&handler_))); |
- connect_callback1.Run(net::OK); |
+ RunPendingTasks(); |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_ERROR, socket_->error_state()); |
+} |
+ |
+// Test connection error - SSL connect fails (async) |
+TEST_F(CastSocketTest, TestConnectSslConnectErrorSync) { |
+ CreateCastSocketSecure(); |
+ |
+ socket_->SetupTcp1Connect(net::SYNCHRONOUS, net::OK); |
+ socket_->SetupSsl1Connect(net::ASYNC, net::ERR_FAILED); |
+ |
+ EXPECT_CALL(handler_, OnConnectComplete(net::ERR_FAILED)); |
+ socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
+ base::Unretained(&handler_))); |
+ RunPendingTasks(); |
+ |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_ERROR, socket_->error_state()); |
+} |
+ |
+// Test connection error - cert extraction error (async) |
+TEST_F(CastSocketTest, TestConnectCertExtractionErrorAsync) { |
+ CreateCastSocket(); |
+ socket_->SetupTcp1Connect(net::ASYNC, net::OK); |
+ socket_->SetupSsl1Connect(net::ASYNC, net::ERR_CERT_AUTHORITY_INVALID); |
+ // Set cert extraction to fail |
+ socket_->SetExtractCertResult(false); |
+ |
EXPECT_CALL(handler_, OnConnectComplete(net::ERR_CERT_AUTHORITY_INVALID)); |
+ socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
+ base::Unretained(&handler_))); |
+ RunPendingTasks(); |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_ERROR, socket_->error_state()); |
+} |
+ |
+// Test connection error - cert extraction error (sync) |
+TEST_F(CastSocketTest, TestConnectCertExtractionErrorSync) { |
+ CreateCastSocket(); |
+ socket_->SetupTcp1Connect(net::SYNCHRONOUS, net::OK); |
+ socket_->SetupSsl1Connect(net::SYNCHRONOUS, net::ERR_CERT_AUTHORITY_INVALID); |
// Set cert extraction to fail |
socket_->SetExtractCertResult(false); |
- // Attempt to connect results in ERR_CERT_AUTHORTY_INVALID |
- connect_callback2.Run(net::ERR_CERT_AUTHORITY_INVALID); |
+ EXPECT_CALL(handler_, OnConnectComplete(net::ERR_CERT_AUTHORITY_INVALID)); |
+ socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
+ base::Unretained(&handler_))); |
+ RunPendingTasks(); |
+ |
EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_ERROR, socket_->error_state()); |
} |
-// Tests that the following connection flow works: |
-// - TCP connection succeeds (async) |
-// - SSL connection fails with cert error (async) |
-// - Cert is extracted successfully |
-// - Second TCP connection succeeds (async) |
-// - Second SSL connection succeeds (async) |
-// - Challenge request is sent (async) |
-// - Challenge response is received (async) |
-// - Credentials are verified successfuly |
-TEST_F(CastSocketTest, TestFullSecureConnectionFlowAsync) { |
+// Test connection error - challenge send fails |
+TEST_F(CastSocketTest, TestConnectChallengeSendError) { |
CreateCastSocketSecure(); |
- net::CompletionCallback tcp_connect_callback1; |
- net::CompletionCallback ssl_connect_callback1; |
+ socket_->SetupTcp1Connect(net::SYNCHRONOUS, net::OK); |
+ socket_->SetupSsl1Connect(net::SYNCHRONOUS, net::OK); |
+ socket_->AddWriteResult(net::SYNCHRONOUS, net::ERR_FAILED); |
- // Expectations for the initial connect call |
- ExpectTcpConnectPending(&tcp_connect_callback1); |
- ExpectSslConnectPending(&ssl_connect_callback1); |
+ EXPECT_CALL(handler_, OnConnectComplete(net::ERR_FAILED)); |
+ socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
+ base::Unretained(&handler_))); |
+ RunPendingTasks(); |
- // Start connect flow |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_ERROR, socket_->error_state()); |
+} |
+ |
+// Test connection error - challenge reply receive fails |
+TEST_F(CastSocketTest, TestConnectChallengeReplyReceiveError) { |
+ CreateCastSocketSecure(); |
+ |
+ socket_->SetupTcp1Connect(net::SYNCHRONOUS, net::OK); |
+ socket_->SetupSsl1Connect(net::SYNCHRONOUS, net::OK); |
+ socket_->AddWriteResultForMessage(net::ASYNC, auth_request_); |
+ socket_->AddReadResult(net::SYNCHRONOUS, net::ERR_FAILED); |
+ |
+ EXPECT_CALL(handler_, OnConnectComplete(net::ERR_FAILED)); |
socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
base::Unretained(&handler_))); |
- tcp_connect_callback1.Run(net::OK); |
+ RunPendingTasks(); |
- socket_->CreateNewSockets(); |
- net::CompletionCallback tcp_connect_callback2; |
- net::CompletionCallback ssl_connect_callback2; |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_ERROR, socket_->error_state()); |
+} |
- // Expectations for the second connect call |
- ExpectTcpConnectPending(&tcp_connect_callback2); |
- ExpectSslConnectPending(&ssl_connect_callback2); |
- EXPECT_CALL(handler_, OnConnectComplete(net::OK)); |
+// Test connection error - challenge reply verification fails |
+TEST_F(CastSocketTest, TestConnectChallengeVerificationFails) { |
+ CreateCastSocketSecure(); |
- // Trigger callbacks for the first connect |
- ssl_connect_callback1.Run(net::ERR_CERT_AUTHORITY_INVALID); |
+ socket_->SetupTcp1Connect(net::SYNCHRONOUS, net::OK); |
+ socket_->SetupSsl1Connect(net::SYNCHRONOUS, net::OK); |
+ socket_->AddWriteResultForMessage(net::ASYNC, auth_request_); |
+ socket_->AddReadResultForMessage(net::ASYNC, auth_reply_); |
+ socket_->AddReadResult(net::ASYNC, net::ERR_IO_PENDING); |
+ socket_->SetVerifyChallengeResult(false); |
- // Trigger callbacks for the second connect |
- tcp_connect_callback2.Run(net::OK); |
- ssl_connect_callback2.Run(net::OK); |
+ EXPECT_CALL(handler_, OnConnectComplete(net::ERR_FAILED)); |
+ socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
+ base::Unretained(&handler_))); |
+ RunPendingTasks(); |
- // Trigger callbacks for auth events. |
- CallOnChallengeEvent(net::OK); // Sent challenge |
- CallOnChallengeEvent(net::OK); // Received reply |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_CONNECT_ERROR, socket_->error_state()); |
+} |
+// Test write success - single message (async) |
+TEST_F(CastSocketTest, TestWriteAsync) { |
+ CreateCastSocket(); |
+ socket_->AddWriteResultForMessage(net::ASYNC, test_proto_strs_[0]); |
+ ConnectHelper(); |
+ |
+ EXPECT_CALL(handler_, OnWriteComplete(test_proto_strs_[0].size())); |
+ socket_->SendMessage(test_messages_[0], |
+ base::Bind(&CompleteHandler::OnWriteComplete, |
+ base::Unretained(&handler_))); |
+ RunPendingTasks(); |
+ |
EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
} |
-// Same as TestFullSecureConnectionFlowAsync, but operations are synchronous. |
-TEST_F(CastSocketTest, TestFullSecureConnectionFlowSync) { |
- CreateCastSocketSecure(); |
+// Test write success - single message (sync) |
+TEST_F(CastSocketTest, TestWriteSync) { |
+ CreateCastSocket(); |
+ socket_->AddWriteResultForMessage(net::SYNCHRONOUS, test_proto_strs_[0]); |
+ ConnectHelper(); |
- net::CompletionCallback tcp_connect_callback; |
- net::CompletionCallback ssl_connect_callback; |
+ EXPECT_CALL(handler_, OnWriteComplete(test_proto_strs_[0].size())); |
+ socket_->SendMessage(test_messages_[0], |
+ base::Bind(&CompleteHandler::OnWriteComplete, |
+ base::Unretained(&handler_))); |
+ RunPendingTasks(); |
- // Expectations for the connect calls |
- ExpectTcpConnect(&tcp_connect_callback, net::OK); |
- ExpectSslConnect(&ssl_connect_callback, net::OK); |
- EXPECT_CALL(handler_, OnConnectComplete(net::OK)); |
+ EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
+} |
- socket_->SetSendAuthChallengeResult(net::OK); |
- socket_->SetReadAuthChallengeReplyResult(net::OK); |
+// Test write success - single message sent in multiple chunks (async) |
+TEST_F(CastSocketTest, TestWriteChunkedAsync) { |
+ CreateCastSocket(); |
+ socket_->AddWriteResultForMessage(net::ASYNC, test_proto_strs_[0], 2); |
+ ConnectHelper(); |
- // Start connect flow |
- socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
- base::Unretained(&handler_))); |
+ EXPECT_CALL(handler_, OnWriteComplete(test_proto_strs_[0].size())); |
+ socket_->SendMessage(test_messages_[0], |
+ base::Bind(&CompleteHandler::OnWriteComplete, |
+ base::Unretained(&handler_))); |
+ RunPendingTasks(); |
EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
} |
-// Tests writing a single message where the completion is signaled via |
-// callback. |
-TEST_F(CastSocketTest, TestWriteViaCallback) { |
+// Test write success - single message sent in multiple chunks (sync) |
+TEST_F(CastSocketTest, TestWriteChunkedSync) { |
CreateCastSocket(); |
+ socket_->AddWriteResultForMessage(net::SYNCHRONOUS, test_proto_strs_[0], 2); |
ConnectHelper(); |
- net::CompletionCallback write_callback; |
- |
- EXPECT_CALL(mock_ssl_socket(), |
- Write(A<net::IOBuffer*>(), |
- 39, |
- A<const net::CompletionCallback&>())) |
- .Times(1) |
- .WillOnce(DoAll(SaveArg<2>(&write_callback), |
- Return(net::ERR_IO_PENDING))); |
- EXPECT_CALL(handler_, OnWriteComplete(39)); |
- socket_->SendMessage(test_message_, |
+ EXPECT_CALL(handler_, OnWriteComplete(test_proto_strs_[0].size())); |
+ socket_->SendMessage(test_messages_[0], |
base::Bind(&CompleteHandler::OnWriteComplete, |
base::Unretained(&handler_))); |
- write_callback.Run(39); |
+ RunPendingTasks(); |
+ |
EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
} |
-// Tests writing a single message where the Write() returns directly. |
-TEST_F(CastSocketTest, TestWrite) { |
+// Test write success - multiple messages (async) |
+TEST_F(CastSocketTest, TestWriteManyAsync) { |
CreateCastSocket(); |
+ for (size_t i = 0; i < arraysize(test_messages_); i++) { |
+ size_t msg_size = test_proto_strs_[i].size(); |
+ socket_->AddWriteResult(net::ASYNC, msg_size); |
+ EXPECT_CALL(handler_, OnWriteComplete(msg_size)); |
+ } |
ConnectHelper(); |
- EXPECT_CALL(mock_ssl_socket(), |
- Write(A<net::IOBuffer*>(), |
- 39, |
- A<const net::CompletionCallback&>())) |
- .Times(1) |
- .WillOnce(Return(39)); |
- EXPECT_CALL(handler_, OnWriteComplete(39)); |
- socket_->SendMessage(test_message_, |
- base::Bind(&CompleteHandler::OnWriteComplete, |
- base::Unretained(&handler_))); |
+ for (size_t i = 0; i < arraysize(test_messages_); i++) { |
+ socket_->SendMessage(test_messages_[i], |
+ base::Bind(&CompleteHandler::OnWriteComplete, |
+ base::Unretained(&handler_))); |
+ } |
+ RunPendingTasks(); |
+ |
EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
} |
-// Tests writing multiple messages. |
-TEST_F(CastSocketTest, TestWriteMany) { |
+// Test write success - multiple messages (sync) |
+TEST_F(CastSocketTest, TestWriteManySync) { |
CreateCastSocket(); |
+ for (size_t i = 0; i < arraysize(test_messages_); i++) { |
+ size_t msg_size = test_proto_strs_[i].size(); |
+ socket_->AddWriteResult(net::SYNCHRONOUS, msg_size); |
+ EXPECT_CALL(handler_, OnWriteComplete(msg_size)); |
+ } |
ConnectHelper(); |
- std::string messages[4]; |
- messages[0] = "Hello, World!"; |
- messages[1] = "Goodbye, World!"; |
- messages[2] = "Hello, Sky!"; |
- messages[3] = "Goodbye, Volcano!"; |
- int sizes[4] = {39, 41, 37, 43}; |
- MessageInfo message_info[4]; |
- net::CompletionCallback write_callback; |
- for (int i = 0; i < 4; i++) { |
- EXPECT_CALL(mock_ssl_socket(), |
- Write(A<net::IOBuffer*>(), |
- sizes[i], |
- A<const net::CompletionCallback&>())) |
- .WillRepeatedly(DoAll(SaveArg<2>(&write_callback), |
- Return(net::ERR_IO_PENDING))); |
- EXPECT_CALL(handler_, OnWriteComplete(sizes[i])); |
- } |
- |
- for (int i = 0; i < 4; i++) { |
- message_info[i].namespace_ = "urn:test"; |
- message_info[i].source_id = "1"; |
- message_info[i].destination_id = "2"; |
- message_info[i].data.reset(new base::StringValue(messages[i])); |
- socket_->SendMessage(message_info[i], |
+ for (size_t i = 0; i < arraysize(test_messages_); i++) { |
+ socket_->SendMessage(test_messages_[i], |
base::Bind(&CompleteHandler::OnWriteComplete, |
base::Unretained(&handler_))); |
} |
- for (int i = 0; i < 4; i++) { |
- write_callback.Run(sizes[i]); |
- } |
+ RunPendingTasks(); |
+ |
EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
} |
-// Tests error on writing. |
-TEST_F(CastSocketTest, TestWriteError) { |
+// Test write error - not connected |
+TEST_F(CastSocketTest, TestWriteErrorNotConnected) { |
CreateCastSocket(); |
+ |
+ EXPECT_CALL(handler_, OnWriteComplete(net::ERR_FAILED)); |
+ socket_->SendMessage(test_messages_[0], |
+ base::Bind(&CompleteHandler::OnWriteComplete, |
+ base::Unretained(&handler_))); |
+ |
+ EXPECT_EQ(cast_channel::READY_STATE_NONE, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
+} |
+ |
+// Test write error - very large message |
+TEST_F(CastSocketTest, TestWriteErrorLargeMessage) { |
+ CreateCastSocket(); |
ConnectHelper(); |
- net::CompletionCallback write_callback; |
- EXPECT_CALL(mock_ssl_socket(), |
- Write(A<net::IOBuffer*>(), |
- 39, |
- A<const net::CompletionCallback&>())) |
- .Times(1) |
- .WillOnce(DoAll(SaveArg<2>(&write_callback), |
- Return(net::ERR_SOCKET_NOT_CONNECTED))); |
- EXPECT_CALL(handler_, OnWriteComplete(net::ERR_SOCKET_NOT_CONNECTED)); |
+ EXPECT_CALL(handler_, OnWriteComplete(net::ERR_FAILED)); |
+ size_t size = kMaxMessageSize + 1; |
+ test_messages_[0].data.reset( |
+ new base::StringValue(std::string(size, 'a'))); |
+ socket_->SendMessage(test_messages_[0], |
+ base::Bind(&CompleteHandler::OnWriteComplete, |
+ base::Unretained(&handler_))); |
+ |
+ EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
+ |
+} |
+ |
+// Test write error - network error (sync) |
+TEST_F(CastSocketTest, TestWriteNetworkErrorSync) { |
+ CreateCastSocket(); |
+ socket_->AddWriteResult(net::SYNCHRONOUS, net::ERR_FAILED); |
+ ConnectHelper(); |
+ |
+ EXPECT_CALL(handler_, OnWriteComplete(net::ERR_FAILED)); |
EXPECT_CALL(mock_delegate_, |
OnError(socket_.get(), cast_channel::CHANNEL_ERROR_SOCKET_ERROR)); |
- socket_->SendMessage(test_message_, |
+ socket_->SendMessage(test_messages_[0], |
base::Bind(&CompleteHandler::OnWriteComplete, |
base::Unretained(&handler_))); |
+ RunPendingTasks(); |
+ |
EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_SOCKET_ERROR, socket_->error_state()); |
} |
-// Tests reading a single message. |
-TEST_F(CastSocketTest, TestRead) { |
+// Test write error - network error (async) |
+TEST_F(CastSocketTest, TestWriteErrorAsync) { |
CreateCastSocket(); |
+ socket_->AddWriteResult(net::ASYNC, net::ERR_FAILED); |
+ ConnectHelper(); |
- net::CompletionCallback connect_callback1; |
- net::CompletionCallback connect_callback2; |
- net::CompletionCallback read_callback; |
+ EXPECT_CALL(handler_, OnWriteComplete(net::ERR_FAILED)); |
+ EXPECT_CALL(mock_delegate_, |
+ OnError(socket_.get(), cast_channel::CHANNEL_ERROR_SOCKET_ERROR)); |
+ socket_->SendMessage(test_messages_[0], |
+ base::Bind(&CompleteHandler::OnWriteComplete, |
+ base::Unretained(&handler_))); |
+ RunPendingTasks(); |
- std::string message_data; |
- ASSERT_TRUE(CastSocket::Serialize(test_proto_, &message_data)); |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_SOCKET_ERROR, socket_->error_state()); |
+} |
- ExpectTcpConnect(&connect_callback1, net::ERR_IO_PENDING); |
- ExpectSslConnect(&connect_callback2, net::ERR_IO_PENDING); |
+// Test write error - 0 bytes written should be considered an error |
+TEST_F(CastSocketTest, TestWriteErrorZeroBytesWritten) { |
+ CreateCastSocket(); |
+ socket_->AddWriteResult(net::SYNCHRONOUS, 0); |
+ ConnectHelper(); |
- EXPECT_CALL(handler_, OnConnectComplete(net::OK)); |
- EXPECT_CALL(mock_ssl_socket(), Read(A<net::IOBuffer*>(), |
- A<int>(), |
- A<const net::CompletionCallback&>())) |
- .Times(3) |
- .WillRepeatedly(DoAll(SaveArg<2>(&read_callback), |
- Return(net::ERR_IO_PENDING))); |
+ EXPECT_CALL(handler_, OnWriteComplete(net::ERR_FAILED)); |
+ EXPECT_CALL(mock_delegate_, |
+ OnError(socket_.get(), cast_channel::CHANNEL_ERROR_SOCKET_ERROR)); |
+ socket_->SendMessage(test_messages_[0], |
+ base::Bind(&CompleteHandler::OnWriteComplete, |
+ base::Unretained(&handler_))); |
+ RunPendingTasks(); |
- // Expect the test message to be read and invoke the delegate. |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_SOCKET_ERROR, socket_->error_state()); |
+} |
+ |
+// Test that when an error occurrs in one write, write callback is invoked for |
+// all pending writes with the error |
+TEST_F(CastSocketTest, TestWriteErrorWithMultiplePendingWritesAsync) { |
+ CreateCastSocket(); |
+ socket_->AddWriteResult(net::ASYNC, net::ERR_SOCKET_NOT_CONNECTED); |
+ ConnectHelper(); |
+ |
+ const int num_writes = arraysize(test_messages_); |
+ EXPECT_CALL(handler_, OnWriteComplete(net::ERR_SOCKET_NOT_CONNECTED)) |
+ .Times(num_writes); |
EXPECT_CALL(mock_delegate_, |
- OnMessage(socket_.get(), A<const MessageInfo&>())); |
+ OnError(socket_.get(), cast_channel::CHANNEL_ERROR_SOCKET_ERROR)); |
+ for (int i = 0; i < num_writes; i++) { |
+ socket_->SendMessage(test_messages_[i], |
+ base::Bind(&CompleteHandler::OnWriteComplete, |
+ base::Unretained(&handler_))); |
+ } |
+ RunPendingTasks(); |
- // Connect the socket. |
- socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
- base::Unretained(&handler_))); |
- connect_callback1.Run(net::OK); |
- connect_callback2.Run(net::OK); |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_SOCKET_ERROR, socket_->error_state()); |
+} |
- // Put the test header and message into the io_buffers and invoke the read |
- // callbacks. |
- memcpy(socket_->header_read_buffer_->StartOfBuffer(), |
- message_data.c_str(), 4); |
- read_callback.Run(4); |
- memcpy(socket_->body_read_buffer_->StartOfBuffer(), |
- message_data.c_str() + 4, 35); |
- read_callback.Run(35); |
+// Test read success - single message (async) |
+TEST_F(CastSocketTest, TestReadAsync) { |
+ CreateCastSocket(); |
+ socket_->AddReadResultForMessage(net::ASYNC, test_proto_strs_[0]); |
+ EXPECT_CALL(mock_delegate_, |
+ OnMessage(socket_.get(), A<const MessageInfo&>())); |
+ ConnectHelper(); |
EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
} |
-// Tests reading multiple messages. |
-TEST_F(CastSocketTest, TestReadMany) { |
+// Test read success - single message (sync) |
+TEST_F(CastSocketTest, TestReadSync) { |
CreateCastSocket(); |
+ socket_->AddReadResultForMessage(net::SYNCHRONOUS, test_proto_strs_[0]); |
+ EXPECT_CALL(mock_delegate_, |
+ OnMessage(socket_.get(), A<const MessageInfo&>())); |
+ ConnectHelper(); |
- net::CompletionCallback connect_callback1; |
- net::CompletionCallback connect_callback2; |
- net::CompletionCallback read_callback; |
+ EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
+} |
- std::string messages[4]; |
- messages[0] = "Hello, World!"; |
- messages[1] = "Goodbye, World!"; |
- messages[2] = "Hello, Sky!"; |
- messages[3] = "Goodbye, Volcano!"; |
- int sizes[4] = {35, 37, 33, 39}; |
- std::string message_data[4]; |
+// Test read success - single message received in multiple chunks (async) |
+TEST_F(CastSocketTest, TestReadChunkedAsync) { |
+ CreateCastSocket(); |
+ socket_->AddReadResultForMessage(net::ASYNC, test_proto_strs_[0], 2); |
+ EXPECT_CALL(mock_delegate_, |
+ OnMessage(socket_.get(), A<const MessageInfo&>())); |
+ ConnectHelper(); |
- // Set up test data |
- for (int i = 0; i < 4; i++) { |
- test_proto_.set_payload_utf8(messages[i]); |
- ASSERT_TRUE(CastSocket::Serialize(test_proto_, &message_data[i])); |
- } |
+ EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
+} |
- ExpectTcpConnect(&connect_callback1, net::ERR_IO_PENDING); |
- ExpectSslConnect(&connect_callback2, net::ERR_IO_PENDING); |
+// Test read success - single message received in multiple chunks (sync) |
+TEST_F(CastSocketTest, TestReadChunkedSync) { |
+ CreateCastSocket(); |
+ socket_->AddReadResultForMessage(net::SYNCHRONOUS, test_proto_strs_[0], 2); |
+ EXPECT_CALL(mock_delegate_, |
+ OnMessage(socket_.get(), A<const MessageInfo&>())); |
+ ConnectHelper(); |
- EXPECT_CALL(handler_, OnConnectComplete(net::OK)); |
- EXPECT_CALL(mock_ssl_socket(), Read(A<net::IOBuffer*>(), |
- A<int>(), |
- A<const net::CompletionCallback&>())) |
- .Times(9) |
- .WillRepeatedly(DoAll(SaveArg<2>(&read_callback), |
- Return(net::ERR_IO_PENDING))); |
+ EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
+} |
- // Expect the test messages to be read and invoke the delegate. |
- EXPECT_CALL(mock_delegate_, OnMessage(socket_.get(), |
- A<const MessageInfo&>())) |
- .Times(4); |
+// Test read success - multiple messages (async) |
+TEST_F(CastSocketTest, TestReadManyAsync) { |
+ CreateCastSocket(); |
+ size_t num_reads = arraysize(test_proto_strs_); |
+ for (size_t i = 0; i < num_reads; i++) |
+ socket_->AddReadResultForMessage(net::ASYNC, test_proto_strs_[i]); |
+ EXPECT_CALL(mock_delegate_, |
+ OnMessage(socket_.get(), A<const MessageInfo&>())) |
+ .Times(num_reads); |
+ ConnectHelper(); |
- // Connect the socket. |
- socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
- base::Unretained(&handler_))); |
- connect_callback1.Run(net::OK); |
- connect_callback2.Run(net::OK); |
+ EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
+} |
- // Put the test headers and messages into the io_buffer and invoke the read |
- // callbacks. |
- for (int i = 0; i < 4; i++) { |
- memcpy(socket_->header_read_buffer_->StartOfBuffer(), |
- message_data[i].c_str(), 4); |
- read_callback.Run(4); |
- memcpy(socket_->body_read_buffer_->StartOfBuffer(), |
- message_data[i].c_str() + 4, sizes[i]); |
- read_callback.Run(sizes[i]); |
- } |
+// Test read success - multiple messages (sync) |
+TEST_F(CastSocketTest, TestReadManySync) { |
+ CreateCastSocket(); |
+ size_t num_reads = arraysize(test_proto_strs_); |
+ for (size_t i = 0; i < num_reads; i++) |
+ socket_->AddReadResultForMessage(net::SYNCHRONOUS, test_proto_strs_[i]); |
+ EXPECT_CALL(mock_delegate_, |
+ OnMessage(socket_.get(), A<const MessageInfo&>())) |
+ .Times(num_reads); |
+ ConnectHelper(); |
EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
} |
-// Tests error on reading. |
-TEST_F(CastSocketTest, TestReadError) { |
+// Test read error - network error (async) |
+TEST_F(CastSocketTest, TestReadErrorAsync) { |
CreateCastSocket(); |
+ socket_->AddReadResult(net::ASYNC, net::ERR_SOCKET_NOT_CONNECTED); |
+ EXPECT_CALL(mock_delegate_, |
+ OnError(socket_.get(), |
+ cast_channel::CHANNEL_ERROR_SOCKET_ERROR)); |
+ ConnectHelper(); |
- net::CompletionCallback connect_callback1; |
- net::CompletionCallback connect_callback2; |
- net::CompletionCallback read_callback; |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_SOCKET_ERROR, socket_->error_state()); |
+} |
- ExpectTcpConnect(&connect_callback1, net::ERR_IO_PENDING); |
- ExpectSslConnect(&connect_callback2, net::ERR_IO_PENDING); |
+// Test read error - network error (sync) |
+TEST_F(CastSocketTest, TestReadErrorSync) { |
+ CreateCastSocket(); |
+ socket_->AddReadResult(net::SYNCHRONOUS, net::ERR_SOCKET_NOT_CONNECTED); |
+ EXPECT_CALL(mock_delegate_, |
+ OnError(socket_.get(), |
+ cast_channel::CHANNEL_ERROR_SOCKET_ERROR)); |
+ ConnectHelper(); |
- EXPECT_CALL(handler_, OnConnectComplete(net::OK)); |
- EXPECT_CALL(mock_ssl_socket(), Read(A<net::IOBuffer*>(), |
- A<int>(), |
- A<const net::CompletionCallback&>())) |
- .WillOnce(DoAll(SaveArg<2>(&read_callback), |
- Return(net::ERR_IO_PENDING))); |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_SOCKET_ERROR, socket_->error_state()); |
+} |
+ |
+// Test read error - header parse error |
+TEST_F(CastSocketTest, TestReadHeaderParseError) { |
+ CreateCastSocket(); |
+ uint32 body_size = base::HostToNet32(kMaxMessageSize + 1); |
+ // TODO(munjal): Add a method to cast_message_util.h to serialize messages |
+ char header[sizeof(body_size)]; |
+ memcpy(&header, &body_size, arraysize(header)); |
+ socket_->AddReadResult(net::SYNCHRONOUS, header, arraysize(header)); |
EXPECT_CALL(mock_delegate_, |
- OnError(socket_.get(), cast_channel::CHANNEL_ERROR_SOCKET_ERROR)); |
+ OnError(socket_.get(), |
+ cast_channel::CHANNEL_ERROR_INVALID_MESSAGE)); |
+ ConnectHelper(); |
- // Connect the socket. |
- socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
- base::Unretained(&handler_))); |
- connect_callback1.Run(net::OK); |
- connect_callback2.Run(net::OK); |
+ EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_INVALID_MESSAGE, |
+ socket_->error_state()); |
+} |
- // Cause an error. |
- read_callback.Run(net::ERR_SOCKET_NOT_CONNECTED); |
+// Test read error - body parse error |
+TEST_F(CastSocketTest, TestReadBodyParseError) { |
+ CreateCastSocket(); |
+ char body[] = "some body"; |
+ uint32 body_size = base::HostToNet32(arraysize(body)); |
+ char header[sizeof(body_size)]; |
+ memcpy(&header, &body_size, arraysize(header)); |
+ socket_->AddReadResult(net::SYNCHRONOUS, header, arraysize(header)); |
+ socket_->AddReadResult(net::SYNCHRONOUS, body, arraysize(body)); |
+ EXPECT_CALL(mock_delegate_, |
+ OnError(socket_.get(), |
+ cast_channel::CHANNEL_ERROR_INVALID_MESSAGE)); |
+ ConnectHelper(); |
EXPECT_EQ(cast_channel::READY_STATE_CLOSED, socket_->ready_state()); |
- EXPECT_EQ(cast_channel::CHANNEL_ERROR_SOCKET_ERROR, socket_->error_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_INVALID_MESSAGE, |
+ socket_->error_state()); |
} |
} // namespace cast_channel |