Index: remoting/host/win/worker_process_launcher_unittest.cc |
diff --git a/remoting/host/win/worker_process_launcher_unittest.cc b/remoting/host/win/worker_process_launcher_unittest.cc |
index c5a6c85e6ad4f3124af520ee01e00e8ddac3d65b..e10617963f128da1bf6e1de47cdda5594618bf57 100644 |
--- a/remoting/host/win/worker_process_launcher_unittest.cc |
+++ b/remoting/host/win/worker_process_launcher_unittest.cc |
@@ -12,12 +12,13 @@ |
#include "ipc/ipc_listener.h" |
#include "ipc/ipc_message.h" |
#include "remoting/base/auto_thread_task_runner.h" |
+#include "remoting/host/chromoting_messages.h" |
#include "remoting/host/host_exit_codes.h" |
#include "remoting/host/win/launch_process_with_token.h" |
#include "remoting/host/win/worker_process_launcher.h" |
#include "remoting/host/worker_process_ipc_delegate.h" |
-#include "testing/gmock_mutant.h" |
#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gmock_mutant.h" |
#include "testing/gtest/include/gtest/gtest.h" |
using base::win::ScopedHandle; |
@@ -37,27 +38,18 @@ namespace { |
const char kIpcSecurityDescriptor[] = "D:(A;;GA;;;AU)"; |
-class MockProcessLauncherDelegate |
- : public WorkerProcessLauncher::Delegate { |
+class MockProcessLauncherDelegate : public WorkerProcessLauncher::Delegate { |
public: |
MockProcessLauncherDelegate() {} |
virtual ~MockProcessLauncherDelegate() {} |
- virtual DWORD GetProcessId() const OVERRIDE { |
- return const_cast<MockProcessLauncherDelegate*>(this)->GetProcessId(); |
- } |
- |
- virtual bool IsPermanentError(int failure_count) const OVERRIDE { |
- return const_cast<MockProcessLauncherDelegate*>(this)->IsPermanentError( |
- failure_count); |
- } |
- |
// IPC::Sender implementation. |
MOCK_METHOD1(Send, bool(IPC::Message*)); |
- // WorkerProcessLauncher::Delegate implementation |
- MOCK_METHOD0(GetProcessId, DWORD()); |
- MOCK_METHOD1(IsPermanentError, bool(int)); |
+ // WorkerProcessLauncher::Delegate interface. |
+ MOCK_METHOD0(CloseChannel, void()); |
+ MOCK_CONST_METHOD0(GetProcessId, DWORD()); |
+ MOCK_CONST_METHOD1(IsPermanentError, bool(int)); |
MOCK_METHOD1(KillProcess, void(DWORD)); |
MOCK_METHOD2(LaunchProcess, bool(IPC::Listener*, ScopedHandle*)); |
@@ -65,13 +57,12 @@ class MockProcessLauncherDelegate |
DISALLOW_COPY_AND_ASSIGN(MockProcessLauncherDelegate); |
}; |
-class MockIpcDelegate |
- : public WorkerProcessIpcDelegate { |
+class MockIpcDelegate : public WorkerProcessIpcDelegate { |
public: |
MockIpcDelegate() {} |
virtual ~MockIpcDelegate() {} |
- // WorkerProcessIpcDelegate implementation |
+ // WorkerProcessIpcDelegate interface. |
MOCK_METHOD1(OnChannelConnected, void(int32)); |
MOCK_METHOD1(OnMessageReceived, bool(const IPC::Message&)); |
MOCK_METHOD0(OnPermanentError, void()); |
@@ -80,11 +71,35 @@ class MockIpcDelegate |
DISALLOW_COPY_AND_ASSIGN(MockIpcDelegate); |
}; |
+class MockWorkerListener : public IPC::Listener { |
+ public: |
+ MockWorkerListener() {} |
+ virtual ~MockWorkerListener() {} |
+ |
+ MOCK_METHOD3(OnCrash, void(const std::string&, const std::string&, int)); |
+ |
+ // IPC::Listener implementation |
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(MockWorkerListener); |
+}; |
+ |
+bool MockWorkerListener::OnMessageReceived(const IPC::Message& message) { |
+ bool handled = true; |
+ IPC_BEGIN_MESSAGE_MAP(MockWorkerListener, message) |
+ IPC_MESSAGE_HANDLER(ChromotingDaemonMsg_Crash, OnCrash) |
+ IPC_MESSAGE_UNHANDLED(handled = false) |
+ IPC_END_MESSAGE_MAP() |
+ |
+ EXPECT_TRUE(handled); |
+ |
+ return handled; |
+} |
+ |
} // namespace |
-class WorkerProcessLauncherTest |
- : public testing::Test, |
- public IPC::Listener { |
+class WorkerProcessLauncherTest : public testing::Test { |
public: |
WorkerProcessLauncherTest(); |
virtual ~WorkerProcessLauncherTest(); |
@@ -92,9 +107,6 @@ class WorkerProcessLauncherTest |
virtual void SetUp() OVERRIDE; |
virtual void TearDown() OVERRIDE; |
- // IPC::Listener implementation |
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; |
- |
// WorkerProcessLauncher::Delegate mocks |
void KillProcess(DWORD exit_code); |
bool LaunchProcess(IPC::Listener* delegate, |
@@ -104,8 +116,23 @@ class WorkerProcessLauncherTest |
bool FailLaunchAndStopWorker(IPC::Listener* delegate, |
ScopedHandle* process_exit_event_out); |
- void ConnectChannel(); |
- void DisconnectChannel(); |
+ // Connects the client end of the channel (the worker process's end). |
+ void ConnectClient(); |
+ |
+ // Disconnects the client end of the channel. |
+ void DisconnectClient(); |
+ |
+ // Disconnects the server end of the channel (the launcher's end). |
+ void DisconnectServer(); |
+ |
+ // Sends a message to the worker process. |
+ bool SendToProcess(IPC::Message* message); |
+ |
+ // Sends a fake message to the launcher. |
+ void SendFakeMessageToLauncher(); |
+ |
+ // Requests the worker to crash. |
+ void CrashWorker(); |
// Starts the worker. |
void StartWorker(); |
@@ -120,7 +147,13 @@ class WorkerProcessLauncherTest |
MessageLoop message_loop_; |
scoped_refptr<AutoThreadTaskRunner> task_runner_; |
- MockIpcDelegate ipc_delegate_; |
+ // Receives messages sent to the worker process. |
+ MockWorkerListener client_listener_; |
+ |
+ // Receives messages sent from the worker process. |
+ MockIpcDelegate server_listener_; |
+ |
+ // Implements WorkerProcessLauncher::Delegate. |
scoped_ptr<MockProcessLauncherDelegate> launcher_delegate_; |
// The name of the IPC channel. |
@@ -163,7 +196,11 @@ void WorkerProcessLauncherTest::SetUp() { |
launcher_delegate_.reset(new MockProcessLauncherDelegate()); |
EXPECT_CALL(*launcher_delegate_, Send(_)) |
.Times(AnyNumber()) |
- .WillRepeatedly(Return(false)); |
+ .WillRepeatedly(Invoke(this, &WorkerProcessLauncherTest::SendToProcess)); |
+ EXPECT_CALL(*launcher_delegate_, CloseChannel()) |
+ .Times(AnyNumber()) |
+ .WillRepeatedly(Invoke(this, |
+ &WorkerProcessLauncherTest::DisconnectServer)); |
EXPECT_CALL(*launcher_delegate_, GetProcessId()) |
.Times(AnyNumber()) |
.WillRepeatedly(ReturnPointee(&client_pid_)); |
@@ -175,18 +212,13 @@ void WorkerProcessLauncherTest::SetUp() { |
.WillRepeatedly(Invoke(this, &WorkerProcessLauncherTest::KillProcess)); |
// Set up IPC delegate. |
- EXPECT_CALL(ipc_delegate_, OnMessageReceived(_)) |
- .Times(AnyNumber()) |
- .WillRepeatedly(Return(false)); |
+ EXPECT_CALL(server_listener_, OnMessageReceived(_)) |
+ .Times(0); |
} |
void WorkerProcessLauncherTest::TearDown() { |
} |
-bool WorkerProcessLauncherTest::OnMessageReceived(const IPC::Message& message) { |
- return false; |
-} |
- |
void WorkerProcessLauncherTest::KillProcess(DWORD exit_code) { |
BOOL result = SetEvent(process_exit_event_); |
EXPECT_TRUE(result); |
@@ -229,7 +261,7 @@ bool WorkerProcessLauncherTest::LaunchProcessAndConnect( |
task_runner_->PostTask( |
FROM_HERE, |
- base::Bind(&WorkerProcessLauncherTest::ConnectChannel, |
+ base::Bind(&WorkerProcessLauncherTest::ConnectClient, |
base::Unretained(this))); |
return true; |
} |
@@ -244,26 +276,54 @@ bool WorkerProcessLauncherTest::FailLaunchAndStopWorker( |
return false; |
} |
-void WorkerProcessLauncherTest::ConnectChannel() { |
+void WorkerProcessLauncherTest::ConnectClient() { |
channel_client_.reset(new IPC::ChannelProxy( |
IPC::ChannelHandle(channel_name_), |
IPC::Channel::MODE_CLIENT, |
- this, |
+ &client_listener_, |
task_runner_)); |
+ |
+ // Pretend that |kLaunchSuccessTimeoutSeconds| passed since launching |
+ // the worker process. This will make the backoff algorithm think that this |
+ // launch attempt was successful and it will not delay the next launch. |
+ launcher_->ResetLaunchSuccessTimeoutForTest(); |
} |
-void WorkerProcessLauncherTest::DisconnectChannel() { |
+void WorkerProcessLauncherTest::DisconnectClient() { |
channel_client_.reset(); |
} |
+void WorkerProcessLauncherTest::DisconnectServer() { |
+ channel_server_.reset(); |
+} |
+ |
+bool WorkerProcessLauncherTest::SendToProcess(IPC::Message* message) { |
+ if (channel_server_) |
+ return channel_server_->Send(message); |
+ |
+ delete message; |
+ return false; |
+} |
+ |
+void WorkerProcessLauncherTest::SendFakeMessageToLauncher() { |
+ if (channel_client_) |
+ channel_client_->Send(new ChromotingDesktopNetworkMsg_DisconnectSession()); |
+} |
+ |
+void WorkerProcessLauncherTest::CrashWorker() { |
+ launcher_->Crash(FROM_HERE); |
+} |
+ |
void WorkerProcessLauncherTest::StartWorker() { |
launcher_.reset(new WorkerProcessLauncher( |
- task_runner_, launcher_delegate_.Pass(), &ipc_delegate_)); |
+ task_runner_, launcher_delegate_.Pass(), &server_listener_)); |
+ |
+ launcher_->SetKillProcessTimeoutForTest(base::TimeDelta::FromMilliseconds(0)); |
} |
void WorkerProcessLauncherTest::StopWorker() { |
launcher_.reset(); |
- DisconnectChannel(); |
+ DisconnectClient(); |
channel_name_.clear(); |
channel_server_.reset(); |
task_runner_ = NULL; |
@@ -278,9 +338,9 @@ TEST_F(WorkerProcessLauncherTest, Start) { |
.Times(1) |
.WillRepeatedly(Invoke(this, &WorkerProcessLauncherTest::LaunchProcess)); |
- EXPECT_CALL(ipc_delegate_, OnChannelConnected(_)) |
+ EXPECT_CALL(server_listener_, OnChannelConnected(_)) |
.Times(0); |
- EXPECT_CALL(ipc_delegate_, OnPermanentError()) |
+ EXPECT_CALL(server_listener_, OnPermanentError()) |
.Times(0); |
StartWorker(); |
@@ -296,11 +356,11 @@ TEST_F(WorkerProcessLauncherTest, StartAndConnect) { |
.WillRepeatedly(Invoke( |
this, &WorkerProcessLauncherTest::LaunchProcessAndConnect)); |
- EXPECT_CALL(ipc_delegate_, OnChannelConnected(_)) |
+ EXPECT_CALL(server_listener_, OnChannelConnected(_)) |
.Times(1) |
.WillOnce(InvokeWithoutArgs(this, |
&WorkerProcessLauncherTest::StopWorker)); |
- EXPECT_CALL(ipc_delegate_, OnPermanentError()) |
+ EXPECT_CALL(server_listener_, OnPermanentError()) |
.Times(0); |
StartWorker(); |
@@ -315,14 +375,14 @@ TEST_F(WorkerProcessLauncherTest, Restart) { |
.WillRepeatedly(Invoke( |
this, &WorkerProcessLauncherTest::LaunchProcessAndConnect)); |
Expectation first_connect = |
- EXPECT_CALL(ipc_delegate_, OnChannelConnected(_)) |
+ EXPECT_CALL(server_listener_, OnChannelConnected(_)) |
.Times(2) |
.WillOnce(InvokeWithoutArgs(CreateFunctor( |
this, &WorkerProcessLauncherTest::KillProcess, CONTROL_C_EXIT))) |
.WillOnce(InvokeWithoutArgs(this, |
&WorkerProcessLauncherTest::StopWorker)); |
- EXPECT_CALL(ipc_delegate_, OnPermanentError()) |
+ EXPECT_CALL(server_listener_, OnPermanentError()) |
.Times(0); |
StartWorker(); |
@@ -338,14 +398,14 @@ TEST_F(WorkerProcessLauncherTest, DropIpcChannel) { |
this, &WorkerProcessLauncherTest::LaunchProcessAndConnect)); |
Expectation first_connect = |
- EXPECT_CALL(ipc_delegate_, OnChannelConnected(_)) |
+ EXPECT_CALL(server_listener_, OnChannelConnected(_)) |
.Times(2) |
.WillOnce(InvokeWithoutArgs( |
- this, &WorkerProcessLauncherTest::DisconnectChannel)) |
+ this, &WorkerProcessLauncherTest::DisconnectClient)) |
.WillOnce(InvokeWithoutArgs( |
this, &WorkerProcessLauncherTest::StopWorker)); |
- EXPECT_CALL(ipc_delegate_, OnPermanentError()) |
+ EXPECT_CALL(server_listener_, OnPermanentError()) |
.Times(0); |
StartWorker(); |
@@ -360,11 +420,11 @@ TEST_F(WorkerProcessLauncherTest, PermanentError) { |
.WillRepeatedly(Invoke( |
this, &WorkerProcessLauncherTest::LaunchProcessAndConnect)); |
- EXPECT_CALL(ipc_delegate_, OnChannelConnected(_)) |
+ EXPECT_CALL(server_listener_, OnChannelConnected(_)) |
.Times(1) |
.WillOnce(InvokeWithoutArgs(CreateFunctor( |
this, &WorkerProcessLauncherTest::KillProcess, CONTROL_C_EXIT))); |
- EXPECT_CALL(ipc_delegate_, OnPermanentError()) |
+ EXPECT_CALL(server_listener_, OnPermanentError()) |
.Times(1) |
.WillOnce(InvokeWithoutArgs(this, |
&WorkerProcessLauncherTest::StopWorker)); |
@@ -383,9 +443,9 @@ TEST_F(WorkerProcessLauncherTest, InvalidClientPid) { |
.WillOnce(Invoke( |
this, &WorkerProcessLauncherTest::FailLaunchAndStopWorker)); |
- EXPECT_CALL(ipc_delegate_, OnChannelConnected(_)) |
+ EXPECT_CALL(server_listener_, OnChannelConnected(_)) |
.Times(0); |
- EXPECT_CALL(ipc_delegate_, OnPermanentError()) |
+ EXPECT_CALL(server_listener_, OnPermanentError()) |
.Times(0); |
client_pid_ = GetCurrentProcessId() + 4; |
@@ -393,4 +453,53 @@ TEST_F(WorkerProcessLauncherTest, InvalidClientPid) { |
message_loop_.Run(); |
} |
+// Requests the worker to crash and expects it to honor the request. |
+TEST_F(WorkerProcessLauncherTest, Crash) { |
+ EXPECT_CALL(*launcher_delegate_, LaunchProcess(_, _)) |
+ .Times(2) |
+ .WillRepeatedly(Invoke( |
+ this, &WorkerProcessLauncherTest::LaunchProcessAndConnect)); |
+ |
+ EXPECT_CALL(server_listener_, OnChannelConnected(_)) |
+ .Times(2) |
+ .WillOnce(InvokeWithoutArgs(this, |
+ &WorkerProcessLauncherTest::CrashWorker)) |
+ .WillOnce(InvokeWithoutArgs(this, |
+ &WorkerProcessLauncherTest::StopWorker)); |
+ |
+ EXPECT_CALL(client_listener_, OnCrash(_, _, _)) |
+ .Times(1) |
+ .WillOnce(InvokeWithoutArgs(CreateFunctor( |
+ this, &WorkerProcessLauncherTest::KillProcess, |
+ EXCEPTION_BREAKPOINT))); |
+ |
+ StartWorker(); |
+ message_loop_.Run(); |
+} |
+ |
+// Requests the worker to crash and terminates the worker even if it does not |
+// comply. |
+TEST_F(WorkerProcessLauncherTest, CrashAnyway) { |
+ EXPECT_CALL(*launcher_delegate_, LaunchProcess(_, _)) |
+ .Times(2) |
+ .WillRepeatedly(Invoke( |
+ this, &WorkerProcessLauncherTest::LaunchProcessAndConnect)); |
+ |
+ EXPECT_CALL(server_listener_, OnChannelConnected(_)) |
+ .Times(2) |
+ .WillOnce(InvokeWithoutArgs(this, |
+ &WorkerProcessLauncherTest::CrashWorker)) |
+ .WillOnce(InvokeWithoutArgs(this, |
+ &WorkerProcessLauncherTest::StopWorker)); |
+ |
+ // Ignore the crash request and try send another message to the launcher. |
+ EXPECT_CALL(client_listener_, OnCrash(_, _, _)) |
+ .Times(1) |
+ .WillOnce(InvokeWithoutArgs( |
+ this, &WorkerProcessLauncherTest::SendFakeMessageToLauncher)); |
+ |
+ StartWorker(); |
+ message_loop_.Run(); |
+} |
+ |
} // namespace remoting |