summaryrefslogtreecommitdiffstats
path: root/remoting/host/daemon_process_unittest.cc
diff options
context:
space:
mode:
authoralexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-17 21:06:24 +0000
committeralexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-17 21:06:24 +0000
commit60ccc243dfbfc86001cf1c0a4b44131a39d7d28d (patch)
tree8834337b7ad8eec985fd783d382734c5d9388eed /remoting/host/daemon_process_unittest.cc
parentf05d582b7e213b15138697c01abf48c652ff271a (diff)
downloadchromium_src-60ccc243dfbfc86001cf1c0a4b44131a39d7d28d.zip
chromium_src-60ccc243dfbfc86001cf1c0a4b44131a39d7d28d.tar.gz
chromium_src-60ccc243dfbfc86001cf1c0a4b44131a39d7d28d.tar.bz2
[Chromoting] Added support of a list of desktop sessions on the daemon side.
DaemonProcess object keeps a list of active desktop sessions, each representing the screen, input devices, etc to be remoted to another machine. The network process is expected to request a desktop session to be opened once a connection has been accepted and closed when the client session is destroyed. This CL includes changes on the daemon side only. BUG=134694 Review URL: https://chromiumcodereview.appspot.com/11017065 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@162520 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/host/daemon_process_unittest.cc')
-rw-r--r--remoting/host/daemon_process_unittest.cc312
1 files changed, 312 insertions, 0 deletions
diff --git a/remoting/host/daemon_process_unittest.cc b/remoting/host/daemon_process_unittest.cc
new file mode 100644
index 0000000..29a1dd2
--- /dev/null
+++ b/remoting/host/daemon_process_unittest.cc
@@ -0,0 +1,312 @@
+// Copyright (c) 2012 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 "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_macros.h"
+#include "remoting/base/auto_thread_task_runner.h"
+#include "remoting/host/chromoting_messages.h"
+#include "remoting/host/daemon_process.h"
+#include "remoting/host/desktop_session.h"
+#include "testing/gmock_mutant.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::AnyNumber;
+using testing::InSequence;
+
+namespace remoting {
+
+namespace {
+
+enum Messages {
+ kMessageConfiguration = ChromotingDaemonNetworkMsg_Configuration::ID,
+ kMessageConnectTerminal = ChromotingNetworkHostMsg_ConnectTerminal::ID,
+ kMessageDisconnectTerminal = ChromotingNetworkHostMsg_DisconnectTerminal::ID,
+ kMessageTerminalDisconnected =
+ ChromotingDaemonNetworkMsg_TerminalDisconnected::ID
+};
+
+// Provides a public constructor allowing the test to create instances of
+// DesktopSession directly.
+class FakeDesktopSession : public DesktopSession {
+ public:
+ FakeDesktopSession(DaemonProcess* daemon_process, int id);
+ virtual ~FakeDesktopSession();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FakeDesktopSession);
+};
+
+class MockDaemonProcess : public DaemonProcess {
+ public:
+ MockDaemonProcess(
+ scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
+ const base::Closure& stopped_callback);
+ virtual ~MockDaemonProcess();
+
+ virtual scoped_ptr<DesktopSession> DoCreateDesktopSession(
+ int terminal_id) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual void SendToNetwork(IPC::Message* message) OVERRIDE;
+
+ MOCK_METHOD1(Received, void(const IPC::Message&));
+ MOCK_METHOD1(Sent, void(const IPC::Message&));
+
+ MOCK_METHOD1(DoCreateDesktopSessionPtr, DesktopSession*(int));
+ MOCK_METHOD0(LaunchNetworkProcess, void());
+ MOCK_METHOD0(RestartNetworkProcess, void());
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockDaemonProcess);
+};
+
+FakeDesktopSession::FakeDesktopSession(DaemonProcess* daemon_process, int id)
+ : DesktopSession(daemon_process, id) {
+}
+
+FakeDesktopSession::~FakeDesktopSession() {
+}
+
+MockDaemonProcess::MockDaemonProcess(
+ scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
+ const base::Closure& stopped_callback)
+ : DaemonProcess(caller_task_runner, io_task_runner, stopped_callback) {
+}
+
+MockDaemonProcess::~MockDaemonProcess() {
+}
+
+scoped_ptr<DesktopSession> MockDaemonProcess::DoCreateDesktopSession(
+ int terminal_id) {
+ return scoped_ptr<DesktopSession>(DoCreateDesktopSessionPtr(terminal_id));
+}
+
+bool MockDaemonProcess::OnMessageReceived(const IPC::Message& message) {
+ // Notify the mock method.
+ Received(message);
+
+ // Call the actual handler.
+ return DaemonProcess::OnMessageReceived(message);
+}
+
+void MockDaemonProcess::SendToNetwork(IPC::Message* message) {
+ // Notify the mock method.
+ Sent(*message);
+}
+
+} // namespace
+
+class DaemonProcessTest : public testing::Test {
+ public:
+ DaemonProcessTest();
+ virtual ~DaemonProcessTest();
+
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+
+ // DaemonProcess mocks
+ DesktopSession* DoCreateDesktopSession(int terminal_id);
+ void LaunchNetworkProcess();
+
+ // Deletes |daemon_process_|.
+ void DeleteDaemonProcess();
+
+ // Quits |message_loop_|.
+ void QuitMessageLoop();
+
+ void StartDaemonProcess();
+
+ const DaemonProcess::DesktopSessionList& desktop_sessions() const {
+ return daemon_process_->desktop_sessions();
+ }
+
+ protected:
+ MessageLoop message_loop_;
+
+ scoped_ptr<MockDaemonProcess> daemon_process_;
+ int terminal_id_;
+};
+
+
+DaemonProcessTest::DaemonProcessTest()
+ : message_loop_(MessageLoop::TYPE_IO),
+ terminal_id_(0) {
+}
+
+DaemonProcessTest::~DaemonProcessTest() {
+}
+
+void DaemonProcessTest::SetUp() {
+ scoped_refptr<AutoThreadTaskRunner> task_runner = new AutoThreadTaskRunner(
+ message_loop_.message_loop_proxy(),
+ base::Bind(&DaemonProcessTest::QuitMessageLoop,
+ base::Unretained(this)));
+ daemon_process_.reset(
+ new MockDaemonProcess(task_runner, task_runner,
+ base::Bind(&DaemonProcessTest::DeleteDaemonProcess,
+ base::Unretained(this))));
+
+ // Set up daemon process mocks.
+ EXPECT_CALL(*daemon_process_, DoCreateDesktopSessionPtr(_))
+ .Times(AnyNumber())
+ .WillRepeatedly(Invoke(this, &DaemonProcessTest::DoCreateDesktopSession));
+ EXPECT_CALL(*daemon_process_, LaunchNetworkProcess())
+ .Times(AnyNumber())
+ .WillRepeatedly(Invoke(this, &DaemonProcessTest::LaunchNetworkProcess));
+}
+
+void DaemonProcessTest::TearDown() {
+ daemon_process_->Stop();
+ message_loop_.Run();
+}
+
+DesktopSession* DaemonProcessTest::DoCreateDesktopSession(int terminal_id) {
+ return new FakeDesktopSession(daemon_process_.get(), terminal_id);
+}
+
+void DaemonProcessTest::LaunchNetworkProcess() {
+ terminal_id_ = 0;
+ daemon_process_->OnChannelConnected();
+}
+
+void DaemonProcessTest::DeleteDaemonProcess() {
+ daemon_process_.reset();
+}
+
+void DaemonProcessTest::QuitMessageLoop() {
+ message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
+}
+
+void DaemonProcessTest::StartDaemonProcess() {
+ // DaemonProcess::Initialize() sets up the config watcher that this test does
+ // not support. Launch the process directly.
+ daemon_process_->LaunchNetworkProcess();
+}
+
+MATCHER_P(Message, type, "") {
+ return arg.type() == static_cast<uint32>(type);
+}
+
+TEST_F(DaemonProcessTest, OpenClose) {
+ InSequence s;
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageConnectTerminal)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageDisconnectTerminal)));
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageTerminalDisconnected)));
+
+ StartDaemonProcess();
+
+ int id = terminal_id_++;
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_ConnectTerminal(id)));
+ EXPECT_EQ(1u, desktop_sessions().size());
+ EXPECT_EQ(id, desktop_sessions().front()->id());
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_DisconnectTerminal(id)));
+ EXPECT_TRUE(desktop_sessions().empty());
+}
+
+TEST_F(DaemonProcessTest, CallCloseDesktopSession) {
+ InSequence s;
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageConnectTerminal)));
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageTerminalDisconnected)));
+
+ StartDaemonProcess();
+
+ int id = terminal_id_++;
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_ConnectTerminal(id)));
+ EXPECT_EQ(1u, desktop_sessions().size());
+ EXPECT_EQ(id, desktop_sessions().front()->id());
+
+ daemon_process_->CloseDesktopSession(id);
+ EXPECT_TRUE(desktop_sessions().empty());
+}
+
+// Sends two CloseDesktopSession messages and expects the second one to be
+// ignored.
+TEST_F(DaemonProcessTest, DoubleDisconnectTerminal) {
+ InSequence s;
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageConnectTerminal)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageDisconnectTerminal)));
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageTerminalDisconnected)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageDisconnectTerminal)));
+
+ StartDaemonProcess();
+
+ int id = terminal_id_++;
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_ConnectTerminal(id)));
+ EXPECT_EQ(1u, desktop_sessions().size());
+ EXPECT_EQ(id, desktop_sessions().front()->id());
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_DisconnectTerminal(id)));
+ EXPECT_TRUE(desktop_sessions().empty());
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_DisconnectTerminal(id)));
+ EXPECT_TRUE(desktop_sessions().empty());
+}
+
+// Tries to close an invalid terminal ID and expects the network process to be
+// restarted.
+TEST_F(DaemonProcessTest, InvalidDisconnectTerminal) {
+ InSequence s;
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageDisconnectTerminal)));
+ EXPECT_CALL(*daemon_process_, RestartNetworkProcess())
+ .WillRepeatedly(Invoke(this, &DaemonProcessTest::LaunchNetworkProcess));
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
+
+ StartDaemonProcess();
+
+ int id = terminal_id_++;
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_DisconnectTerminal(id)));
+ EXPECT_TRUE(desktop_sessions().empty());
+ EXPECT_EQ(0, terminal_id_);
+}
+
+// Tries to open an invalid terminal ID and expects the network process to be
+// restarted.
+TEST_F(DaemonProcessTest, InvalidConnectTerminal) {
+ InSequence s;
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageConnectTerminal)));
+ EXPECT_CALL(*daemon_process_, Received(Message(kMessageConnectTerminal)));
+ EXPECT_CALL(*daemon_process_, RestartNetworkProcess())
+ .WillRepeatedly(Invoke(this, &DaemonProcessTest::LaunchNetworkProcess));
+ EXPECT_CALL(*daemon_process_, Sent(Message(kMessageConfiguration)));
+
+ StartDaemonProcess();
+
+ int id = terminal_id_++;
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_ConnectTerminal(id)));
+ EXPECT_EQ(1u, desktop_sessions().size());
+ EXPECT_EQ(id, desktop_sessions().front()->id());
+
+ EXPECT_TRUE(daemon_process_->OnMessageReceived(
+ ChromotingNetworkHostMsg_ConnectTerminal(id)));
+ EXPECT_TRUE(desktop_sessions().empty());
+ EXPECT_EQ(0, terminal_id_);
+}
+
+} // namespace remoting