OLD | NEW |
| (Empty) |
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. | |
4 | |
5 // These tests are POSIX only. | |
6 | |
7 #include "ipc/ipc_channel_posix.h" | |
8 | |
9 #include <errno.h> | |
10 #include <fcntl.h> | |
11 #include <stddef.h> | |
12 #include <stdint.h> | |
13 #include <string.h> | |
14 #include <sys/socket.h> | |
15 #include <sys/un.h> | |
16 #include <unistd.h> | |
17 | |
18 #include <memory> | |
19 | |
20 #include "base/command_line.h" | |
21 #include "base/files/file_path.h" | |
22 #include "base/files/file_util.h" | |
23 #include "base/location.h" | |
24 #include "base/path_service.h" | |
25 #include "base/posix/eintr_wrapper.h" | |
26 #include "base/process/process.h" | |
27 #include "base/rand_util.h" | |
28 #include "base/run_loop.h" | |
29 #include "base/single_thread_task_runner.h" | |
30 #include "base/strings/string_number_conversions.h" | |
31 #include "base/test/multiprocess_test.h" | |
32 #include "base/test/test_timeouts.h" | |
33 #include "build/build_config.h" | |
34 #include "ipc/ipc_listener.h" | |
35 #include "ipc/unix_domain_socket_util.h" | |
36 #include "testing/multiprocess_func_list.h" | |
37 | |
38 namespace { | |
39 | |
40 const char kSocketNameSwitch[] = "connection-socket-name"; | |
41 | |
42 static const uint32_t kQuitMessage = 47; | |
43 | |
44 class IPCChannelPosixTestListener : public IPC::Listener { | |
45 public: | |
46 enum STATUS { | |
47 DISCONNECTED, | |
48 MESSAGE_RECEIVED, | |
49 CHANNEL_ERROR, | |
50 CONNECTED, | |
51 DENIED, | |
52 LISTEN_ERROR | |
53 }; | |
54 | |
55 IPCChannelPosixTestListener(bool quit_only_on_message) | |
56 : status_(DISCONNECTED), | |
57 quit_only_on_message_(quit_only_on_message) { | |
58 } | |
59 | |
60 ~IPCChannelPosixTestListener() override {} | |
61 | |
62 bool OnMessageReceived(const IPC::Message& message) override { | |
63 EXPECT_EQ(message.type(), kQuitMessage); | |
64 status_ = MESSAGE_RECEIVED; | |
65 QuitRunLoop(); | |
66 return true; | |
67 } | |
68 | |
69 void OnChannelConnected(int32_t peer_pid) override { | |
70 status_ = CONNECTED; | |
71 if (!quit_only_on_message_) { | |
72 QuitRunLoop(); | |
73 } | |
74 } | |
75 | |
76 void OnChannelError() override { | |
77 status_ = CHANNEL_ERROR; | |
78 QuitRunLoop(); | |
79 } | |
80 | |
81 void OnChannelDenied() override { | |
82 status_ = DENIED; | |
83 if (!quit_only_on_message_) { | |
84 QuitRunLoop(); | |
85 } | |
86 } | |
87 | |
88 void OnChannelListenError() override { | |
89 status_ = LISTEN_ERROR; | |
90 if (!quit_only_on_message_) { | |
91 QuitRunLoop(); | |
92 } | |
93 } | |
94 | |
95 STATUS status() { return status_; } | |
96 | |
97 void QuitRunLoop() { | |
98 base::MessageLoopForIO* loop = base::MessageLoopForIO::current(); | |
99 if (loop->is_running()) { | |
100 loop->QuitNow(); | |
101 } else { | |
102 // Die as soon as Run is called. | |
103 loop->task_runner()->PostTask(FROM_HERE, loop->QuitWhenIdleClosure()); | |
104 } | |
105 } | |
106 | |
107 private: | |
108 // The current status of the listener. | |
109 STATUS status_; | |
110 // If |quit_only_on_message_| then the listener will only break out of | |
111 // the run loop when kQuitMessage is received. | |
112 bool quit_only_on_message_; | |
113 }; | |
114 | |
115 class IPCChannelPosixTest : public base::MultiProcessTest { | |
116 public: | |
117 static void SetUpSocket(IPC::ChannelHandle *handle, | |
118 IPC::Channel::Mode mode); | |
119 static void SpinRunLoop(base::TimeDelta delay); | |
120 static const std::string GetChannelDirName(); | |
121 static std::string GetClientConnectionSocketName(); | |
122 | |
123 const std::string& GetConnectionSocketName(); | |
124 | |
125 base::Process SpawnChild(const std::string& procname) { | |
126 base::CommandLine command_line = MakeCmdLine(procname); | |
127 command_line.AppendSwitchASCII( | |
128 kSocketNameSwitch, GetConnectionSocketName()); | |
129 return base::SpawnMultiProcessTestChild( | |
130 procname, command_line, base::LaunchOptions()); | |
131 } | |
132 | |
133 bool WaitForExit(base::Process& process, int* exit_code) { | |
134 #if defined(OS_ANDROID) | |
135 return AndroidWaitForChildExitWithTimeout( | |
136 process, base::TimeDelta::Max(), exit_code); | |
137 #else | |
138 return process.WaitForExit(exit_code); | |
139 #endif // defined(OS_ANDROID) | |
140 } | |
141 | |
142 protected: | |
143 void SetUp() override; | |
144 void TearDown() override; | |
145 | |
146 private: | |
147 std::unique_ptr<base::MessageLoopForIO> message_loop_; | |
148 std::string socket_name_; | |
149 }; | |
150 | |
151 const std::string IPCChannelPosixTest::GetChannelDirName() { | |
152 base::FilePath tmp_dir; | |
153 PathService::Get(base::DIR_TEMP, &tmp_dir); | |
154 return tmp_dir.value(); | |
155 } | |
156 | |
157 const std::string& IPCChannelPosixTest::GetConnectionSocketName() { | |
158 if (socket_name_.empty()) { | |
159 uint64_t id = base::RandUint64(); | |
160 socket_name_ = GetChannelDirName() + | |
161 "/chrome_IPCChannelPosixTest_" + | |
162 base::HexEncode(&id, sizeof(id)); | |
163 } | |
164 return socket_name_; | |
165 } | |
166 | |
167 std::string IPCChannelPosixTest::GetClientConnectionSocketName() { | |
168 DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(kSocketNameSwitch)); | |
169 return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
170 kSocketNameSwitch); | |
171 } | |
172 | |
173 void IPCChannelPosixTest::SetUp() { | |
174 MultiProcessTest::SetUp(); | |
175 // Construct a fresh IO Message loop for the duration of each test. | |
176 message_loop_.reset(new base::MessageLoopForIO()); | |
177 } | |
178 | |
179 void IPCChannelPosixTest::TearDown() { | |
180 message_loop_.reset(NULL); | |
181 MultiProcessTest::TearDown(); | |
182 } | |
183 | |
184 // Create up a socket and bind and listen to it, or connect it | |
185 // depending on the |mode|. | |
186 void IPCChannelPosixTest::SetUpSocket(IPC::ChannelHandle *handle, | |
187 IPC::Channel::Mode mode) { | |
188 const std::string& name = handle->name; | |
189 | |
190 int socket_fd = 0; | |
191 if (mode == IPC::Channel::MODE_NAMED_SERVER) { | |
192 IPC::CreateServerUnixDomainSocket(base::FilePath(name), &socket_fd); | |
193 } else if (mode == IPC::Channel::MODE_NAMED_CLIENT) { | |
194 IPC::CreateClientUnixDomainSocket(base::FilePath(name), &socket_fd); | |
195 } else { | |
196 FAIL() << "Unknown mode " << mode; | |
197 } | |
198 handle->socket.fd = socket_fd; | |
199 } | |
200 | |
201 void IPCChannelPosixTest::SpinRunLoop(base::TimeDelta delay) { | |
202 base::MessageLoopForIO* loop = base::MessageLoopForIO::current(); | |
203 // Post a quit task so that this loop eventually ends and we don't hang | |
204 // in the case of a bad test. Usually, the run loop will quit sooner than | |
205 // that because all tests use a IPCChannelPosixTestListener which quits the | |
206 // current run loop on any channel activity. | |
207 loop->task_runner()->PostDelayedTask(FROM_HERE, loop->QuitWhenIdleClosure(), | |
208 delay); | |
209 base::RunLoop().Run(); | |
210 } | |
211 | |
212 TEST_F(IPCChannelPosixTest, BasicListen) { | |
213 const std::string kChannelName = | |
214 GetChannelDirName() + "/IPCChannelPosixTest_BasicListen"; | |
215 | |
216 // Test creating a socket that is listening. | |
217 IPC::ChannelHandle handle(kChannelName); | |
218 SetUpSocket(&handle, IPC::Channel::MODE_NAMED_SERVER); | |
219 unlink(handle.name.c_str()); | |
220 std::unique_ptr<IPC::ChannelPosix> channel( | |
221 new IPC::ChannelPosix(handle, IPC::Channel::MODE_NAMED_SERVER, NULL)); | |
222 ASSERT_TRUE(channel->Connect()); | |
223 ASSERT_TRUE(channel->AcceptsConnections()); | |
224 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
225 channel->ResetToAcceptingConnectionState(); | |
226 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
227 unlink(handle.name.c_str()); | |
228 } | |
229 | |
230 TEST_F(IPCChannelPosixTest, BasicConnected) { | |
231 // Test creating a socket that is connected. | |
232 int pipe_fds[2]; | |
233 ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds)); | |
234 std::string socket_name("/var/tmp/IPCChannelPosixTest_BasicConnected"); | |
235 ASSERT_GE(fcntl(pipe_fds[0], F_SETFL, O_NONBLOCK), 0); | |
236 | |
237 base::FileDescriptor fd(pipe_fds[0], false); | |
238 IPC::ChannelHandle handle(socket_name, fd); | |
239 std::unique_ptr<IPC::ChannelPosix> channel( | |
240 new IPC::ChannelPosix(handle, IPC::Channel::MODE_SERVER, NULL)); | |
241 ASSERT_TRUE(channel->Connect()); | |
242 ASSERT_FALSE(channel->AcceptsConnections()); | |
243 channel->Close(); | |
244 ASSERT_TRUE(IGNORE_EINTR(close(pipe_fds[1])) == 0); | |
245 | |
246 // Make sure that we can use the socket that is created for us by | |
247 // a standard channel. | |
248 std::unique_ptr<IPC::ChannelPosix> channel2( | |
249 new IPC::ChannelPosix(socket_name, IPC::Channel::MODE_SERVER, NULL)); | |
250 ASSERT_TRUE(channel2->Connect()); | |
251 ASSERT_FALSE(channel2->AcceptsConnections()); | |
252 } | |
253 | |
254 // If a connection closes right before a Send() call, we may end up closing | |
255 // the connection without notifying the listener, which can cause hangs in | |
256 // sync_message_filter and others. Make sure the listener is notified. | |
257 TEST_F(IPCChannelPosixTest, SendHangTest) { | |
258 IPCChannelPosixTestListener out_listener(true); | |
259 IPCChannelPosixTestListener in_listener(true); | |
260 IPC::ChannelHandle in_handle("IN"); | |
261 std::unique_ptr<IPC::ChannelPosix> in_chan(new IPC::ChannelPosix( | |
262 in_handle, IPC::Channel::MODE_SERVER, &in_listener)); | |
263 IPC::ChannelHandle out_handle( | |
264 "OUT", base::FileDescriptor(in_chan->TakeClientFileDescriptor())); | |
265 std::unique_ptr<IPC::ChannelPosix> out_chan(new IPC::ChannelPosix( | |
266 out_handle, IPC::Channel::MODE_CLIENT, &out_listener)); | |
267 ASSERT_TRUE(in_chan->Connect()); | |
268 ASSERT_TRUE(out_chan->Connect()); | |
269 in_chan->Close(); // simulate remote process dying at an unfortunate time. | |
270 // Send will fail, because it cannot write the message. | |
271 ASSERT_FALSE(out_chan->Send(new IPC::Message( | |
272 0, // routing_id | |
273 kQuitMessage, // message type | |
274 IPC::Message::PRIORITY_NORMAL))); | |
275 SpinRunLoop(TestTimeouts::action_max_timeout()); | |
276 ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, out_listener.status()); | |
277 } | |
278 | |
279 // If a connection closes right before a Connect() call, we may end up closing | |
280 // the connection without notifying the listener, which can cause hangs in | |
281 // sync_message_filter and others. Make sure the listener is notified. | |
282 TEST_F(IPCChannelPosixTest, AcceptHangTest) { | |
283 IPCChannelPosixTestListener out_listener(true); | |
284 IPCChannelPosixTestListener in_listener(true); | |
285 IPC::ChannelHandle in_handle("IN"); | |
286 std::unique_ptr<IPC::ChannelPosix> in_chan(new IPC::ChannelPosix( | |
287 in_handle, IPC::Channel::MODE_SERVER, &in_listener)); | |
288 IPC::ChannelHandle out_handle( | |
289 "OUT", base::FileDescriptor(in_chan->TakeClientFileDescriptor())); | |
290 std::unique_ptr<IPC::ChannelPosix> out_chan(new IPC::ChannelPosix( | |
291 out_handle, IPC::Channel::MODE_CLIENT, &out_listener)); | |
292 ASSERT_TRUE(in_chan->Connect()); | |
293 in_chan->Close(); // simulate remote process dying at an unfortunate time. | |
294 ASSERT_FALSE(out_chan->Connect()); | |
295 SpinRunLoop(TestTimeouts::action_max_timeout()); | |
296 ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, out_listener.status()); | |
297 } | |
298 | |
299 TEST_F(IPCChannelPosixTest, AdvancedConnected) { | |
300 // Test creating a connection to an external process. | |
301 IPCChannelPosixTestListener listener(false); | |
302 IPC::ChannelHandle chan_handle(GetConnectionSocketName()); | |
303 SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER); | |
304 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( | |
305 chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener)); | |
306 ASSERT_TRUE(channel->Connect()); | |
307 ASSERT_TRUE(channel->AcceptsConnections()); | |
308 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
309 | |
310 base::Process process = SpawnChild("IPCChannelPosixTestConnectionProc"); | |
311 ASSERT_TRUE(process.IsValid()); | |
312 SpinRunLoop(TestTimeouts::action_max_timeout()); | |
313 ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status()); | |
314 ASSERT_TRUE(channel->HasAcceptedConnection()); | |
315 IPC::Message* message = new IPC::Message(0, // routing_id | |
316 kQuitMessage, // message type | |
317 IPC::Message::PRIORITY_NORMAL); | |
318 channel->Send(message); | |
319 SpinRunLoop(TestTimeouts::action_timeout()); | |
320 int exit_code = 0; | |
321 EXPECT_TRUE(WaitForExit(process, &exit_code)); | |
322 EXPECT_EQ(0, exit_code); | |
323 ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status()); | |
324 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
325 unlink(chan_handle.name.c_str()); | |
326 } | |
327 | |
328 TEST_F(IPCChannelPosixTest, ResetState) { | |
329 // Test creating a connection to an external process. Close the connection, | |
330 // but continue to listen and make sure another external process can connect | |
331 // to us. | |
332 IPCChannelPosixTestListener listener(false); | |
333 IPC::ChannelHandle chan_handle(GetConnectionSocketName()); | |
334 SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER); | |
335 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( | |
336 chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener)); | |
337 ASSERT_TRUE(channel->Connect()); | |
338 ASSERT_TRUE(channel->AcceptsConnections()); | |
339 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
340 | |
341 base::Process process = SpawnChild("IPCChannelPosixTestConnectionProc"); | |
342 ASSERT_TRUE(process.IsValid()); | |
343 SpinRunLoop(TestTimeouts::action_max_timeout()); | |
344 ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status()); | |
345 ASSERT_TRUE(channel->HasAcceptedConnection()); | |
346 channel->ResetToAcceptingConnectionState(); | |
347 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
348 | |
349 base::Process process2 = SpawnChild("IPCChannelPosixTestConnectionProc"); | |
350 ASSERT_TRUE(process2.IsValid()); | |
351 SpinRunLoop(TestTimeouts::action_max_timeout()); | |
352 ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status()); | |
353 ASSERT_TRUE(channel->HasAcceptedConnection()); | |
354 IPC::Message* message = new IPC::Message(0, // routing_id | |
355 kQuitMessage, // message type | |
356 IPC::Message::PRIORITY_NORMAL); | |
357 channel->Send(message); | |
358 SpinRunLoop(TestTimeouts::action_timeout()); | |
359 EXPECT_TRUE(process.Terminate(0, false)); | |
360 int exit_code = 0; | |
361 EXPECT_TRUE(WaitForExit(process2, &exit_code)); | |
362 EXPECT_EQ(0, exit_code); | |
363 ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status()); | |
364 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
365 unlink(chan_handle.name.c_str()); | |
366 } | |
367 | |
368 TEST_F(IPCChannelPosixTest, BadChannelName) { | |
369 // Test empty name | |
370 IPC::ChannelHandle handle(""); | |
371 std::unique_ptr<IPC::ChannelPosix> channel( | |
372 new IPC::ChannelPosix(handle, IPC::Channel::MODE_NAMED_SERVER, NULL)); | |
373 ASSERT_FALSE(channel->Connect()); | |
374 | |
375 // Test name that is too long. | |
376 const char *kTooLongName = "This_is_a_very_long_name_to_proactively_implement" | |
377 "client-centered_synergy_through_top-line" | |
378 "platforms_Phosfluorescently_disintermediate_" | |
379 "clicks-and-mortar_best_practices_without_" | |
380 "future-proof_growth_strategies_Continually" | |
381 "pontificate_proactive_potentialities_before" | |
382 "leading-edge_processes"; | |
383 EXPECT_GE(strlen(kTooLongName), IPC::kMaxSocketNameLength); | |
384 IPC::ChannelHandle handle2(kTooLongName); | |
385 std::unique_ptr<IPC::ChannelPosix> channel2( | |
386 new IPC::ChannelPosix(handle2, IPC::Channel::MODE_NAMED_SERVER, NULL)); | |
387 EXPECT_FALSE(channel2->Connect()); | |
388 } | |
389 | |
390 TEST_F(IPCChannelPosixTest, MultiConnection) { | |
391 // Test setting up a connection to an external process, and then have | |
392 // another external process attempt to connect to us. | |
393 IPCChannelPosixTestListener listener(false); | |
394 IPC::ChannelHandle chan_handle(GetConnectionSocketName()); | |
395 SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER); | |
396 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( | |
397 chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener)); | |
398 ASSERT_TRUE(channel->Connect()); | |
399 ASSERT_TRUE(channel->AcceptsConnections()); | |
400 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
401 | |
402 base::Process process = SpawnChild("IPCChannelPosixTestConnectionProc"); | |
403 ASSERT_TRUE(process.IsValid()); | |
404 SpinRunLoop(TestTimeouts::action_max_timeout()); | |
405 ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status()); | |
406 ASSERT_TRUE(channel->HasAcceptedConnection()); | |
407 base::Process process2 = SpawnChild("IPCChannelPosixFailConnectionProc"); | |
408 ASSERT_TRUE(process2.IsValid()); | |
409 SpinRunLoop(TestTimeouts::action_max_timeout()); | |
410 int exit_code = 0; | |
411 EXPECT_TRUE(WaitForExit(process2, &exit_code)); | |
412 EXPECT_EQ(exit_code, 0); | |
413 ASSERT_EQ(IPCChannelPosixTestListener::DENIED, listener.status()); | |
414 ASSERT_TRUE(channel->HasAcceptedConnection()); | |
415 IPC::Message* message = new IPC::Message(0, // routing_id | |
416 kQuitMessage, // message type | |
417 IPC::Message::PRIORITY_NORMAL); | |
418 channel->Send(message); | |
419 SpinRunLoop(TestTimeouts::action_timeout()); | |
420 EXPECT_TRUE(WaitForExit(process, &exit_code)); | |
421 EXPECT_EQ(exit_code, 0); | |
422 ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status()); | |
423 ASSERT_FALSE(channel->HasAcceptedConnection()); | |
424 unlink(chan_handle.name.c_str()); | |
425 } | |
426 | |
427 TEST_F(IPCChannelPosixTest, DoubleServer) { | |
428 // Test setting up two servers with the same name. | |
429 IPCChannelPosixTestListener listener(false); | |
430 IPCChannelPosixTestListener listener2(false); | |
431 IPC::ChannelHandle chan_handle(GetConnectionSocketName()); | |
432 std::unique_ptr<IPC::ChannelPosix> channel( | |
433 new IPC::ChannelPosix(chan_handle, IPC::Channel::MODE_SERVER, &listener)); | |
434 std::unique_ptr<IPC::ChannelPosix> channel2(new IPC::ChannelPosix( | |
435 chan_handle, IPC::Channel::MODE_SERVER, &listener2)); | |
436 ASSERT_TRUE(channel->Connect()); | |
437 ASSERT_FALSE(channel2->Connect()); | |
438 } | |
439 | |
440 TEST_F(IPCChannelPosixTest, BadMode) { | |
441 // Test setting up two servers with a bad mode. | |
442 IPCChannelPosixTestListener listener(false); | |
443 IPC::ChannelHandle chan_handle(GetConnectionSocketName()); | |
444 std::unique_ptr<IPC::ChannelPosix> channel( | |
445 new IPC::ChannelPosix(chan_handle, IPC::Channel::MODE_NONE, &listener)); | |
446 ASSERT_FALSE(channel->Connect()); | |
447 } | |
448 | |
449 TEST_F(IPCChannelPosixTest, IsNamedServerInitialized) { | |
450 const std::string& connection_socket_name = GetConnectionSocketName(); | |
451 IPCChannelPosixTestListener listener(false); | |
452 IPC::ChannelHandle chan_handle(connection_socket_name); | |
453 ASSERT_TRUE(base::DeleteFile(base::FilePath(connection_socket_name), false)); | |
454 ASSERT_FALSE(IPC::Channel::IsNamedServerInitialized( | |
455 connection_socket_name)); | |
456 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( | |
457 chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener)); | |
458 ASSERT_TRUE(IPC::Channel::IsNamedServerInitialized( | |
459 connection_socket_name)); | |
460 channel->Close(); | |
461 ASSERT_FALSE(IPC::Channel::IsNamedServerInitialized( | |
462 connection_socket_name)); | |
463 unlink(chan_handle.name.c_str()); | |
464 } | |
465 | |
466 // A long running process that connects to us | |
467 MULTIPROCESS_TEST_MAIN(IPCChannelPosixTestConnectionProc) { | |
468 base::MessageLoopForIO message_loop; | |
469 IPCChannelPosixTestListener listener(true); | |
470 IPC::ChannelHandle handle( | |
471 IPCChannelPosixTest::GetClientConnectionSocketName()); | |
472 IPCChannelPosixTest::SetUpSocket(&handle, IPC::Channel::MODE_NAMED_CLIENT); | |
473 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( | |
474 handle, IPC::Channel::MODE_NAMED_CLIENT, &listener)); | |
475 EXPECT_TRUE(channel->Connect()); | |
476 IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout()); | |
477 EXPECT_EQ(IPCChannelPosixTestListener::MESSAGE_RECEIVED, listener.status()); | |
478 return 0; | |
479 } | |
480 | |
481 // Simple external process that shouldn't be able to connect to us. | |
482 MULTIPROCESS_TEST_MAIN(IPCChannelPosixFailConnectionProc) { | |
483 base::MessageLoopForIO message_loop; | |
484 IPCChannelPosixTestListener listener(false); | |
485 IPC::ChannelHandle handle( | |
486 IPCChannelPosixTest::GetClientConnectionSocketName()); | |
487 IPCChannelPosixTest::SetUpSocket(&handle, IPC::Channel::MODE_NAMED_CLIENT); | |
488 std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( | |
489 handle, IPC::Channel::MODE_NAMED_CLIENT, &listener)); | |
490 | |
491 // In this case connect may succeed or fail depending on if the packet | |
492 // actually gets sent at sendmsg. Since we never delay on send, we may not | |
493 // see the error. However even if connect succeeds, eventually we will get an | |
494 // error back since the channel will be closed when we attempt to read from | |
495 // it. | |
496 bool connected = channel->Connect(); | |
497 if (connected) { | |
498 IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout()); | |
499 EXPECT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status()); | |
500 } else { | |
501 EXPECT_EQ(IPCChannelPosixTestListener::DISCONNECTED, listener.status()); | |
502 } | |
503 return 0; | |
504 } | |
505 | |
506 } // namespace | |
OLD | NEW |