12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ATL headers have to go first. 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <atlbase.h> 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <atlhost.h> 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <string> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind_helpers.h" 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/guid.h" 149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/run_loop.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/scoped_com_initializer.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/base/auto_thread_task_runner.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/win/rdp_client.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/win/wts_terminal_monitor.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gmock_mutant.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using testing::_; 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using testing::AtMost; 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using testing::InvokeWithoutArgs; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace remoting { 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Default width and hight of the RDP client window. 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const long kDefaultWidth = 1024; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const long kDefaultHeight = 768; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MockRdpClientEventHandler : public RdpClient::EventHandler { 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRdpClientEventHandler() {} 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~MockRdpClientEventHandler() {} 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MOCK_METHOD0(OnRdpConnected, void()); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MOCK_METHOD0(OnRdpClosed, void()); 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MockRdpClientEventHandler); 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// a14498c6-7f3b-4e42-9605-6c4a20d53c87 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static GUID RdpClientModuleLibid = { 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0xa14498c6, 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0x7f3b, 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0x4e42, 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 0x96, 0x05, 0x6c, 0x4a, 0x20, 0xd5, 0x3c, 0x87 } 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class RdpClientModule : public ATL::CAtlModuleT<RdpClientModule> { 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RdpClientModule(); 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~RdpClientModule(); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DECLARE_LIBID(RdpClientModuleLibid) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::win::ScopedCOMInitializer com_initializer_; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)RdpClientModule::RdpClientModule() { 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AtlAxWinInit(); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)RdpClientModule::~RdpClientModule() { 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AtlAxWinTerm(); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ATL::_pAtlModule = NULL; 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class RdpClientTest : public testing::Test { 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RdpClientTest(); 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~RdpClientTest(); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void SetUp() OVERRIDE; 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void TearDown() OVERRIDE; 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Caaled when an RDP connection is established. 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void OnRdpConnected(); 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Tears down |rdp_client_|. 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void CloseRdpClient(); 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected: 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The ATL module instance required by the ATL code. 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<RdpClientModule> module_; 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The UI message loop used by RdpClient. The loop is stopped once there is no 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // more references to |task_runner_|. 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MessageLoopForUI message_loop_; 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::RunLoop run_loop_; 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<AutoThreadTaskRunner> task_runner_; 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Mocks RdpClient::EventHandler for testing. 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockRdpClientEventHandler event_handler_; 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Points to the object being tested. 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<RdpClient> rdp_client_; 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Unique terminal identifier passed to RdpClient. 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string terminal_id_; 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RdpClientTest::RdpClientTest() { 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)RdpClientTest::~RdpClientTest() { 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RdpClientTest::SetUp() { 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Arrange to run |message_loop_| until no components depend on it. 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) task_runner_ = new AutoThreadTaskRunner( 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_loop_.message_loop_proxy(), run_loop_.QuitClosure()); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) module_.reset(new RdpClientModule()); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RdpClientTest::TearDown() { 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(!rdp_client_); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) module_.reset(); 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid RdpClientTest::OnRdpConnected() { 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch uint32 session_id = WtsTerminalMonitor::LookupSessionId(terminal_id_); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string id; 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(WtsTerminalMonitor::LookupTerminalId(session_id, &id)); 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(id, terminal_id_); 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_loop_.PostTask(FROM_HERE, base::Bind(&RdpClientTest::CloseRdpClient, 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))); 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RdpClientTest::CloseRdpClient() { 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(rdp_client_); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rdp_client_.reset(); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Creates a loopback RDP connection. 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(RdpClientTest, Basic) { 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch terminal_id_ = base::GenerateGUID(); 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // An ability to establish a loopback RDP connection depends on many factors 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // including OS SKU and having RDP enabled. Accept both successful connection 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and a connection error as a successful outcome. 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_CALL(event_handler_, OnRdpConnected()) 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) .Times(AtMost(1)) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) .WillOnce(Invoke(this, &RdpClientTest::OnRdpConnected)); 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_CALL(event_handler_, OnRdpClosed()) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) .Times(AtMost(1)) 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) .WillOnce(InvokeWithoutArgs(this, &RdpClientTest::CloseRdpClient)); 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rdp_client_.reset(new RdpClient( 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) task_runner_, task_runner_, 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) webrtc::DesktopSize(kDefaultWidth, kDefaultHeight), 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) terminal_id_, &event_handler_)); 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) task_runner_ = NULL; 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) run_loop_.Run(); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace remoting 174