OLD | NEW |
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 // These tests are POSIX only. | 5 // These tests are POSIX only. |
6 | 6 |
7 #include "ipc/ipc_channel_posix.h" | 7 #include "ipc/ipc_channel_posix.h" |
8 | 8 |
9 #include <fcntl.h> | 9 #include <fcntl.h> |
10 #include <sys/socket.h> | 10 #include <sys/socket.h> |
(...skipping 23 matching lines...) Expand all Loading... |
34 enum STATUS { | 34 enum STATUS { |
35 DISCONNECTED, | 35 DISCONNECTED, |
36 MESSAGE_RECEIVED, | 36 MESSAGE_RECEIVED, |
37 CHANNEL_ERROR, | 37 CHANNEL_ERROR, |
38 CONNECTED, | 38 CONNECTED, |
39 DENIED, | 39 DENIED, |
40 LISTEN_ERROR | 40 LISTEN_ERROR |
41 }; | 41 }; |
42 | 42 |
43 IPCChannelPosixTestListener(bool quit_only_on_message) | 43 IPCChannelPosixTestListener(bool quit_only_on_message) |
44 : status_(DISCONNECTED), quit_only_on_message_(quit_only_on_message) {} | 44 : status_(DISCONNECTED), |
| 45 quit_only_on_message_(quit_only_on_message) { |
| 46 } |
45 | 47 |
46 virtual ~IPCChannelPosixTestListener() {} | 48 virtual ~IPCChannelPosixTestListener() {} |
47 | 49 |
48 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { | 50 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
49 EXPECT_EQ(message.type(), kQuitMessage); | 51 EXPECT_EQ(message.type(), kQuitMessage); |
50 status_ = MESSAGE_RECEIVED; | 52 status_ = MESSAGE_RECEIVED; |
51 QuitRunLoop(); | 53 QuitRunLoop(); |
52 return true; | 54 return true; |
53 } | 55 } |
54 | 56 |
55 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE { | 57 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE { |
56 status_ = CONNECTED; | 58 status_ = CONNECTED; |
57 if (!quit_only_on_message_) { | 59 if (!quit_only_on_message_) { |
58 QuitRunLoop(); | 60 QuitRunLoop(); |
59 } | 61 } |
60 } | 62 } |
61 | 63 |
62 virtual void OnChannelError() OVERRIDE { | 64 virtual void OnChannelError() OVERRIDE { |
63 status_ = CHANNEL_ERROR; | 65 status_ = CHANNEL_ERROR; |
64 if (!quit_only_on_message_) { | 66 QuitRunLoop(); |
65 QuitRunLoop(); | |
66 } | |
67 } | 67 } |
68 | 68 |
69 virtual void OnChannelDenied() OVERRIDE { | 69 virtual void OnChannelDenied() OVERRIDE { |
70 status_ = DENIED; | 70 status_ = DENIED; |
71 if (!quit_only_on_message_) { | 71 if (!quit_only_on_message_) { |
72 QuitRunLoop(); | 72 QuitRunLoop(); |
73 } | 73 } |
74 } | 74 } |
75 | 75 |
76 virtual void OnChannelListenError() OVERRIDE { | 76 virtual void OnChannelListenError() OVERRIDE { |
77 status_ = LISTEN_ERROR; | 77 status_ = LISTEN_ERROR; |
78 if (!quit_only_on_message_) { | 78 if (!quit_only_on_message_) { |
79 QuitRunLoop(); | 79 QuitRunLoop(); |
80 } | 80 } |
81 } | 81 } |
82 | 82 |
83 STATUS status() { return status_; } | 83 STATUS status() { return status_; } |
84 | 84 |
85 void QuitRunLoop() { | 85 void QuitRunLoop() { |
86 base::MessageLoopForIO::current()->QuitNow(); | 86 base::MessageLoopForIO* loop = base::MessageLoopForIO::current(); |
| 87 if (loop->is_running()) { |
| 88 loop->QuitNow(); |
| 89 } else { |
| 90 // Die as soon as Run is called. |
| 91 loop->PostTask(FROM_HERE, loop->QuitClosure()); |
| 92 } |
87 } | 93 } |
88 | 94 |
89 private: | 95 private: |
90 // The current status of the listener. | 96 // The current status of the listener. |
91 STATUS status_; | 97 STATUS status_; |
92 // If |quit_only_on_message_| then the listener will only break out of | 98 // If |quit_only_on_message_| then the listener will only break out of |
93 // the run loop when kQuitMessage is received. | 99 // the run loop when kQuitMessage is received. |
94 bool quit_only_on_message_; | 100 bool quit_only_on_message_; |
95 }; | 101 }; |
96 | 102 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 } | 185 } |
180 handle->socket.fd = socket_fd; | 186 handle->socket.fd = socket_fd; |
181 } | 187 } |
182 | 188 |
183 void IPCChannelPosixTest::SpinRunLoop(base::TimeDelta delay) { | 189 void IPCChannelPosixTest::SpinRunLoop(base::TimeDelta delay) { |
184 base::MessageLoopForIO* loop = base::MessageLoopForIO::current(); | 190 base::MessageLoopForIO* loop = base::MessageLoopForIO::current(); |
185 // Post a quit task so that this loop eventually ends and we don't hang | 191 // Post a quit task so that this loop eventually ends and we don't hang |
186 // in the case of a bad test. Usually, the run loop will quit sooner than | 192 // in the case of a bad test. Usually, the run loop will quit sooner than |
187 // that because all tests use a IPCChannelPosixTestListener which quits the | 193 // that because all tests use a IPCChannelPosixTestListener which quits the |
188 // current run loop on any channel activity. | 194 // current run loop on any channel activity. |
189 loop->PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(), delay); | 195 loop->PostDelayedTask(FROM_HERE, loop->QuitClosure(), delay); |
190 loop->Run(); | 196 loop->Run(); |
191 } | 197 } |
192 | 198 |
193 TEST_F(IPCChannelPosixTest, BasicListen) { | 199 TEST_F(IPCChannelPosixTest, BasicListen) { |
194 const std::string kChannelName = | 200 const std::string kChannelName = |
195 GetChannelDirName() + "/IPCChannelPosixTest_BasicListen"; | 201 GetChannelDirName() + "/IPCChannelPosixTest_BasicListen"; |
196 | 202 |
197 // Test creating a socket that is listening. | 203 // Test creating a socket that is listening. |
198 IPC::ChannelHandle handle(kChannelName); | 204 IPC::ChannelHandle handle(kChannelName); |
199 SetUpSocket(&handle, IPC::Channel::MODE_NAMED_SERVER); | 205 SetUpSocket(&handle, IPC::Channel::MODE_NAMED_SERVER); |
(...skipping 21 matching lines...) Expand all Loading... |
221 channel.Close(); | 227 channel.Close(); |
222 ASSERT_TRUE(IGNORE_EINTR(close(pipe_fds[1])) == 0); | 228 ASSERT_TRUE(IGNORE_EINTR(close(pipe_fds[1])) == 0); |
223 | 229 |
224 // Make sure that we can use the socket that is created for us by | 230 // Make sure that we can use the socket that is created for us by |
225 // a standard channel. | 231 // a standard channel. |
226 IPC::Channel channel2(socket_name, IPC::Channel::MODE_SERVER, NULL); | 232 IPC::Channel channel2(socket_name, IPC::Channel::MODE_SERVER, NULL); |
227 ASSERT_TRUE(channel2.Connect()); | 233 ASSERT_TRUE(channel2.Connect()); |
228 ASSERT_FALSE(channel2.AcceptsConnections()); | 234 ASSERT_FALSE(channel2.AcceptsConnections()); |
229 } | 235 } |
230 | 236 |
| 237 // If a connection closes right before a Send() call, we may end up closing |
| 238 // the connection without notifying the listener, which can cause hangs in |
| 239 // sync_message_filter and others. Make sure the listener is notified. |
| 240 TEST_F(IPCChannelPosixTest, SendHangTest) { |
| 241 IPCChannelPosixTestListener out_listener(true); |
| 242 IPCChannelPosixTestListener in_listener(true); |
| 243 IPC::ChannelHandle in_handle("IN"); |
| 244 IPC::Channel in_chan(in_handle, IPC::Channel::MODE_SERVER, &in_listener); |
| 245 base::FileDescriptor out_fd(in_chan.TakeClientFileDescriptor(), false); |
| 246 IPC::ChannelHandle out_handle("OUT", out_fd); |
| 247 IPC::Channel out_chan(out_handle, IPC::Channel::MODE_CLIENT, &out_listener); |
| 248 ASSERT_TRUE(in_chan.Connect()); |
| 249 ASSERT_TRUE(out_chan.Connect()); |
| 250 in_chan.Close(); // simulate remote process dying at an unfortunate time. |
| 251 // Send will fail, because it cannot write the message. |
| 252 ASSERT_FALSE(out_chan.Send(new IPC::Message( |
| 253 0, // routing_id |
| 254 kQuitMessage, // message type |
| 255 IPC::Message::PRIORITY_NORMAL))); |
| 256 SpinRunLoop(TestTimeouts::action_max_timeout()); |
| 257 ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, out_listener.status()); |
| 258 } |
| 259 |
| 260 // If a connection closes right before a Connect() call, we may end up closing |
| 261 // the connection without notifying the listener, which can cause hangs in |
| 262 // sync_message_filter and others. Make sure the listener is notified. |
| 263 TEST_F(IPCChannelPosixTest, AcceptHangTest) { |
| 264 IPCChannelPosixTestListener out_listener(true); |
| 265 IPCChannelPosixTestListener in_listener(true); |
| 266 IPC::ChannelHandle in_handle("IN"); |
| 267 IPC::Channel in_chan(in_handle, IPC::Channel::MODE_SERVER, &in_listener); |
| 268 base::FileDescriptor out_fd(in_chan.TakeClientFileDescriptor(), false); |
| 269 IPC::ChannelHandle out_handle("OUT", out_fd); |
| 270 IPC::Channel out_chan(out_handle, IPC::Channel::MODE_CLIENT, &out_listener); |
| 271 ASSERT_TRUE(in_chan.Connect()); |
| 272 in_chan.Close(); // simulate remote process dying at an unfortunate time. |
| 273 ASSERT_FALSE(out_chan.Connect()); |
| 274 SpinRunLoop(TestTimeouts::action_max_timeout()); |
| 275 ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, out_listener.status()); |
| 276 } |
| 277 |
231 TEST_F(IPCChannelPosixTest, AdvancedConnected) { | 278 TEST_F(IPCChannelPosixTest, AdvancedConnected) { |
232 // Test creating a connection to an external process. | 279 // Test creating a connection to an external process. |
233 IPCChannelPosixTestListener listener(false); | 280 IPCChannelPosixTestListener listener(false); |
234 IPC::ChannelHandle chan_handle(GetConnectionSocketName()); | 281 IPC::ChannelHandle chan_handle(GetConnectionSocketName()); |
235 SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER); | 282 SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER); |
236 IPC::Channel channel(chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener); | 283 IPC::Channel channel(chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener); |
237 ASSERT_TRUE(channel.Connect()); | 284 ASSERT_TRUE(channel.Connect()); |
238 ASSERT_TRUE(channel.AcceptsConnections()); | 285 ASSERT_TRUE(channel.AcceptsConnections()); |
239 ASSERT_FALSE(channel.HasAcceptedConnection()); | 286 ASSERT_FALSE(channel.HasAcceptedConnection()); |
240 | 287 |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 if (connected) { | 464 if (connected) { |
418 IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout()); | 465 IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout()); |
419 EXPECT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status()); | 466 EXPECT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status()); |
420 } else { | 467 } else { |
421 EXPECT_EQ(IPCChannelPosixTestListener::DISCONNECTED, listener.status()); | 468 EXPECT_EQ(IPCChannelPosixTestListener::DISCONNECTED, listener.status()); |
422 } | 469 } |
423 return 0; | 470 return 0; |
424 } | 471 } |
425 | 472 |
426 } // namespace | 473 } // namespace |
OLD | NEW |