summaryrefslogtreecommitdiffstats
path: root/chromium/ipc/ipc_channel_posix_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ipc/ipc_channel_posix_unittest.cc')
-rw-r--r--chromium/ipc/ipc_channel_posix_unittest.cc202
1 files changed, 132 insertions, 70 deletions
diff --git a/chromium/ipc/ipc_channel_posix_unittest.cc b/chromium/ipc/ipc_channel_posix_unittest.cc
index dbd854e16c6..a4b4f8dbb95 100644
--- a/chromium/ipc/ipc_channel_posix_unittest.cc
+++ b/chromium/ipc/ipc_channel_posix_unittest.cc
@@ -41,7 +41,9 @@ class IPCChannelPosixTestListener : public IPC::Listener {
};
IPCChannelPosixTestListener(bool quit_only_on_message)
- : status_(DISCONNECTED), quit_only_on_message_(quit_only_on_message) {}
+ : status_(DISCONNECTED),
+ quit_only_on_message_(quit_only_on_message) {
+ }
virtual ~IPCChannelPosixTestListener() {}
@@ -61,9 +63,7 @@ class IPCChannelPosixTestListener : public IPC::Listener {
virtual void OnChannelError() OVERRIDE {
status_ = CHANNEL_ERROR;
- if (!quit_only_on_message_) {
- QuitRunLoop();
- }
+ QuitRunLoop();
}
virtual void OnChannelDenied() OVERRIDE {
@@ -83,7 +83,13 @@ class IPCChannelPosixTestListener : public IPC::Listener {
STATUS status() { return status_; }
void QuitRunLoop() {
- base::MessageLoopForIO::current()->QuitNow();
+ base::MessageLoopForIO* loop = base::MessageLoopForIO::current();
+ if (loop->is_running()) {
+ loop->QuitNow();
+ } else {
+ // Die as soon as Run is called.
+ loop->PostTask(FROM_HERE, loop->QuitClosure());
+ }
}
private:
@@ -186,7 +192,7 @@ void IPCChannelPosixTest::SpinRunLoop(base::TimeDelta delay) {
// in the case of a bad test. Usually, the run loop will quit sooner than
// that because all tests use a IPCChannelPosixTestListener which quits the
// current run loop on any channel activity.
- loop->PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(), delay);
+ loop->PostDelayedTask(FROM_HERE, loop->QuitClosure(), delay);
loop->Run();
}
@@ -198,12 +204,13 @@ TEST_F(IPCChannelPosixTest, BasicListen) {
IPC::ChannelHandle handle(kChannelName);
SetUpSocket(&handle, IPC::Channel::MODE_NAMED_SERVER);
unlink(handle.name.c_str());
- IPC::Channel channel(handle, IPC::Channel::MODE_NAMED_SERVER, NULL);
- ASSERT_TRUE(channel.Connect());
- ASSERT_TRUE(channel.AcceptsConnections());
- ASSERT_FALSE(channel.HasAcceptedConnection());
- channel.ResetToAcceptingConnectionState();
- ASSERT_FALSE(channel.HasAcceptedConnection());
+ scoped_ptr<IPC::ChannelPosix> channel(
+ new IPC::ChannelPosix(handle, IPC::Channel::MODE_NAMED_SERVER, NULL));
+ ASSERT_TRUE(channel->Connect());
+ ASSERT_TRUE(channel->AcceptsConnections());
+ ASSERT_FALSE(channel->HasAcceptedConnection());
+ channel->ResetToAcceptingConnectionState();
+ ASSERT_FALSE(channel->HasAcceptedConnection());
}
TEST_F(IPCChannelPosixTest, BasicConnected) {
@@ -215,17 +222,66 @@ TEST_F(IPCChannelPosixTest, BasicConnected) {
base::FileDescriptor fd(pipe_fds[0], false);
IPC::ChannelHandle handle(socket_name, fd);
- IPC::Channel channel(handle, IPC::Channel::MODE_SERVER, NULL);
- ASSERT_TRUE(channel.Connect());
- ASSERT_FALSE(channel.AcceptsConnections());
- channel.Close();
+ scoped_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix(
+ handle, IPC::Channel::MODE_SERVER, NULL));
+ ASSERT_TRUE(channel->Connect());
+ ASSERT_FALSE(channel->AcceptsConnections());
+ channel->Close();
ASSERT_TRUE(IGNORE_EINTR(close(pipe_fds[1])) == 0);
// Make sure that we can use the socket that is created for us by
// a standard channel.
- IPC::Channel channel2(socket_name, IPC::Channel::MODE_SERVER, NULL);
- ASSERT_TRUE(channel2.Connect());
- ASSERT_FALSE(channel2.AcceptsConnections());
+ scoped_ptr<IPC::ChannelPosix> channel2(new IPC::ChannelPosix(
+ socket_name, IPC::Channel::MODE_SERVER, NULL));
+ ASSERT_TRUE(channel2->Connect());
+ ASSERT_FALSE(channel2->AcceptsConnections());
+}
+
+// If a connection closes right before a Send() call, we may end up closing
+// the connection without notifying the listener, which can cause hangs in
+// sync_message_filter and others. Make sure the listener is notified.
+TEST_F(IPCChannelPosixTest, SendHangTest) {
+ IPCChannelPosixTestListener out_listener(true);
+ IPCChannelPosixTestListener in_listener(true);
+ IPC::ChannelHandle in_handle("IN");
+ scoped_ptr<IPC::ChannelPosix> in_chan(new IPC::ChannelPosix(
+ in_handle, IPC::Channel::MODE_SERVER, &in_listener));
+ base::FileDescriptor out_fd(
+ in_chan->TakeClientFileDescriptor(), false);
+ IPC::ChannelHandle out_handle("OUT", out_fd);
+ scoped_ptr<IPC::ChannelPosix> out_chan(new IPC::ChannelPosix(
+ out_handle, IPC::Channel::MODE_CLIENT, &out_listener));
+ ASSERT_TRUE(in_chan->Connect());
+ ASSERT_TRUE(out_chan->Connect());
+ in_chan->Close(); // simulate remote process dying at an unfortunate time.
+ // Send will fail, because it cannot write the message.
+ ASSERT_FALSE(out_chan->Send(new IPC::Message(
+ 0, // routing_id
+ kQuitMessage, // message type
+ IPC::Message::PRIORITY_NORMAL)));
+ SpinRunLoop(TestTimeouts::action_max_timeout());
+ ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, out_listener.status());
+}
+
+// If a connection closes right before a Connect() call, we may end up closing
+// the connection without notifying the listener, which can cause hangs in
+// sync_message_filter and others. Make sure the listener is notified.
+TEST_F(IPCChannelPosixTest, AcceptHangTest) {
+ IPCChannelPosixTestListener out_listener(true);
+ IPCChannelPosixTestListener in_listener(true);
+ IPC::ChannelHandle in_handle("IN");
+ scoped_ptr<IPC::ChannelPosix> in_chan(new IPC::ChannelPosix(
+ in_handle, IPC::Channel::MODE_SERVER, &in_listener));
+ base::FileDescriptor out_fd(
+ in_chan->TakeClientFileDescriptor(), false);
+ IPC::ChannelHandle out_handle("OUT", out_fd);
+ scoped_ptr<IPC::ChannelPosix> out_chan(new IPC::ChannelPosix(
+ out_handle, IPC::Channel::MODE_CLIENT, &out_listener));
+ ASSERT_TRUE(in_chan->Connect());
+ in_chan->Close(); // simulate remote process dying at an unfortunate time.
+ ASSERT_FALSE(out_chan->Connect());
+ SpinRunLoop(TestTimeouts::action_max_timeout());
+ ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, out_listener.status());
}
TEST_F(IPCChannelPosixTest, AdvancedConnected) {
@@ -233,27 +289,27 @@ TEST_F(IPCChannelPosixTest, AdvancedConnected) {
IPCChannelPosixTestListener listener(false);
IPC::ChannelHandle chan_handle(GetConnectionSocketName());
SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER);
- IPC::Channel channel(chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener);
- ASSERT_TRUE(channel.Connect());
- ASSERT_TRUE(channel.AcceptsConnections());
- ASSERT_FALSE(channel.HasAcceptedConnection());
+ scoped_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix(
+ chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener));
+ ASSERT_TRUE(channel->Connect());
+ ASSERT_TRUE(channel->AcceptsConnections());
+ ASSERT_FALSE(channel->HasAcceptedConnection());
- base::ProcessHandle handle = SpawnChild("IPCChannelPosixTestConnectionProc",
- false);
+ base::ProcessHandle handle = SpawnChild("IPCChannelPosixTestConnectionProc");
ASSERT_TRUE(handle);
SpinRunLoop(TestTimeouts::action_max_timeout());
ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status());
- ASSERT_TRUE(channel.HasAcceptedConnection());
+ ASSERT_TRUE(channel->HasAcceptedConnection());
IPC::Message* message = new IPC::Message(0, // routing_id
kQuitMessage, // message type
IPC::Message::PRIORITY_NORMAL);
- channel.Send(message);
+ channel->Send(message);
SpinRunLoop(TestTimeouts::action_timeout());
int exit_code = 0;
EXPECT_TRUE(base::WaitForExitCode(handle, &exit_code));
EXPECT_EQ(0, exit_code);
ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status());
- ASSERT_FALSE(channel.HasAcceptedConnection());
+ ASSERT_FALSE(channel->HasAcceptedConnection());
}
TEST_F(IPCChannelPosixTest, ResetState) {
@@ -263,44 +319,44 @@ TEST_F(IPCChannelPosixTest, ResetState) {
IPCChannelPosixTestListener listener(false);
IPC::ChannelHandle chan_handle(GetConnectionSocketName());
SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER);
- IPC::Channel channel(chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener);
- ASSERT_TRUE(channel.Connect());
- ASSERT_TRUE(channel.AcceptsConnections());
- ASSERT_FALSE(channel.HasAcceptedConnection());
+ scoped_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix(
+ chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener));
+ ASSERT_TRUE(channel->Connect());
+ ASSERT_TRUE(channel->AcceptsConnections());
+ ASSERT_FALSE(channel->HasAcceptedConnection());
- base::ProcessHandle handle = SpawnChild("IPCChannelPosixTestConnectionProc",
- false);
+ base::ProcessHandle handle = SpawnChild("IPCChannelPosixTestConnectionProc");
ASSERT_TRUE(handle);
SpinRunLoop(TestTimeouts::action_max_timeout());
ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status());
- ASSERT_TRUE(channel.HasAcceptedConnection());
- channel.ResetToAcceptingConnectionState();
- ASSERT_FALSE(channel.HasAcceptedConnection());
+ ASSERT_TRUE(channel->HasAcceptedConnection());
+ channel->ResetToAcceptingConnectionState();
+ ASSERT_FALSE(channel->HasAcceptedConnection());
- base::ProcessHandle handle2 = SpawnChild("IPCChannelPosixTestConnectionProc",
- false);
+ base::ProcessHandle handle2 = SpawnChild("IPCChannelPosixTestConnectionProc");
ASSERT_TRUE(handle2);
SpinRunLoop(TestTimeouts::action_max_timeout());
ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status());
- ASSERT_TRUE(channel.HasAcceptedConnection());
+ ASSERT_TRUE(channel->HasAcceptedConnection());
IPC::Message* message = new IPC::Message(0, // routing_id
kQuitMessage, // message type
IPC::Message::PRIORITY_NORMAL);
- channel.Send(message);
+ channel->Send(message);
SpinRunLoop(TestTimeouts::action_timeout());
EXPECT_TRUE(base::KillProcess(handle, 0, false));
int exit_code = 0;
EXPECT_TRUE(base::WaitForExitCode(handle2, &exit_code));
EXPECT_EQ(0, exit_code);
ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status());
- ASSERT_FALSE(channel.HasAcceptedConnection());
+ ASSERT_FALSE(channel->HasAcceptedConnection());
}
TEST_F(IPCChannelPosixTest, BadChannelName) {
// Test empty name
IPC::ChannelHandle handle("");
- IPC::Channel channel(handle, IPC::Channel::MODE_NAMED_SERVER, NULL);
- ASSERT_FALSE(channel.Connect());
+ scoped_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix(
+ handle, IPC::Channel::MODE_NAMED_SERVER, NULL));
+ ASSERT_FALSE(channel->Connect());
// Test name that is too long.
const char *kTooLongName = "This_is_a_very_long_name_to_proactively_implement"
@@ -312,8 +368,9 @@ TEST_F(IPCChannelPosixTest, BadChannelName) {
"leading-edge_processes";
EXPECT_GE(strlen(kTooLongName), IPC::kMaxSocketNameLength);
IPC::ChannelHandle handle2(kTooLongName);
- IPC::Channel channel2(handle2, IPC::Channel::MODE_NAMED_SERVER, NULL);
- EXPECT_FALSE(channel2.Connect());
+ scoped_ptr<IPC::ChannelPosix> channel2(new IPC::ChannelPosix(
+ handle2, IPC::Channel::MODE_NAMED_SERVER, NULL));
+ EXPECT_FALSE(channel2->Connect());
}
TEST_F(IPCChannelPosixTest, MultiConnection) {
@@ -322,35 +379,34 @@ TEST_F(IPCChannelPosixTest, MultiConnection) {
IPCChannelPosixTestListener listener(false);
IPC::ChannelHandle chan_handle(GetConnectionSocketName());
SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER);
- IPC::Channel channel(chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener);
- ASSERT_TRUE(channel.Connect());
- ASSERT_TRUE(channel.AcceptsConnections());
- ASSERT_FALSE(channel.HasAcceptedConnection());
+ scoped_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix(
+ chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener));
+ ASSERT_TRUE(channel->Connect());
+ ASSERT_TRUE(channel->AcceptsConnections());
+ ASSERT_FALSE(channel->HasAcceptedConnection());
- base::ProcessHandle handle = SpawnChild("IPCChannelPosixTestConnectionProc",
- false);
+ base::ProcessHandle handle = SpawnChild("IPCChannelPosixTestConnectionProc");
ASSERT_TRUE(handle);
SpinRunLoop(TestTimeouts::action_max_timeout());
ASSERT_EQ(IPCChannelPosixTestListener::CONNECTED, listener.status());
- ASSERT_TRUE(channel.HasAcceptedConnection());
- base::ProcessHandle handle2 = SpawnChild("IPCChannelPosixFailConnectionProc",
- false);
+ ASSERT_TRUE(channel->HasAcceptedConnection());
+ base::ProcessHandle handle2 = SpawnChild("IPCChannelPosixFailConnectionProc");
ASSERT_TRUE(handle2);
SpinRunLoop(TestTimeouts::action_max_timeout());
int exit_code = 0;
EXPECT_TRUE(base::WaitForExitCode(handle2, &exit_code));
EXPECT_EQ(exit_code, 0);
ASSERT_EQ(IPCChannelPosixTestListener::DENIED, listener.status());
- ASSERT_TRUE(channel.HasAcceptedConnection());
+ ASSERT_TRUE(channel->HasAcceptedConnection());
IPC::Message* message = new IPC::Message(0, // routing_id
kQuitMessage, // message type
IPC::Message::PRIORITY_NORMAL);
- channel.Send(message);
+ channel->Send(message);
SpinRunLoop(TestTimeouts::action_timeout());
EXPECT_TRUE(base::WaitForExitCode(handle, &exit_code));
EXPECT_EQ(exit_code, 0);
ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status());
- ASSERT_FALSE(channel.HasAcceptedConnection());
+ ASSERT_FALSE(channel->HasAcceptedConnection());
}
TEST_F(IPCChannelPosixTest, DoubleServer) {
@@ -358,18 +414,21 @@ TEST_F(IPCChannelPosixTest, DoubleServer) {
IPCChannelPosixTestListener listener(false);
IPCChannelPosixTestListener listener2(false);
IPC::ChannelHandle chan_handle(GetConnectionSocketName());
- IPC::Channel channel(chan_handle, IPC::Channel::MODE_SERVER, &listener);
- IPC::Channel channel2(chan_handle, IPC::Channel::MODE_SERVER, &listener2);
- ASSERT_TRUE(channel.Connect());
- ASSERT_FALSE(channel2.Connect());
+ scoped_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix(
+ chan_handle, IPC::Channel::MODE_SERVER, &listener));
+ scoped_ptr<IPC::ChannelPosix> channel2(new IPC::ChannelPosix(
+ chan_handle, IPC::Channel::MODE_SERVER, &listener2));
+ ASSERT_TRUE(channel->Connect());
+ ASSERT_FALSE(channel2->Connect());
}
TEST_F(IPCChannelPosixTest, BadMode) {
// Test setting up two servers with a bad mode.
IPCChannelPosixTestListener listener(false);
IPC::ChannelHandle chan_handle(GetConnectionSocketName());
- IPC::Channel channel(chan_handle, IPC::Channel::MODE_NONE, &listener);
- ASSERT_FALSE(channel.Connect());
+ scoped_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix(
+ chan_handle, IPC::Channel::MODE_NONE, &listener));
+ ASSERT_FALSE(channel->Connect());
}
TEST_F(IPCChannelPosixTest, IsNamedServerInitialized) {
@@ -379,10 +438,11 @@ TEST_F(IPCChannelPosixTest, IsNamedServerInitialized) {
ASSERT_TRUE(base::DeleteFile(base::FilePath(connection_socket_name), false));
ASSERT_FALSE(IPC::Channel::IsNamedServerInitialized(
connection_socket_name));
- IPC::Channel channel(chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener);
+ scoped_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix(
+ chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener));
ASSERT_TRUE(IPC::Channel::IsNamedServerInitialized(
connection_socket_name));
- channel.Close();
+ channel->Close();
ASSERT_FALSE(IPC::Channel::IsNamedServerInitialized(
connection_socket_name));
}
@@ -393,8 +453,9 @@ MULTIPROCESS_TEST_MAIN(IPCChannelPosixTestConnectionProc) {
IPCChannelPosixTestListener listener(true);
IPC::ChannelHandle handle(IPCChannelPosixTest::GetConnectionSocketName());
IPCChannelPosixTest::SetUpSocket(&handle, IPC::Channel::MODE_NAMED_CLIENT);
- IPC::Channel channel(handle, IPC::Channel::MODE_NAMED_CLIENT, &listener);
- EXPECT_TRUE(channel.Connect());
+ scoped_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix(
+ handle, IPC::Channel::MODE_NAMED_CLIENT, &listener));
+ EXPECT_TRUE(channel->Connect());
IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout());
EXPECT_EQ(IPCChannelPosixTestListener::MESSAGE_RECEIVED, listener.status());
return 0;
@@ -406,14 +467,15 @@ MULTIPROCESS_TEST_MAIN(IPCChannelPosixFailConnectionProc) {
IPCChannelPosixTestListener listener(false);
IPC::ChannelHandle handle(IPCChannelPosixTest::GetConnectionSocketName());
IPCChannelPosixTest::SetUpSocket(&handle, IPC::Channel::MODE_NAMED_CLIENT);
- IPC::Channel channel(handle, IPC::Channel::MODE_NAMED_CLIENT, &listener);
+ scoped_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix(
+ handle, IPC::Channel::MODE_NAMED_CLIENT, &listener));
// In this case connect may succeed or fail depending on if the packet
// actually gets sent at sendmsg. Since we never delay on send, we may not
// see the error. However even if connect succeeds, eventually we will get an
// error back since the channel will be closed when we attempt to read from
// it.
- bool connected = channel.Connect();
+ bool connected = channel->Connect();
if (connected) {
IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout());
EXPECT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status());