diff options
author | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-17 21:06:24 +0000 |
---|---|---|
committer | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-17 21:06:24 +0000 |
commit | 60ccc243dfbfc86001cf1c0a4b44131a39d7d28d (patch) | |
tree | 8834337b7ad8eec985fd783d382734c5d9388eed /remoting/host/daemon_process_unittest.cc | |
parent | f05d582b7e213b15138697c01abf48c652ff271a (diff) | |
download | chromium_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.cc | 312 |
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 |