Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(305)

Side by Side Diff: remoting/host/desktop_process_unittest.cc

Issue 11272036: Fixing threading issues in remoting::DesktopProcess. The UI thread is now owned by the caller of re… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: CR feedback. Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/desktop_process.h" 5 #include "remoting/host/desktop_process.h"
6 6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
7 #include "base/location.h" 9 #include "base/location.h"
8 #include "base/memory/ref_counted.h" 10 #include "base/memory/ref_counted.h"
9 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "base/run_loop.h"
10 #include "base/single_thread_task_runner.h" 13 #include "base/single_thread_task_runner.h"
11 #include "ipc/ipc_channel.h" 14 #include "ipc/ipc_channel.h"
12 #include "ipc/ipc_channel_proxy.h" 15 #include "ipc/ipc_channel_proxy.h"
13 #include "ipc/ipc_listener.h" 16 #include "ipc/ipc_listener.h"
14 #include "ipc/ipc_message.h" 17 #include "ipc/ipc_message.h"
15 #include "remoting/base/auto_thread.h" 18 #include "remoting/base/auto_thread.h"
16 #include "remoting/base/auto_thread_task_runner.h" 19 #include "remoting/base/auto_thread_task_runner.h"
17 #include "remoting/host/chromoting_messages.h" 20 #include "remoting/host/chromoting_messages.h"
18 #include "remoting/host/desktop_process.h" 21 #include "remoting/host/desktop_process.h"
19 #include "remoting/host/host_exit_codes.h" 22 #include "remoting/host/host_exit_codes.h"
(...skipping 17 matching lines...) Expand all
37 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; 40 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
38 41
39 MOCK_METHOD1(OnDesktopAttached, void(IPC::PlatformFileForTransit)); 42 MOCK_METHOD1(OnDesktopAttached, void(IPC::PlatformFileForTransit));
40 MOCK_METHOD1(OnChannelConnected, void(int32)); 43 MOCK_METHOD1(OnChannelConnected, void(int32));
41 MOCK_METHOD0(OnChannelError, void()); 44 MOCK_METHOD0(OnChannelError, void());
42 45
43 private: 46 private:
44 DISALLOW_COPY_AND_ASSIGN(MockDaemonListener); 47 DISALLOW_COPY_AND_ASSIGN(MockDaemonListener);
45 }; 48 };
46 49
50 class MockNetworkListener : public IPC::Listener {
51 public:
52 MockNetworkListener() {}
53 virtual ~MockNetworkListener() {}
54
55 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
56
57 MOCK_METHOD1(OnDesktopAttached, void(IPC::PlatformFileForTransit));
58 MOCK_METHOD1(OnChannelConnected, void(int32));
59 MOCK_METHOD0(OnChannelError, void());
60
61 private:
62 DISALLOW_COPY_AND_ASSIGN(MockNetworkListener);
63 };
64
47 bool MockDaemonListener::OnMessageReceived(const IPC::Message& message) { 65 bool MockDaemonListener::OnMessageReceived(const IPC::Message& message) {
48 bool handled = true; 66 bool handled = true;
49 IPC_BEGIN_MESSAGE_MAP(MockDaemonListener, message) 67 IPC_BEGIN_MESSAGE_MAP(MockDaemonListener, message)
50 IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_DesktopAttached, 68 IPC_MESSAGE_HANDLER(ChromotingDesktopDaemonMsg_DesktopAttached,
51 OnDesktopAttached) 69 OnDesktopAttached)
52 IPC_MESSAGE_UNHANDLED(handled = false) 70 IPC_MESSAGE_UNHANDLED(handled = false)
53 IPC_END_MESSAGE_MAP() 71 IPC_END_MESSAGE_MAP()
54 72
55 EXPECT_TRUE(handled); 73 EXPECT_TRUE(handled);
56 return handled; 74 return handled;
57 } 75 }
58 76
77 bool MockNetworkListener::OnMessageReceived(const IPC::Message& message) {
78 bool handled = true;
79
80 // TODO(alexeypa): handle received messages here.
81
82 EXPECT_TRUE(handled);
83 return handled;
84 }
85
59 } // namespace 86 } // namespace
60 87
61 class DesktopProcessTest : public testing::Test { 88 class DesktopProcessTest : public testing::Test {
62 public: 89 public:
63 DesktopProcessTest(); 90 DesktopProcessTest();
64 virtual ~DesktopProcessTest(); 91 virtual ~DesktopProcessTest();
65 92
66 // testing::Test overrides 93 // testing::Test overrides
67 virtual void SetUp() OVERRIDE; 94 virtual void SetUp() OVERRIDE;
68 virtual void TearDown() OVERRIDE; 95 virtual void TearDown() OVERRIDE;
69 96
70 // MockDaemonListener mocks 97 // MockDaemonListener mocks
71 void ConnectNetworkChannel(IPC::PlatformFileForTransit desktop_process); 98 void ConnectNetworkChannel(IPC::PlatformFileForTransit desktop_process);
72 void OnDesktopAttached(IPC::PlatformFileForTransit desktop_process); 99 void OnDesktopAttached(IPC::PlatformFileForTransit desktop_process);
73 100
74 // Disconnects the daemon-to-desktop channel causing the desktop process to 101 // Disconnects the daemon-to-desktop channel causing the desktop process to
75 // exit. 102 // exit.
76 void DisconnectChannels(); 103 void DisconnectChannels();
77 104
78 void QuitMessageLoop();
79
80 // Runs the desktop process code in a separate thread. 105 // Runs the desktop process code in a separate thread.
81 void RunDesktopProcess(); 106 void RunDesktopProcess();
82 107
83 // Creates the desktop process and sends a crash request to it. 108 // Creates the desktop process and sends a crash request to it.
84 void RunDeathTest(); 109 void RunDeathTest();
85 110
86 // Sends a crash request to the desktop process. 111 // Sends a crash request to the desktop process.
87 void SendCrashRequest(); 112 void SendCrashRequest();
88 113
89 protected: 114 protected:
90 // Name of the daemon-to_desktop channel.
91 std::string channel_name_;
92
93 // The daemon's end of the daemon-to-desktop channel. 115 // The daemon's end of the daemon-to-desktop channel.
94 scoped_ptr<IPC::ChannelProxy> daemon_channel_; 116 scoped_ptr<IPC::ChannelProxy> daemon_channel_;
95 117
96 // Delegate that is passed to |daemon_channel_|. 118 // Delegate that is passed to |daemon_channel_|.
97 MockDaemonListener daemon_listener_; 119 MockDaemonListener daemon_listener_;
98 120
99 // Runs the daemon's end of the channel. 121 // Runs the daemon's end of the channel.
100 MessageLoop message_loop_; 122 MessageLoop message_loop_;
101 123
102 scoped_refptr<AutoThreadTaskRunner> io_task_runner_; 124 scoped_refptr<AutoThreadTaskRunner> io_task_runner_;
103 125
104 // The network's end of the network-to-desktop channel. 126 // The network's end of the network-to-desktop channel.
105 scoped_ptr<IPC::ChannelProxy> network_channel_; 127 scoped_ptr<IPC::ChannelProxy> network_channel_;
106 128
107 // Delegate that is passed to |network_channel_|. 129 // Delegate that is passed to |network_channel_|.
108 MockDaemonListener network_listener_; 130 MockNetworkListener network_listener_;
109 }; 131 };
110 132
111 133
112 DesktopProcessTest::DesktopProcessTest() 134 DesktopProcessTest::DesktopProcessTest()
113 : message_loop_(MessageLoop::TYPE_UI) { 135 : message_loop_(MessageLoop::TYPE_UI) {
114 } 136 }
115 137
116 DesktopProcessTest::~DesktopProcessTest() { 138 DesktopProcessTest::~DesktopProcessTest() {
117 } 139 }
118 140
119 void DesktopProcessTest::SetUp() { 141 void DesktopProcessTest::SetUp() {
120 scoped_refptr<AutoThreadTaskRunner> ui_task_runner = new AutoThreadTaskRunner(
121 message_loop_.message_loop_proxy(),
122 base::Bind(&DesktopProcessTest::QuitMessageLoop,
123 base::Unretained(this)));
124
125 io_task_runner_ = AutoThread::CreateWithType("IPC thread", ui_task_runner,
126 MessageLoop::TYPE_IO);
127
128 // Create the daemon-to-desktop process channel.
129 channel_name_ = IPC::Channel::GenerateUniqueRandomChannelID();
130 daemon_channel_.reset(new IPC::ChannelProxy(
131 IPC::ChannelHandle(channel_name_),
132 IPC::Channel::MODE_SERVER,
133 &daemon_listener_,
134 io_task_runner_));
135 } 142 }
136 143
137 void DesktopProcessTest::TearDown() { 144 void DesktopProcessTest::TearDown() {
138 } 145 }
139 146
140 void DesktopProcessTest::ConnectNetworkChannel( 147 void DesktopProcessTest::ConnectNetworkChannel(
141 IPC::PlatformFileForTransit desktop_process) { 148 IPC::PlatformFileForTransit desktop_process) {
142 149
143 #if defined(OS_POSIX) 150 #if defined(OS_POSIX)
144 IPC::ChannelHandle channel_handle("", desktop_process); 151 IPC::ChannelHandle channel_handle("", desktop_process);
(...skipping 16 matching lines...) Expand all
161 base::ClosePlatformFile(desktop_process.fd); 168 base::ClosePlatformFile(desktop_process.fd);
162 #endif // defined(OS_POSIX) 169 #endif // defined(OS_POSIX)
163 } 170 }
164 171
165 void DesktopProcessTest::DisconnectChannels() { 172 void DesktopProcessTest::DisconnectChannels() {
166 daemon_channel_.reset(); 173 daemon_channel_.reset();
167 network_channel_.reset(); 174 network_channel_.reset();
168 io_task_runner_ = NULL; 175 io_task_runner_ = NULL;
169 } 176 }
170 177
171 void DesktopProcessTest::QuitMessageLoop() { 178 void DesktopProcessTest::RunDesktopProcess() {
172 message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure()); 179 base::RunLoop run_loop;
173 } 180 base::Closure quit_ui_task_runner = base::Bind(
181 base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask),
182 message_loop_.message_loop_proxy(),
183 FROM_HERE, run_loop.QuitClosure());
184 scoped_refptr<AutoThreadTaskRunner> ui_task_runner = new AutoThreadTaskRunner(
185 message_loop_.message_loop_proxy(), quit_ui_task_runner);
174 186
175 void DesktopProcessTest::RunDesktopProcess() { 187 io_task_runner_ = AutoThread::CreateWithType("IPC thread", ui_task_runner,
176 DesktopProcess desktop_process(channel_name_); 188 MessageLoop::TYPE_IO);
177 EXPECT_EQ(desktop_process.Run(), kSuccessExitCode); 189
190 std::string channel_name = IPC::Channel::GenerateUniqueRandomChannelID();
191 daemon_channel_.reset(new IPC::ChannelProxy(
192 IPC::ChannelHandle(channel_name),
193 IPC::Channel::MODE_SERVER,
194 &daemon_listener_,
195 io_task_runner_));
196
197 DesktopProcess desktop_process(ui_task_runner, channel_name);
198 EXPECT_TRUE(desktop_process.Start());
199
200 ui_task_runner = NULL;
201 run_loop.Run();
178 } 202 }
179 203
180 void DesktopProcessTest::RunDeathTest() { 204 void DesktopProcessTest::RunDeathTest() {
181 InSequence s; 205 InSequence s;
182 EXPECT_CALL(daemon_listener_, OnChannelConnected(_)); 206 EXPECT_CALL(daemon_listener_, OnChannelConnected(_));
183 EXPECT_CALL(daemon_listener_, OnDesktopAttached(_)) 207 EXPECT_CALL(daemon_listener_, OnDesktopAttached(_))
184 .WillOnce(DoAll( 208 .WillOnce(DoAll(
185 Invoke(this, &DesktopProcessTest::OnDesktopAttached), 209 Invoke(this, &DesktopProcessTest::OnDesktopAttached),
186 InvokeWithoutArgs(this, &DesktopProcessTest::SendCrashRequest))); 210 InvokeWithoutArgs(this, &DesktopProcessTest::SendCrashRequest)));
187 211
(...skipping 29 matching lines...) Expand all
217 this, &DesktopProcessTest::DisconnectChannels)); 241 this, &DesktopProcessTest::DisconnectChannels));
218 242
219 RunDesktopProcess(); 243 RunDesktopProcess();
220 } 244 }
221 245
222 // Run the desktop process and ask it to crash. 246 // Run the desktop process and ask it to crash.
223 TEST_F(DesktopProcessTest, DeathTest) { 247 TEST_F(DesktopProcessTest, DeathTest) {
224 testing::GTEST_FLAG(death_test_style) = "threadsafe"; 248 testing::GTEST_FLAG(death_test_style) = "threadsafe";
225 249
226 EXPECT_DEATH(RunDeathTest(), ""); 250 EXPECT_DEATH(RunDeathTest(), "");
227
228 DisconnectChannels();
229 } 251 }
230 252
231 } // namespace remoting 253 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/desktop_process_main.cc ('k') | tools/valgrind/gtest_exclude/remoting_unittests.gtest-drmemory_win32.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698