Index: ipc/mojo/ipc_channel_mojo_unittest.cc |
diff --git a/ipc/mojo/ipc_channel_mojo_unittest.cc b/ipc/mojo/ipc_channel_mojo_unittest.cc |
index 8ea828f4fb01f131848f65d431df9dfd4aad7d79..4a0cbd0f2e3f2d65fccb548735c3cf34986c9f99 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,155 @@ MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) { |
return 0; |
} |
+ |
+// To make WriteMessageToPipe() fail. |
+class ErraticMessageReader : public IPC::internal::MessageReader { |
+ public: |
+ ErraticMessageReader(mojo::ScopedMessagePipeHandle pipe, |
+ IPC::ChannelMojo* owner) |
+ : IPC::internal::MessageReader(pipe.Pass(), owner) { |
+ } |
+ |
+ virtual MojoResult WriteMessageToPipe( |
+ const void* bytes, |
+ uint32_t num_bytes, |
+ const MojoHandle* handles, |
+ uint32_t num_handles, |
+ MojoWriteMessageFlags flags) OVERRIDE { |
+ return MOJO_RESULT_UNKNOWN; |
+ } |
+ |
yzshen1
2014/09/15 17:26:08
unnecessary empty line
Hajime Morrita
2014/09/15 18:16:53
Done.
|
+}; |
+ |
+// Exists to create ErraticMessageReader |
yzshen1
2014/09/15 17:26:08
nit: trailing '.', please. (and line 188, 259)
Hajime Morrita
2014/09/15 18:16:53
Done.
|
+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 scoped_ptr<IPC::internal::MessageReader> CreateMessageReader( |
+ mojo::ScopedMessagePipeHandle pipe) OVERRIDE { |
+ return scoped_ptr<IPC::internal::MessageReader>( |
+ new ErraticMessageReader(pipe.Pass(), this)); |
+ } |
+ |
+}; |
+ |
+// 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. |
yzshen1
2014/09/15 17:26:07
This -> These
|
+ for (size_t i = 0; i < 2; ++i) { |
+ IPC::TestChannelListener::SendOneMessage( |
+ sender(), "hello from parent"); |
+ } |
+ |
+ // This triggers ChannelMojo::OnConnected(), which hits |
+ // crbug.com/410813 |
+ 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: |