diff options
Diffstat (limited to 'chromium/ipc/ipc_channel_posix_unittest.cc')
-rw-r--r-- | chromium/ipc/ipc_channel_posix_unittest.cc | 202 |
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()); |