1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
// 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 <atlbase.h>
#include <atlhost.h>
#include <stdint.h>
#include <string>
#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<RdpClientModule> {
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<RdpClientModule> 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<AutoThreadTaskRunner> task_runner_;
// Mocks RdpClient::EventHandler for testing.
MockRdpClientEventHandler event_handler_;
// Points to the object being tested.
scoped_ptr<RdpClient> 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
|