// Copyright (c) 2013 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. // ATL headers have to go first. #include #include #include #include #include "base/bind.h" #include "base/bind_helpers.h" #include "base/guid.h" #include "base/macros.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/win/scoped_com_initializer.h" #include "remoting/base/auto_thread_task_runner.h" #include "remoting/host/win/rdp_client.h" #include "remoting/host/win/wts_terminal_monitor.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock_mutant.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" using testing::_; using testing::AtMost; using testing::InvokeWithoutArgs; namespace remoting { namespace { // Default width and hight of the RDP client window. const long kDefaultWidth = 1024; const long kDefaultHeight = 768; class MockRdpClientEventHandler : public RdpClient::EventHandler { public: MockRdpClientEventHandler() {} virtual ~MockRdpClientEventHandler() {} MOCK_METHOD0(OnRdpConnected, void()); MOCK_METHOD0(OnRdpClosed, void()); private: DISALLOW_COPY_AND_ASSIGN(MockRdpClientEventHandler); }; // a14498c6-7f3b-4e42-9605-6c4a20d53c87 static GUID RdpClientModuleLibid = { 0xa14498c6, 0x7f3b, 0x4e42, { 0x96, 0x05, 0x6c, 0x4a, 0x20, 0xd5, 0x3c, 0x87 } }; class RdpClientModule : public ATL::CAtlModuleT { public: RdpClientModule(); ~RdpClientModule() override; DECLARE_LIBID(RdpClientModuleLibid) private: base::win::ScopedCOMInitializer com_initializer_; }; RdpClientModule::RdpClientModule() { AtlAxWinInit(); } RdpClientModule::~RdpClientModule() { AtlAxWinTerm(); ATL::_pAtlModule = nullptr; } } // namespace class RdpClientTest : public testing::Test { public: RdpClientTest(); ~RdpClientTest() override; void SetUp() override; void TearDown() override; // Caaled when an RDP connection is established. void OnRdpConnected(); // Tears down |rdp_client_|. void CloseRdpClient(); protected: // The ATL module instance required by the ATL code. scoped_ptr module_; // The UI message loop used by RdpClient. The loop is stopped once there is no // more references to |task_runner_|. base::MessageLoopForUI message_loop_; base::RunLoop run_loop_; scoped_refptr task_runner_; // Mocks RdpClient::EventHandler for testing. MockRdpClientEventHandler event_handler_; // Points to the object being tested. scoped_ptr rdp_client_; // Unique terminal identifier passed to RdpClient. std::string terminal_id_; }; RdpClientTest::RdpClientTest() { } RdpClientTest::~RdpClientTest() { } void RdpClientTest::SetUp() { // Arrange to run |message_loop_| until no components depend on it. task_runner_ = new AutoThreadTaskRunner( message_loop_.task_runner(), run_loop_.QuitClosure()); module_.reset(new RdpClientModule()); } void RdpClientTest::TearDown() { EXPECT_TRUE(!rdp_client_); module_.reset(); } void RdpClientTest::OnRdpConnected() { uint32_t session_id = WtsTerminalMonitor::LookupSessionId(terminal_id_); std::string id; EXPECT_TRUE(WtsTerminalMonitor::LookupTerminalId(session_id, &id)); EXPECT_EQ(id, terminal_id_); message_loop_.PostTask(FROM_HERE, base::Bind(&RdpClientTest::CloseRdpClient, base::Unretained(this))); } void RdpClientTest::CloseRdpClient() { EXPECT_TRUE(rdp_client_); rdp_client_.reset(); } // Creates a loopback RDP connection. TEST_F(RdpClientTest, Basic) { terminal_id_ = base::GenerateGUID(); // An ability to establish a loopback RDP connection depends on many factors // including OS SKU and having RDP enabled. Accept both successful connection // and a connection error as a successful outcome. EXPECT_CALL(event_handler_, OnRdpConnected()) .Times(AtMost(1)) .WillOnce(Invoke(this, &RdpClientTest::OnRdpConnected)); EXPECT_CALL(event_handler_, OnRdpClosed()) .Times(AtMost(1)) .WillOnce(InvokeWithoutArgs(this, &RdpClientTest::CloseRdpClient)); rdp_client_.reset(new RdpClient( task_runner_, task_runner_, webrtc::DesktopSize(kDefaultWidth, kDefaultHeight), terminal_id_, &event_handler_)); task_runner_ = nullptr; run_loop_.Run(); } } // namespace remoting