diff options
author | morrita <morrita@chromium.org> | 2014-09-15 20:20:48 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-16 03:21:58 +0000 |
commit | 0a24cfc91484cc092603abf3863690dafe61311e (patch) | |
tree | 90dc1e96404f39cd99f02b5b3390a60a980f94b6 /ipc/mojo/ipc_channel_mojo_unittest.cc | |
parent | 57400f1712e531b11d2b08f6f3aa2a11b334c9f6 (diff) | |
download | chromium_src-0a24cfc91484cc092603abf3863690dafe61311e.zip chromium_src-0a24cfc91484cc092603abf3863690dafe61311e.tar.gz chromium_src-0a24cfc91484cc092603abf3863690dafe61311e.tar.bz2 |
ChannelMojo: Handle errors in pending message processing.
ChannelMojo::OnConnect() ignores errors in Send() but the error
results deleting |message_readrer_| which causes null access.
This CL add an error check for that.
This also adds some hooks to make this testable by
faking lower level API.
TEST=ipc_channel_mojo_unittest.cc
BUG=410813
R=yzshen@chromium.org, viettrungluu@chromium.org
Review URL: https://codereview.chromium.org/554363004
Cr-Commit-Position: refs/heads/master@{#294997}
Diffstat (limited to 'ipc/mojo/ipc_channel_mojo_unittest.cc')
-rw-r--r-- | ipc/mojo/ipc_channel_mojo_unittest.cc | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/ipc/mojo/ipc_channel_mojo_unittest.cc b/ipc/mojo/ipc_channel_mojo_unittest.cc index 8ea828f..2b9a954 100644 --- a/ipc/mojo/ipc_channel_mojo_unittest.cc +++ b/ipc/mojo/ipc_channel_mojo_unittest.cc @@ -13,6 +13,7 @@ #include "ipc/ipc_message.h" #include "ipc/ipc_test_base.h" #include "ipc/ipc_test_channel_listener.h" +#include "ipc/mojo/ipc_channel_mojo_readers.h" #if defined(OS_POSIX) #include "base/file_descriptor_posix.h" @@ -145,6 +146,131 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) { return 0; } +// Close given handle before use to simulate an error. +class ErraticChannelMojo : public IPC::ChannelMojo { + public: + ErraticChannelMojo( + const IPC::ChannelHandle& channel_handle, + IPC::Channel::Mode mode, + IPC::Listener* listener, + scoped_refptr<base::TaskRunner> runner) + : ChannelMojo(channel_handle, mode, listener, runner) { + } + + virtual void OnConnected(mojo::ScopedMessagePipeHandle pipe) { + MojoClose(pipe.get().value()); + OnConnected(pipe.Pass()); + } +}; + +// Exists to create ErraticChannelMojo. +class ErraticChannelFactory : public IPC::ChannelFactory { + public: + explicit ErraticChannelFactory( + const IPC::ChannelHandle& handle, + base::TaskRunner* runner) + : handle_(handle), runner_(runner) { + } + + virtual std::string GetName() const OVERRIDE { + return ""; + } + + virtual scoped_ptr<IPC::Channel> BuildChannel( + IPC::Listener* listener) OVERRIDE { + return scoped_ptr<IPC::Channel>( + new ErraticChannelMojo( + handle_, IPC::Channel::MODE_SERVER, listener, runner_)); + } + + private: + IPC::ChannelHandle handle_; + scoped_refptr<base::TaskRunner> runner_; +}; + +class ListenerExpectingErrors : public IPC::Listener { + public: + ListenerExpectingErrors() + : has_error_(false) { + } + + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { + return true; + } + + virtual void OnChannelError() OVERRIDE { + has_error_ = true; + base::MessageLoop::current()->Quit(); + } + + bool has_error() const { return has_error_; } + + private: + bool has_error_; +}; + + +class IPCChannelMojoErrorTest : public IPCTestBase { + protected: + virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory( + const IPC::ChannelHandle& handle, + base::TaskRunner* runner) OVERRIDE { + return scoped_ptr<IPC::ChannelFactory>( + new ErraticChannelFactory(handle, runner)); + } +}; + +class ListenerThatQuits : public IPC::Listener { + public: + ListenerThatQuits() { + } + + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { + return true; + } + + virtual void OnChannelConnected(int32 peer_pid) OVERRIDE { + base::MessageLoop::current()->Quit(); + } +}; + +// A long running process that connects to us. +MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient) { + ListenerThatQuits listener; + ChannelClient client(&listener, "IPCChannelMojoErraticTestClient"); + client.Connect(); + + base::MessageLoop::current()->Run(); + + return 0; +} + +TEST_F(IPCChannelMojoErrorTest, SendFailWithPendingMessages) { + Init("IPCChannelMojoErraticTestClient"); + + // Set up IPC channel and start client. + ListenerExpectingErrors listener; + CreateChannel(&listener); + ASSERT_TRUE(ConnectChannel()); + + // This messages are queued as pending. + for (size_t i = 0; i < 2; ++i) { + IPC::TestChannelListener::SendOneMessage( + sender(), "hello from parent"); + } + + ASSERT_TRUE(StartClient()); + base::MessageLoop::current()->Run(); + + this->channel()->Close(); + + EXPECT_TRUE(WaitForClientShutdown()); + EXPECT_TRUE(listener.has_error()); + + DestroyChannel(); +} + + #if defined(OS_POSIX) class ListenerThatExpectsFile : public IPC::Listener { public: |