Roll src/third_party/WebKit f36d5e0:68b67cd (svn 193299:193303)
[chromium-blink-merge.git] / remoting / host / daemon_process_unittest.cc
blobd1e464baa71f59dd595bf26660eb09ea6c73ac4c
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/bind.h"
6 #include "base/bind_helpers.h"
7 #include "base/location.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/process/process.h"
10 #include "ipc/ipc_message.h"
11 #include "ipc/ipc_message_macros.h"
12 #include "ipc/ipc_platform_file.h"
13 #include "remoting/base/auto_thread_task_runner.h"
14 #include "remoting/host/chromoting_messages.h"
15 #include "remoting/host/daemon_process.h"
16 #include "remoting/host/desktop_session.h"
17 #include "testing/gmock_mutant.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 using testing::_;
22 using testing::AnyNumber;
23 using testing::InSequence;
25 namespace remoting {
27 namespace {
29 enum Messages {
30 kMessageCrash = ChromotingDaemonMsg_Crash::ID,
31 kMessageConfiguration = ChromotingDaemonNetworkMsg_Configuration::ID,
32 kMessageConnectTerminal = ChromotingNetworkHostMsg_ConnectTerminal::ID,
33 kMessageDisconnectTerminal = ChromotingNetworkHostMsg_DisconnectTerminal::ID,
34 kMessageTerminalDisconnected =
35 ChromotingDaemonNetworkMsg_TerminalDisconnected::ID
38 // Provides a public constructor allowing the test to create instances of
39 // DesktopSession directly.
40 class FakeDesktopSession : public DesktopSession {
41 public:
42 FakeDesktopSession(DaemonProcess* daemon_process, int id);
43 ~FakeDesktopSession() override;
45 void SetScreenResolution(const ScreenResolution& resolution) override {}
47 private:
48 DISALLOW_COPY_AND_ASSIGN(FakeDesktopSession);
51 class MockDaemonProcess : public DaemonProcess {
52 public:
53 MockDaemonProcess(
54 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
55 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
56 const base::Closure& stopped_callback);
57 virtual ~MockDaemonProcess();
59 virtual scoped_ptr<DesktopSession> DoCreateDesktopSession(
60 int terminal_id,
61 const ScreenResolution& resolution,
62 bool virtual_terminal) override;
64 virtual bool OnMessageReceived(const IPC::Message& message) override;
65 virtual void SendToNetwork(IPC::Message* message) override;
67 MOCK_METHOD1(Received, void(const IPC::Message&));
68 MOCK_METHOD1(Sent, void(const IPC::Message&));
70 MOCK_METHOD3(OnDesktopSessionAgentAttached,
71 bool(int, base::ProcessHandle, IPC::PlatformFileForTransit));
73 MOCK_METHOD1(DoCreateDesktopSessionPtr, DesktopSession*(int));
74 MOCK_METHOD1(DoCrashNetworkProcess, void(const tracked_objects::Location&));
75 MOCK_METHOD0(LaunchNetworkProcess, void());
77 private:
78 DISALLOW_COPY_AND_ASSIGN(MockDaemonProcess);
81 FakeDesktopSession::FakeDesktopSession(DaemonProcess* daemon_process, int id)
82 : DesktopSession(daemon_process, id) {
85 FakeDesktopSession::~FakeDesktopSession() {
88 MockDaemonProcess::MockDaemonProcess(
89 scoped_refptr<AutoThreadTaskRunner> caller_task_runner,
90 scoped_refptr<AutoThreadTaskRunner> io_task_runner,
91 const base::Closure& stopped_callback)
92 : DaemonProcess(caller_task_runner, io_task_runner, stopped_callback) {
95 MockDaemonProcess::~MockDaemonProcess() {
98 scoped_ptr<DesktopSession> MockDaemonProcess::DoCreateDesktopSession(
99 int terminal_id,
100 const ScreenResolution& resolution,
101 bool virtual_terminal) {
102 return make_scoped_ptr(DoCreateDesktopSessionPtr(terminal_id));
105 bool MockDaemonProcess::OnMessageReceived(const IPC::Message& message) {
106 // Notify the mock method.
107 Received(message);
109 // Call the actual handler.
110 return DaemonProcess::OnMessageReceived(message);
113 void MockDaemonProcess::SendToNetwork(IPC::Message* message) {
114 // Notify the mock method.
115 Sent(*message);
116 delete message;
119 } // namespace
121 class DaemonProcessTest : public testing::Test {
122 public:
123 DaemonProcessTest();
124 ~DaemonProcessTest() override;
126 void SetUp() override;
127 void TearDown() override;
129 // DaemonProcess mocks
130 DesktopSession* DoCreateDesktopSession(int terminal_id);
131 void DoCrashNetworkProcess(const tracked_objects::Location& location);
132 void LaunchNetworkProcess();
134 // Deletes |daemon_process_|.
135 void DeleteDaemonProcess();
137 // Quits |message_loop_|.
138 void QuitMessageLoop();
140 void StartDaemonProcess();
142 const DaemonProcess::DesktopSessionList& desktop_sessions() const {
143 return daemon_process_->desktop_sessions();
146 protected:
147 base::MessageLoopForIO message_loop_;
149 scoped_ptr<MockDaemonProcess> daemon_process_;
150 int terminal_id_;
153 DaemonProcessTest::DaemonProcessTest() : terminal_id_(0) {
156 DaemonProcessTest::~DaemonProcessTest() {
159 void DaemonProcessTest::SetUp() {
160 scoped_refptr<AutoThreadTaskRunner> task_runner = new AutoThreadTaskRunner(
161 message_loop_.message_loop_proxy(),
162 base::Bind(&DaemonProcessTest::QuitMessageLoop,
163 base::Unretained(this)));
164 daemon_process_.reset(
165 new MockDaemonProcess(task_runner, task_runner,
166 base::Bind(&DaemonProcessTest::DeleteDaemonProcess,
167 base::Unretained(this))));
169 // Set up daemon process mocks.
170 EXPECT_CALL(*daemon_process_, DoCreateDesktopSessionPtr(_))
171 .Times(AnyNumber())
172 .WillRepeatedly(Invoke(this, &DaemonProcessTest::DoCreateDesktopSession));
173 EXPECT_CALL(*daemon_process_, DoCrashNetworkProcess(_))
174 .Times(AnyNumber())
175 .WillRepeatedly(Invoke(this, &DaemonProcessTest::DoCrashNetworkProcess));
176 EXPECT_CALL(*daemon_process_, LaunchNetworkProcess())
177 .Times(AnyNumber())
178 .WillRepeatedly(Invoke(this, &DaemonProcessTest::LaunchNetworkProcess));
181 void DaemonProcessTest::TearDown() {
182 daemon_process_->Stop();
183 message_loop_.Run();
186 DesktopSession* DaemonProcessTest::DoCreateDesktopSession(int terminal_id) {
187 return new FakeDesktopSession(daemon_process_.get(), terminal_id);
190 void DaemonProcessTest::DoCrashNetworkProcess(
191 const tracked_objects::Location& location) {
192 daemon_process_->SendToNetwork(
193 new ChromotingDaemonMsg_Crash(location.function_name(),
194 location.file_name(),
195 location.line_number()));
198 void DaemonProcessTest::LaunchNetworkProcess() {
199 terminal_id_ = 0;
200 daemon_process_->OnChannelConnected(0);
203 void DaemonProcessTest::DeleteDaemonProcess() {
204 daemon_process_.reset();
207 void DaemonProcessTest::QuitMessageLoop() {
208 message_loop_.PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
211 void DaemonProcessTest::StartDaemonProcess() {
212 // DaemonProcess::Initialize() sets up the config watcher that this test does
213 // not support. Launch the process directly.
214 daemon_process_->LaunchNetworkProcess();
217 MATCHER_P(Message, type, "") {
218 return arg.type() == static_cast<uint32>(type);
221 TEST_F(DaemonProcessTest, OpenClose) {
222 InSequence s;
223 EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
224 EXPECT_CALL(*daemon_process_, Received(Message(kMessageConnectTerminal)));
225 EXPECT_CALL(*daemon_process_, Received(Message(kMessageDisconnectTerminal)));
226 EXPECT_CALL(*daemon_process_, Sent(Message(kMessageTerminalDisconnected)));
228 StartDaemonProcess();
230 int id = terminal_id_++;
231 ScreenResolution resolution;
233 EXPECT_TRUE(daemon_process_->OnMessageReceived(
234 ChromotingNetworkHostMsg_ConnectTerminal(id, resolution, false)));
235 EXPECT_EQ(1u, desktop_sessions().size());
236 EXPECT_EQ(id, desktop_sessions().front()->id());
238 EXPECT_TRUE(daemon_process_->OnMessageReceived(
239 ChromotingNetworkHostMsg_DisconnectTerminal(id)));
240 EXPECT_TRUE(desktop_sessions().empty());
243 TEST_F(DaemonProcessTest, CallCloseDesktopSession) {
244 InSequence s;
245 EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
246 EXPECT_CALL(*daemon_process_, Received(Message(kMessageConnectTerminal)));
247 EXPECT_CALL(*daemon_process_, Sent(Message(kMessageTerminalDisconnected)));
249 StartDaemonProcess();
251 int id = terminal_id_++;
252 ScreenResolution resolution;
254 EXPECT_TRUE(daemon_process_->OnMessageReceived(
255 ChromotingNetworkHostMsg_ConnectTerminal(id, resolution, false)));
256 EXPECT_EQ(1u, desktop_sessions().size());
257 EXPECT_EQ(id, desktop_sessions().front()->id());
259 daemon_process_->CloseDesktopSession(id);
260 EXPECT_TRUE(desktop_sessions().empty());
263 // Sends two CloseDesktopSession messages and expects the second one to be
264 // ignored.
265 TEST_F(DaemonProcessTest, DoubleDisconnectTerminal) {
266 InSequence s;
267 EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
268 EXPECT_CALL(*daemon_process_, Received(Message(kMessageConnectTerminal)));
269 EXPECT_CALL(*daemon_process_, Received(Message(kMessageDisconnectTerminal)));
270 EXPECT_CALL(*daemon_process_, Sent(Message(kMessageTerminalDisconnected)));
271 EXPECT_CALL(*daemon_process_, Received(Message(kMessageDisconnectTerminal)));
273 StartDaemonProcess();
275 int id = terminal_id_++;
276 ScreenResolution resolution;
278 EXPECT_TRUE(daemon_process_->OnMessageReceived(
279 ChromotingNetworkHostMsg_ConnectTerminal(id, resolution, false)));
280 EXPECT_EQ(1u, desktop_sessions().size());
281 EXPECT_EQ(id, desktop_sessions().front()->id());
283 EXPECT_TRUE(daemon_process_->OnMessageReceived(
284 ChromotingNetworkHostMsg_DisconnectTerminal(id)));
285 EXPECT_TRUE(desktop_sessions().empty());
287 EXPECT_TRUE(daemon_process_->OnMessageReceived(
288 ChromotingNetworkHostMsg_DisconnectTerminal(id)));
289 EXPECT_TRUE(desktop_sessions().empty());
292 // Tries to close an invalid terminal ID and expects the network process to be
293 // restarted.
294 TEST_F(DaemonProcessTest, InvalidDisconnectTerminal) {
295 InSequence s;
296 EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
297 EXPECT_CALL(*daemon_process_, Received(Message(kMessageDisconnectTerminal)));
298 EXPECT_CALL(*daemon_process_, Sent(Message(kMessageCrash)))
299 .WillOnce(InvokeWithoutArgs(this,
300 &DaemonProcessTest::LaunchNetworkProcess));
301 EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
303 StartDaemonProcess();
305 int id = terminal_id_++;
307 EXPECT_TRUE(daemon_process_->OnMessageReceived(
308 ChromotingNetworkHostMsg_DisconnectTerminal(id)));
309 EXPECT_TRUE(desktop_sessions().empty());
310 EXPECT_EQ(0, terminal_id_);
313 // Tries to open an invalid terminal ID and expects the network process to be
314 // restarted.
315 TEST_F(DaemonProcessTest, InvalidConnectTerminal) {
316 InSequence s;
317 EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
318 EXPECT_CALL(*daemon_process_, Received(Message(kMessageConnectTerminal)));
319 EXPECT_CALL(*daemon_process_, Received(Message(kMessageConnectTerminal)));
320 EXPECT_CALL(*daemon_process_, Sent(Message(kMessageCrash)))
321 .WillOnce(InvokeWithoutArgs(this,
322 &DaemonProcessTest::LaunchNetworkProcess));
323 EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
325 StartDaemonProcess();
327 int id = terminal_id_++;
328 ScreenResolution resolution;
330 EXPECT_TRUE(daemon_process_->OnMessageReceived(
331 ChromotingNetworkHostMsg_ConnectTerminal(id, resolution, false)));
332 EXPECT_EQ(1u, desktop_sessions().size());
333 EXPECT_EQ(id, desktop_sessions().front()->id());
335 EXPECT_TRUE(daemon_process_->OnMessageReceived(
336 ChromotingNetworkHostMsg_ConnectTerminal(id, resolution, false)));
337 EXPECT_TRUE(desktop_sessions().empty());
338 EXPECT_EQ(0, terminal_id_);
341 } // namespace remoting