Index: chrome/browser/extensions/api/cast_channel/cast_socket_unittest.cc |
=================================================================== |
--- chrome/browser/extensions/api/cast_channel/cast_socket_unittest.cc (revision 230522) |
+++ chrome/browser/extensions/api/cast_channel/cast_socket_unittest.cc (working copy) |
@@ -80,14 +80,30 @@ |
class TestCastSocket : public CastSocket { |
public: |
- explicit TestCastSocket(MockCastSocketDelegate* delegate) : |
- CastSocket("abcdefg", GURL("cast://192.0.0.1:8009"), delegate, |
+ static scoped_ptr<TestCastSocket> Create( |
+ MockCastSocketDelegate* delegate) { |
+ return scoped_ptr<TestCastSocket>( |
+ new TestCastSocket(delegate, "cast://192.0.0.1:8009")); |
+ } |
+ |
+ static scoped_ptr<TestCastSocket> CreateSecure( |
+ MockCastSocketDelegate* delegate) { |
+ return scoped_ptr<TestCastSocket>( |
+ new TestCastSocket(delegate, "casts://192.0.0.1:8009")); |
+ } |
+ |
+ 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) { |
+ 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) { |
} |
virtual ~TestCastSocket() { |
@@ -120,6 +136,18 @@ |
extract_cert_result_ = value; |
} |
+ void SetSendAuthChallengeResult(int result) { |
+ send_auth_challenge_result_ = result; |
+ } |
+ |
+ void SetReadAuthChallengeReplyResult(int result) { |
+ read_auth_challenge_reply_result_ = result; |
+ } |
+ |
+ void SetChallengeReplyResult(bool value) { |
+ challenge_reply_result_ = value; |
+ } |
+ |
MockTCPClientSocket* mock_tcp_socket_; |
MockSSLClientSocket* mock_ssl_socket_; |
@@ -140,6 +168,18 @@ |
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_; |
+ } |
+ |
private: |
net::CapturingNetLog capturing_net_log_; |
// Whether this object or the parent owns |mock_tcp_socket_|. |
@@ -148,6 +188,12 @@ |
bool owns_ssl_socket_; |
// 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_; |
}; |
class CastSocketTest : public testing::Test { |
@@ -156,7 +202,6 @@ |
virtual ~CastSocketTest() {} |
virtual void SetUp() OVERRIDE { |
- socket_.reset(new TestCastSocket(&mock_delegate_)); |
test_message_.namespace_ = "urn:test"; |
test_message_.source_id = "1"; |
test_message_.destination_id = "2"; |
@@ -170,27 +215,43 @@ |
base::Unretained(&handler_))); |
} |
- // Sets an expectation on the TCP socket Connect method. Connect method is |
- // setup to return net::ERR_IO_PENDING and store the callback passed to it |
- // in |callback|. |
- void ExpectTCPConnect(net::CompletionCallback* callback) { |
+ void CreateCastSocket() { |
+ socket_ = TestCastSocket::Create(&mock_delegate_); |
+ } |
+ |
+ void CreateCastSocketSecure() { |
+ 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(net::ERR_IO_PENDING))); |
+ .WillOnce(DoAll(SaveArg<0>(callback), Return(result))); |
} |
- // Sets an expectation on the SSL socket Connect method. Connect method is |
- // setup to return net::ERR_IO_PENDING and store the callback passed to it |
- // in |callback|. |
- void ExpectSSLConnect(net::CompletionCallback* callback) { |
+ // 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(net::ERR_IO_PENDING))); |
+ .WillOnce(DoAll(SaveArg<0>(callback), Return(result))); |
} |
- // Sets an expectation on the SSL socket Read method. Read method is setup |
- // to return net::ERR_IO_PENDING and to be called |times| number of times. |
- void ExpectSSLRead(int times) { |
+ // 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&>())) |
@@ -198,22 +259,20 @@ |
.WillOnce(Return(net::ERR_IO_PENDING)); |
} |
- // Sets expectations when the socket is connected. Connecting the socket also |
- // starts the read loop; we expect the call to Read(), but never fire the read |
- // callback. |
+ // 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. |
void ConnectHelper() { |
net::CompletionCallback connect_callback1; |
net::CompletionCallback connect_callback2; |
- ExpectTCPConnect(&connect_callback1); |
- ExpectSSLConnect(&connect_callback2); |
+ ExpectTcpConnect(&connect_callback1, net::OK); |
+ ExpectSslConnect(&connect_callback2, net::OK); |
EXPECT_CALL(handler_, OnConnectComplete(net::OK)); |
- ExpectSSLRead(1); |
+ ExpectSslRead(1); |
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()); |
@@ -232,6 +291,10 @@ |
return *mock_socket; |
} |
+ void CallOnChallengeEvent(int result) { |
+ socket_->OnChallengeEvent(result); |
+ } |
+ |
MockCastSocketDelegate mock_delegate_; |
scoped_ptr<TestCastSocket> socket_; |
CompleteHandler handler_; |
@@ -241,12 +304,13 @@ |
// Tests URL parsing and validation. |
TEST_F(CastSocketTest, TestCastURLs) { |
+ CreateCastSocket(); |
EXPECT_TRUE(socket_->ParseChannelUrl(GURL("cast://192.0.0.1:8009"))); |
- EXPECT_FALSE(socket_->is_secure_); |
+ EXPECT_FALSE(socket_->auth_required()); |
EXPECT_EQ(socket_->ip_endpoint_.ToString(), "192.0.0.1:8009"); |
EXPECT_TRUE(socket_->ParseChannelUrl(GURL("casts://192.0.0.1:12345"))); |
- EXPECT_TRUE(socket_->is_secure_); |
+ EXPECT_TRUE(socket_->auth_required()); |
EXPECT_EQ(socket_->ip_endpoint_.ToString(), "192.0.0.1:12345"); |
EXPECT_FALSE(socket_->ParseChannelUrl(GURL("http://192.0.0.1:12345"))); |
@@ -266,6 +330,7 @@ |
// Tests connecting and closing the socket. |
TEST_F(CastSocketTest, TestConnectAndClose) { |
+ CreateCastSocket(); |
ConnectHelper(); |
EXPECT_CALL(handler_, OnCloseComplete(net::OK)); |
@@ -275,16 +340,44 @@ |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
} |
-// Test that when first connection attempt fails with certificate authority |
-// invalid error, a second connection attempt is made with peer cert |
-// whitelisted. |
+// Tests that the following connection flow works: |
+// - TCP connection succeeds (async) |
+// - SSL connection succeeds (async) |
+TEST_F(CastSocketTest, TestConnect) { |
+ CreateCastSocket(); |
+ |
+ 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); |
+ |
+ EXPECT_EQ(cast_channel::READY_STATE_OPEN, socket_->ready_state()); |
+ EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
+} |
+ |
+// Test 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) |
TEST_F(CastSocketTest, TestTwoStepConnect) { |
+ CreateCastSocket(); |
+ |
// Expectations for the initial connect call |
net::CompletionCallback tcp_connect_callback1; |
net::CompletionCallback ssl_connect_callback1; |
- ExpectTCPConnect(&tcp_connect_callback1); |
- ExpectSSLConnect(&ssl_connect_callback1); |
+ ExpectTcpConnectPending(&tcp_connect_callback1); |
+ ExpectSslConnectPending(&ssl_connect_callback1); |
// Start connect flow |
socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
@@ -295,10 +388,10 @@ |
socket_->CreateNewSockets(); |
net::CompletionCallback tcp_connect_callback2; |
net::CompletionCallback ssl_connect_callback2; |
- ExpectTCPConnect(&tcp_connect_callback2); |
- ExpectSSLConnect(&ssl_connect_callback2); |
+ ExpectTcpConnectPending(&tcp_connect_callback2); |
+ ExpectSslConnectPending(&ssl_connect_callback2); |
EXPECT_CALL(handler_, OnConnectComplete(net::OK)); |
- ExpectSSLRead(1); |
+ ExpectSslRead(1); |
// Trigger callbacks for the first connect |
ssl_connect_callback1.Run(net::ERR_CERT_AUTHORITY_INVALID); |
@@ -311,15 +404,22 @@ |
EXPECT_EQ(cast_channel::CHANNEL_ERROR_NONE, socket_->error_state()); |
} |
-// Test that connection will be attempted a maximum of 2 times even if the |
-// second attempt also returns certificate authority invalid error. |
+// Test 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 fails (async) |
+// - The flow should NOT be tried again |
TEST_F(CastSocketTest, TestMaxTwoConnectAttempts) { |
+ CreateCastSocket(); |
+ |
net::CompletionCallback tcp_connect_callback1; |
net::CompletionCallback ssl_connect_callback1; |
// Expectations for the initial connect call |
- ExpectTCPConnect(&tcp_connect_callback1); |
- ExpectSSLConnect(&ssl_connect_callback1); |
+ ExpectTcpConnectPending(&tcp_connect_callback1); |
+ ExpectSslConnectPending(&ssl_connect_callback1); |
// Start connect flow |
socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
@@ -331,8 +431,8 @@ |
net::CompletionCallback ssl_connect_callback2; |
// Expectations for the second connect call |
- ExpectTCPConnect(&tcp_connect_callback2); |
- ExpectSSLConnect(&ssl_connect_callback2); |
+ ExpectTcpConnectPending(&tcp_connect_callback2); |
+ ExpectSslConnectPending(&ssl_connect_callback2); |
EXPECT_CALL(handler_, OnConnectComplete(net::ERR_CERT_AUTHORITY_INVALID)); |
// Trigger callbacks for the first connect |
@@ -346,12 +446,15 @@ |
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(); |
+ |
net::CompletionCallback connect_callback1; |
net::CompletionCallback connect_callback2; |
- ExpectTCPConnect(&connect_callback1); |
- ExpectSSLConnect(&connect_callback2); |
+ ExpectTcpConnectPending(&connect_callback1); |
+ ExpectSslConnectPending(&connect_callback2); |
socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
base::Unretained(&handler_))); |
@@ -368,10 +471,85 @@ |
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) { |
+ CreateCastSocketSecure(); |
+ |
+ net::CompletionCallback tcp_connect_callback1; |
+ net::CompletionCallback ssl_connect_callback1; |
+ |
+ // Expectations for the initial connect call |
+ ExpectTcpConnectPending(&tcp_connect_callback1); |
+ ExpectSslConnectPending(&ssl_connect_callback1); |
+ |
+ // Start connect flow |
+ socket_->Connect(base::Bind(&CompleteHandler::OnConnectComplete, |
+ base::Unretained(&handler_))); |
+ tcp_connect_callback1.Run(net::OK); |
+ |
+ socket_->CreateNewSockets(); |
+ net::CompletionCallback tcp_connect_callback2; |
+ net::CompletionCallback ssl_connect_callback2; |
+ |
+ // Expectations for the second connect call |
+ 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); |
+ |
+ // Trigger callbacks for auth events. |
+ CallOnChallengeEvent(net::OK); // Sent challenge |
+ CallOnChallengeEvent(net::OK); // Received reply |
+ |
+ 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(); |
+ |
+ net::CompletionCallback tcp_connect_callback; |
+ net::CompletionCallback ssl_connect_callback; |
+ |
+ // Expectations for the connect calls |
+ ExpectTcpConnect(&tcp_connect_callback, net::OK); |
+ ExpectSslConnect(&ssl_connect_callback, net::OK); |
+ EXPECT_CALL(handler_, OnConnectComplete(net::OK)); |
+ ExpectSslRead(1); |
+ |
+ socket_->SetSendAuthChallengeResult(net::OK); |
+ socket_->SetReadAuthChallengeReplyResult(net::OK); |
+ |
+ // Start connect flow |
+ 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()); |
+} |
+ |
// Tests writing a single message where the completion is signaled via |
// callback. |
TEST_F(CastSocketTest, TestWriteViaCallback) { |
+ CreateCastSocket(); |
ConnectHelper(); |
+ |
net::CompletionCallback write_callback; |
EXPECT_CALL(mock_ssl_socket(), |
@@ -392,6 +570,7 @@ |
// Tests writing a single message where the Write() returns directly. |
TEST_F(CastSocketTest, TestWrite) { |
+ CreateCastSocket(); |
ConnectHelper(); |
EXPECT_CALL(mock_ssl_socket(), |
@@ -410,6 +589,7 @@ |
// Tests writing multiple messages. |
TEST_F(CastSocketTest, TestWriteMany) { |
+ CreateCastSocket(); |
ConnectHelper(); |
std::string messages[4]; |
messages[0] = "Hello, World!"; |
@@ -448,6 +628,7 @@ |
// Tests error on writing. |
TEST_F(CastSocketTest, TestWriteError) { |
+ CreateCastSocket(); |
ConnectHelper(); |
net::CompletionCallback write_callback; |
@@ -470,6 +651,8 @@ |
// Tests reading a single message. |
TEST_F(CastSocketTest, TestRead) { |
+ CreateCastSocket(); |
+ |
net::CompletionCallback connect_callback1; |
net::CompletionCallback connect_callback2; |
net::CompletionCallback read_callback; |
@@ -518,6 +701,8 @@ |
// Tests reading multiple messages. |
TEST_F(CastSocketTest, TestReadMany) { |
+ CreateCastSocket(); |
+ |
net::CompletionCallback connect_callback1; |
net::CompletionCallback connect_callback2; |
net::CompletionCallback read_callback; |
@@ -580,6 +765,8 @@ |
// Tests error on reading. |
TEST_F(CastSocketTest, TestReadError) { |
+ CreateCastSocket(); |
+ |
net::CompletionCallback connect_callback1; |
net::CompletionCallback connect_callback2; |
net::CompletionCallback read_callback; |