Index: remoting/test/chromoting_instance_unittest.cc |
diff --git a/remoting/test/chromoting_instance_unittest.cc b/remoting/test/chromoting_instance_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..65eae1260d812c873545d6ac1a1de1c4f672b94d |
--- /dev/null |
+++ b/remoting/test/chromoting_instance_unittest.cc |
@@ -0,0 +1,266 @@ |
+// Copyright 2015 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 <string> |
+ |
+#include "base/message_loop/message_loop.h" |
+#include "remoting/protocol/fake_connection_to_host.h" |
+#include "remoting/protocol/protocol_mock_objects.h" |
+#include "remoting/test/chromoting_instance.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace { |
+const char kTestUserName[] = "test_user@faux_address.com"; |
+const char kAccessToken[] = "faux_access_token"; |
+} |
+ |
+namespace remoting { |
+namespace test { |
+ |
+using testing::_; |
+ |
+// Provides base functionality for the ChromotingInstance Tests below. This |
+// fixture also creates an IO MessageLoop, if necessary, for use by the |
+// ChromotingInstance. Overrides a subset of the RemoteConnectionObserver |
+// interface to track connection status changes for result verification. |
+class ChromotingInstanceTest : |
+ public ::testing::Test, |
+ public RemoteConnectionObserver { |
+ public: |
+ ChromotingInstanceTest(); |
+ ~ChromotingInstanceTest() override; |
+ |
+ protected: |
+ // Test interface. |
+ void SetUp() override; |
+ void TearDown() override; |
+ |
+ // Used for result verification. |
+ bool is_connected_to_host_; |
+ protocol::ConnectionToHost::State connection_state_; |
+ protocol::ErrorCode error_code_; |
+ |
+ // Used for simulating different conditions for the ChromotingInstance. |
+ RemoteHostInfo remote_host_info_; |
+ FakeConnectionToHost fake_connection_to_host_; |
+ protocol::MockConnectionToHost* mock_connection_to_host_; |
+ |
+ scoped_ptr<remoting::test::ChromotingInstance> chromoting_instance_; |
+ |
+ private: |
+ // RemoteConnectionObserver interface. |
+ void ConnectionStateChanged( |
+ protocol::ConnectionToHost::State state, |
+ protocol::ErrorCode error_code) override; |
+ void ConnectedToRemoteHost() override; |
+ void DisconnectedFromRemoteHost() override; |
+ |
+ // Used as return values in ON_CALL overrides for MockConnectionToHost. |
+ protocol::MockHostStub mock_host_stub_; |
+ protocol::SessionConfig session_config_; |
+ |
+ scoped_ptr<base::MessageLoopForIO> message_loop_; |
Sergey Ulanov
2015/03/09 06:44:41
Usually message_loop_ is defined as a first field
Sergey Ulanov
2015/03/09 06:44:41
Don't need this to be a pointer, see my next comme
joedow
2015/03/09 21:09:26
Done.
joedow
2015/03/09 21:09:26
Done.
|
+ |
+ DISALLOW_COPY_AND_ASSIGN(ChromotingInstanceTest); |
+}; |
+ |
+ChromotingInstanceTest::ChromotingInstanceTest() : |
+ is_connected_to_host_(false), |
+ connection_state_(protocol::ConnectionToHost::INITIALIZING), |
+ error_code_(protocol::OK), |
+ mock_connection_to_host_(nullptr) {} |
+ |
+ChromotingInstanceTest::~ChromotingInstanceTest() {} |
+ |
+void ChromotingInstanceTest::SetUp() { |
+ if (!base::MessageLoop::current()) { |
+ // Create a temporary message loop if the current thread does not already |
Sergey Ulanov
2015/03/09 06:44:41
This code is never expected to be invoked with a M
joedow
2015/03/09 21:09:26
Done.
|
+ // have one so we can use its task runner to create a request object. |
+ message_loop_.reset(new base::MessageLoopForIO); |
+ } |
+ |
+ chromoting_instance_.reset(new remoting::test::ChromotingInstance); |
+ chromoting_instance_->AddRemoteConnectionObserver(this); |
+ |
+ // Pass ownership of the MockConnectionToHost to the chromoting instance but |
+ // keep the ptr around so we can use it to simulate state changes. It will |
+ // remain valid until |chromoting_instance_| is destroyed. |
+ mock_connection_to_host_ = new protocol::MockConnectionToHost(); |
+ chromoting_instance_->SetConnectionToHostForTests( |
+ make_scoped_ptr(mock_connection_to_host_)); |
+ |
+ session_config_ = protocol::SessionConfig::ForTest(); |
+ remote_host_info_.remote_host_status = kRemoteHostStatusReady; |
+ |
+ // We want to redirect some of the calls to the mock objects to real objects |
+ // which implement a simplified version of the method so ON_CALL is used. |
+ ON_CALL(*mock_connection_to_host_, |
+ ConnectPtr(_, _, _, _, _)).WillByDefault(testing::Invoke( |
+ &fake_connection_to_host_, &FakeConnectionToHost::ConnectPtr)); |
Sergey Ulanov
2015/03/09 06:44:41
Do you need MockConnectionToHost, given that there
joedow
2015/03/09 21:09:26
Thanks for this info, I see GMOCK used often in th
|
+ ON_CALL(*mock_connection_to_host_, |
+ OnSessionStateChange(_)).WillByDefault(testing::Invoke( |
+ &fake_connection_to_host_, |
+ &FakeConnectionToHost::OnSessionStateChange)); |
+ ON_CALL(*mock_connection_to_host_, |
+ OnVideoChannelStatus(_)).WillByDefault(testing::Invoke( |
+ &fake_connection_to_host_, |
+ &FakeConnectionToHost::OnVideoChannelStatus)); |
+ ON_CALL(*mock_connection_to_host_, config()).WillByDefault( |
+ testing::ReturnRef(session_config_)); |
+ ON_CALL(*mock_connection_to_host_, host_stub()).WillByDefault( |
+ testing::Return(&mock_host_stub_)); |
+ |
+ EXPECT_CALL(mock_host_stub_, SetCapabilities(_)) |
+ .Times(testing::AtMost(1)); |
+ EXPECT_CALL(*mock_connection_to_host_, ConnectPtr(_, _, _, _, _)) |
+ .Times(testing::AtMost(1)); |
+ EXPECT_CALL(*mock_connection_to_host_, OnSessionStateChange(_)) |
+ .Times(testing::AnyNumber()); |
+ EXPECT_CALL(*mock_connection_to_host_, OnVideoChannelStatus(_)) |
+ .Times(testing::AnyNumber()); |
+ EXPECT_CALL(*mock_connection_to_host_, config()) |
+ .Times(testing::AnyNumber()); |
+ EXPECT_CALL(*mock_connection_to_host_, host_stub()) |
+ .Times(testing::AnyNumber()); |
+} |
+ |
+void ChromotingInstanceTest::TearDown() { |
+ chromoting_instance_->RemoveRemoteConnectionObserver(this); |
+ mock_connection_to_host_ = nullptr; |
+ |
+ // The chromoting instance must be destroyed before the message loop. |
+ chromoting_instance_.reset(); |
+ |
+ // The LibjingleTransportFactory destroys the PortAllocator via a DeleteSoon |
+ // operation. If we do not allow the message loop to run here, we run the |
+ // risk of the DeleteSoon task being dropped and incurring a memory leak. |
+ message_loop_->RunUntilIdle(); |
+ |
+ // Now that the message loop is clear, we can destroy it. |
+ message_loop_.reset(); |
+} |
+ |
+void ChromotingInstanceTest::ConnectionStateChanged( |
+ protocol::ConnectionToHost::State state, |
+ protocol::ErrorCode error_code) { |
+ connection_state_ = state; |
+ error_code_ = error_code; |
+} |
+ |
+void ChromotingInstanceTest::ConnectedToRemoteHost() { |
+ is_connected_to_host_ = true; |
+} |
+ |
+void ChromotingInstanceTest::DisconnectedFromRemoteHost() { |
+ is_connected_to_host_ = false; |
+} |
+ |
+TEST_F(ChromotingInstanceTest, StartConnectionAndDisconnect) { |
+ chromoting_instance_->StartConnection( |
+ kTestUserName, |
+ kAccessToken, |
+ remote_host_info_); |
+ EXPECT_EQ(protocol::ConnectionToHost::State::CONNECTING, connection_state_); |
+ EXPECT_EQ(protocol::ErrorCode::OK, error_code_); |
+ EXPECT_FALSE(is_connected_to_host_); |
+ |
+ // Simulate an AUTHENTICATED message being sent from the Jingle session. |
+ mock_connection_to_host_->OnSessionStateChange( |
+ protocol::Session::AUTHENTICATED); |
+ EXPECT_EQ(protocol::ConnectionToHost::State::AUTHENTICATED, |
+ connection_state_); |
+ EXPECT_EQ(protocol::ErrorCode::OK, error_code_); |
+ EXPECT_FALSE(is_connected_to_host_); |
+ |
+ // Simulate a CONNECTED message being sent from the Jingle session. |
+ mock_connection_to_host_->OnSessionStateChange(protocol::Session::CONNECTED); |
+ EXPECT_EQ(protocol::ConnectionToHost::State::CONNECTED, connection_state_); |
+ EXPECT_EQ(protocol::ErrorCode::OK, error_code_); |
+ EXPECT_FALSE(is_connected_to_host_); |
+ |
+ // The chromoting instance will consider its connection to the host complete |
+ // once the video channel is active. |
+ mock_connection_to_host_->OnVideoChannelStatus(true); |
+ EXPECT_EQ(protocol::ConnectionToHost::State::CONNECTED, connection_state_); |
+ EXPECT_EQ(protocol::ErrorCode::OK, error_code_); |
+ EXPECT_TRUE(is_connected_to_host_); |
+ |
+ chromoting_instance_->EndConnection(); |
+ EXPECT_EQ(protocol::ConnectionToHost::State::CLOSED, connection_state_); |
+ EXPECT_EQ(protocol::ErrorCode::OK, error_code_); |
+ EXPECT_FALSE(is_connected_to_host_); |
+} |
+ |
+TEST_F(ChromotingInstanceTest, StartConnectionThenFailWithAuthenticationError) { |
+ chromoting_instance_->StartConnection( |
+ kTestUserName, |
+ kAccessToken, |
+ remote_host_info_); |
+ EXPECT_EQ(protocol::ConnectionToHost::State::CONNECTING, connection_state_); |
+ EXPECT_EQ(protocol::ErrorCode::OK, error_code_); |
+ EXPECT_FALSE(is_connected_to_host_); |
+ |
+ fake_connection_to_host_.set_session_state_change_error_code( |
+ protocol::AUTHENTICATION_FAILED); |
+ mock_connection_to_host_->OnSessionStateChange(protocol::Session::FAILED); |
+ EXPECT_EQ(protocol::ConnectionToHost::State::FAILED, connection_state_); |
+ EXPECT_EQ(protocol::ErrorCode::AUTHENTICATION_FAILED, error_code_); |
+ EXPECT_FALSE(is_connected_to_host_); |
+ |
+ // Close the connection via the ChromotingInstance and verify the error state |
+ // is persisted. |
+ chromoting_instance_->EndConnection(); |
+ EXPECT_EQ(protocol::ConnectionToHost::State::FAILED, connection_state_); |
+ EXPECT_EQ(protocol::ErrorCode::AUTHENTICATION_FAILED, error_code_); |
+ EXPECT_FALSE(is_connected_to_host_); |
+} |
+ |
+TEST_F(ChromotingInstanceTest, StartConnectionThenFailWithUnknownError) { |
+ chromoting_instance_->StartConnection( |
+ kTestUserName, |
+ kAccessToken, |
+ remote_host_info_); |
+ EXPECT_EQ(protocol::ConnectionToHost::State::CONNECTING, connection_state_); |
+ EXPECT_EQ(protocol::ErrorCode::OK, error_code_); |
+ EXPECT_FALSE(is_connected_to_host_); |
+ |
+ // Simulate an AUTHENTICATED message being sent from the Jingle session. |
+ mock_connection_to_host_->OnSessionStateChange( |
+ protocol::Session::AUTHENTICATED); |
+ EXPECT_EQ(protocol::ConnectionToHost::State::AUTHENTICATED, |
+ connection_state_); |
+ EXPECT_EQ(protocol::ErrorCode::OK, error_code_); |
+ EXPECT_FALSE(is_connected_to_host_); |
+ |
+ // Simulate a CONNECTED message being sent from the Jingle session. |
+ mock_connection_to_host_->OnSessionStateChange(protocol::Session::CONNECTED); |
+ EXPECT_EQ(protocol::ConnectionToHost::State::CONNECTED, connection_state_); |
+ EXPECT_EQ(protocol::ErrorCode::OK, error_code_); |
+ EXPECT_FALSE(is_connected_to_host_); |
+ |
+ // The chromoting instance will consider its connection to the host complete |
+ // once the video channel is active. |
+ mock_connection_to_host_->OnVideoChannelStatus(true); |
+ EXPECT_EQ(protocol::ConnectionToHost::State::CONNECTED, connection_state_); |
+ EXPECT_EQ(protocol::ErrorCode::OK, error_code_); |
+ EXPECT_TRUE(is_connected_to_host_); |
+ |
+ fake_connection_to_host_.set_session_state_change_error_code( |
+ protocol::UNKNOWN_ERROR); |
+ mock_connection_to_host_->OnSessionStateChange(protocol::Session::FAILED); |
+ EXPECT_EQ(protocol::ConnectionToHost::State::FAILED, connection_state_); |
+ EXPECT_EQ(protocol::ErrorCode::UNKNOWN_ERROR, error_code_); |
+ EXPECT_FALSE(is_connected_to_host_); |
+ |
+ // Close the connection via the ChromotingInstance and verify the error state |
+ // is persisted. |
+ chromoting_instance_->EndConnection(); |
+ EXPECT_EQ(protocol::ConnectionToHost::State::FAILED, connection_state_); |
+ EXPECT_EQ(protocol::ErrorCode::UNKNOWN_ERROR, error_code_); |
+ EXPECT_FALSE(is_connected_to_host_); |
+} |
+ |
+} // namespace test |
+} // namespace remoting |