Index: ipc/ipc_channel_proxy_unittest.cc |
=================================================================== |
--- ipc/ipc_channel_proxy_unittest.cc (revision 271102) |
+++ ipc/ipc_channel_proxy_unittest.cc (working copy) |
@@ -8,47 +8,69 @@ |
#include "base/pickle.h" |
#include "base/threading/thread.h" |
#include "ipc/ipc_message.h" |
-#include "ipc/ipc_message_macros.h" |
#include "ipc/ipc_test_base.h" |
#include "ipc/message_filter.h" |
-namespace { |
+// Get basic type definitions. |
+#define IPC_MESSAGE_IMPL |
+#include "ipc/ipc_channel_proxy_unittest_messages.h" |
-#if defined(IPC_MESSAGE_START) |
-#undef IPC_MESSAGE_START |
-#endif |
+// Generate constructors. |
+#include "ipc/struct_constructor_macros.h" |
+#include "ipc/ipc_channel_proxy_unittest_messages.h" |
-enum Command { |
- SEND, |
- QUIT |
-}; |
+// Generate destructors. |
+#include "ipc/struct_destructor_macros.h" |
+#include "ipc/ipc_channel_proxy_unittest_messages.h" |
-static void Send(IPC::Sender* sender, |
- int message_class, |
- Command command) { |
- const int IPC_MESSAGE_START = message_class; |
- IPC::Message* message = new IPC::Message(0, |
- IPC_MESSAGE_ID(), |
- IPC::Message::PRIORITY_NORMAL); |
- message->WriteInt(command); |
- sender->Send(message); |
-} |
+// Generate param traits write methods. |
+#include "ipc/param_traits_write_macros.h" |
+namespace IPC { |
+#include "ipc/ipc_channel_proxy_unittest_messages.h" |
+} // namespace IPC |
+// Generate param traits read methods. |
+#include "ipc/param_traits_read_macros.h" |
+namespace IPC { |
+#include "ipc/ipc_channel_proxy_unittest_messages.h" |
+} // namespace IPC |
+ |
+// Generate param traits log methods. |
+#include "ipc/param_traits_log_macros.h" |
+namespace IPC { |
+#include "ipc/ipc_channel_proxy_unittest_messages.h" |
+} // namespace IPC |
+ |
+ |
+namespace { |
+ |
class QuitListener : public IPC::Listener { |
public: |
- QuitListener() {} |
+ QuitListener() : bad_message_received_(false) {} |
virtual ~QuitListener() {} |
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
- PickleIterator iter(message); |
+ IPC_BEGIN_MESSAGE_MAP(QuitListener, message) |
+ IPC_MESSAGE_HANDLER(WorkerMsg_Quit, OnQuit) |
+ IPC_MESSAGE_HANDLER(TestMsg_BadMessage, OnBadMessage) |
+ IPC_END_MESSAGE_MAP() |
+ return true; |
+ } |
- int command = SEND; |
- EXPECT_TRUE(iter.ReadInt(&command)); |
- if (command == QUIT) |
- base::MessageLoop::current()->QuitWhenIdle(); |
+ virtual void OnBadMessageReceived(const IPC::Message& message) OVERRIDE { |
+ bad_message_received_ = true; |
+ } |
- return true; |
+ void OnQuit() { |
+ base::MessageLoop::current()->QuitWhenIdle(); |
} |
+ |
+ void OnBadMessage(const BadType& bad_type) { |
+ // Should never be called since IPC wouldn't be deserialized correctly. |
+ CHECK(false); |
+ } |
+ |
+ bool bad_message_received_; |
}; |
class ChannelReflectorListener : public IPC::Listener { |
@@ -62,22 +84,37 @@ |
} |
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
- CHECK(channel_); |
+ IPC_BEGIN_MESSAGE_MAP(ChannelReflectorListener, message) |
+ IPC_MESSAGE_HANDLER(TestMsg_Bounce, OnTestBounce) |
+ IPC_MESSAGE_HANDLER(TestMsg_SendBadMessage, OnSendBadMessage) |
+ IPC_MESSAGE_HANDLER(UtilityMsg_Bounce, OnUtilityBounce) |
+ IPC_MESSAGE_HANDLER(WorkerMsg_Bounce, OnBounce) |
+ IPC_MESSAGE_HANDLER(WorkerMsg_Quit, OnQuit) |
+ IPC_END_MESSAGE_MAP() |
+ return true; |
+ } |
- PickleIterator iter(message); |
+ void OnTestBounce() { |
+ channel_->Send(new TestMsg_Bounce()); |
+ } |
- int command = SEND; |
- EXPECT_TRUE(iter.ReadInt(&command)); |
- if (command == QUIT) { |
- channel_->Send(new IPC::Message(message)); |
- base::MessageLoop::current()->QuitWhenIdle(); |
- return true; |
- } |
+ void OnSendBadMessage() { |
+ channel_->Send(new TestMsg_BadMessage(BadType())); |
+ } |
- channel_->Send(new IPC::Message(message)); |
- return true; |
+ void OnUtilityBounce() { |
+ channel_->Send(new UtilityMsg_Bounce()); |
} |
+ void OnBounce() { |
+ channel_->Send(new WorkerMsg_Bounce()); |
+ } |
+ |
+ void OnQuit() { |
+ channel_->Send(new WorkerMsg_Quit()); |
+ base::MessageLoop::current()->QuitWhenIdle(); |
+ } |
+ |
private: |
IPC::Channel* channel_; |
}; |
@@ -149,9 +186,23 @@ |
EXPECT_EQ(supported_message_class_, IPC_MESSAGE_CLASS(message)); |
} |
++messages_received_; |
- return message_filtering_enabled_; |
+ |
+ if (!message_filtering_enabled_) |
+ return false; |
+ |
+ bool handled = true; |
+ IPC_BEGIN_MESSAGE_MAP(MessageCountFilter, message) |
+ IPC_MESSAGE_HANDLER(TestMsg_BadMessage, OnBadMessage) |
+ IPC_MESSAGE_UNHANDLED(handled = false) |
+ IPC_END_MESSAGE_MAP() |
+ return handled; |
} |
+ void OnBadMessage(const BadType& bad_type) { |
+ // Should never be called since IPC wouldn't be deserialized correctly. |
+ CHECK(false); |
+ } |
+ |
virtual bool GetSupportedMessageClasses( |
std::vector<uint32>* supported_message_classes) const OVERRIDE { |
if (is_global_filter_) |
@@ -207,11 +258,15 @@ |
} |
void SendQuitMessageAndWaitForIdle() { |
- Send(sender(), -1, QUIT); |
+ sender()->Send(new WorkerMsg_Quit); |
base::MessageLoop::current()->Run(); |
EXPECT_TRUE(WaitForClientShutdown()); |
} |
+ bool DidListenerGetBadMessage() { |
+ return listener_->bad_message_received_; |
+ } |
+ |
private: |
scoped_ptr<base::Thread> thread_; |
scoped_ptr<QuitListener> listener_; |
@@ -220,20 +275,19 @@ |
TEST_F(IPCChannelProxyTest, MessageClassFilters) { |
// Construct a filter per message class. |
std::vector<scoped_refptr<MessageCountFilter> > class_filters; |
- for (uint32 i = 0; i < LastIPCMsgStart; ++i) { |
- class_filters.push_back(make_scoped_refptr( |
- new MessageCountFilter(i))); |
- channel_proxy()->AddFilter(class_filters.back().get()); |
- } |
+ class_filters.push_back(make_scoped_refptr( |
+ new MessageCountFilter(TestMsgStart))); |
+ class_filters.push_back(make_scoped_refptr( |
+ new MessageCountFilter(UtilityMsgStart))); |
+ for (size_t i = 0; i < class_filters.size(); ++i) |
+ channel_proxy()->AddFilter(class_filters[i].get()); |
// Send a message for each class; each filter should receive just one message. |
- for (uint32 i = 0; i < LastIPCMsgStart; ++i) |
- Send(sender(), i, SEND); |
+ sender()->Send(new TestMsg_Bounce()); |
+ sender()->Send(new UtilityMsg_Bounce()); |
// Send some messages not assigned to a specific or valid message class. |
- Send(sender(), -1, SEND); |
- Send(sender(), LastIPCMsgStart, SEND); |
- Send(sender(), LastIPCMsgStart + 1, SEND); |
+ sender()->Send(new WorkerMsg_Bounce); |
// Each filter should have received just the one sent message of the |
// corresponding class. |
@@ -244,9 +298,8 @@ |
TEST_F(IPCChannelProxyTest, GlobalAndMessageClassFilters) { |
// Add a class and global filter. |
- const int kMessageClass = 7; |
scoped_refptr<MessageCountFilter> class_filter( |
- new MessageCountFilter(kMessageClass)); |
+ new MessageCountFilter(TestMsgStart)); |
class_filter->set_message_filtering_enabled(false); |
channel_proxy()->AddFilter(class_filter.get()); |
@@ -254,12 +307,12 @@ |
global_filter->set_message_filtering_enabled(false); |
channel_proxy()->AddFilter(global_filter.get()); |
- // A message of class |kMessageClass| should be seen by both the global |
- // filter and |kMessageClass|-specific filter. |
- Send(sender(), kMessageClass, SEND); |
+ // A message of class Test should be seen by both the global filter and |
+ // Test-specific filter. |
+ sender()->Send(new TestMsg_Bounce); |
// A message of a different class should be seen only by the global filter. |
- Send(sender(), kMessageClass + 1, SEND); |
+ sender()->Send(new UtilityMsg_Bounce); |
// Flush all messages. |
SendQuitMessageAndWaitForIdle(); |
@@ -267,16 +320,15 @@ |
// The class filter should have received only the class-specific message. |
EXPECT_EQ(1U, class_filter->messages_received()); |
- // The global filter should have received both SEND messages, as well as the |
- // final QUIT message. |
+ // The global filter should have received both messages, as well as the final |
+ // QUIT message. |
EXPECT_EQ(3U, global_filter->messages_received()); |
} |
TEST_F(IPCChannelProxyTest, FilterRemoval) { |
// Add a class and global filter. |
- const int kMessageClass = 7; |
scoped_refptr<MessageCountFilter> class_filter( |
- new MessageCountFilter(kMessageClass)); |
+ new MessageCountFilter(TestMsgStart)); |
scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter()); |
// Add and remove both types of filters. |
@@ -286,8 +338,8 @@ |
channel_proxy()->RemoveFilter(class_filter.get()); |
// Send some messages; they should not be seen by either filter. |
- Send(sender(), 0, SEND); |
- Send(sender(), kMessageClass, SEND); |
+ sender()->Send(new TestMsg_Bounce); |
+ sender()->Send(new UtilityMsg_Bounce); |
// Ensure that the filters were removed and did not receive any messages. |
SendQuitMessageAndWaitForIdle(); |
@@ -299,6 +351,77 @@ |
EXPECT_EQ(0U, global_filter->messages_received()); |
} |
+// The test that follow trigger DCHECKS in debug build. |
+#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) |
+ |
+TEST_F(IPCChannelProxyTest, BadMessageOnListenerThread) { |
+ scoped_refptr<MessageCountFilter> class_filter( |
+ new MessageCountFilter(TestMsgStart)); |
+ class_filter->set_message_filtering_enabled(false); |
+ channel_proxy()->AddFilter(class_filter.get()); |
+ |
+ sender()->Send(new TestMsg_SendBadMessage()); |
+ |
+ SendQuitMessageAndWaitForIdle(); |
+ EXPECT_TRUE(DidListenerGetBadMessage()); |
+} |
+ |
+TEST_F(IPCChannelProxyTest, BadMessageOnIPCThread) { |
+ scoped_refptr<MessageCountFilter> class_filter( |
+ new MessageCountFilter(TestMsgStart)); |
+ class_filter->set_message_filtering_enabled(true); |
+ channel_proxy()->AddFilter(class_filter.get()); |
+ |
+ sender()->Send(new TestMsg_SendBadMessage()); |
+ |
+ SendQuitMessageAndWaitForIdle(); |
+ EXPECT_TRUE(DidListenerGetBadMessage()); |
+} |
+ |
+class IPCChannelBadMessageTest : public IPCTestBase { |
+ public: |
+ IPCChannelBadMessageTest() {} |
+ virtual ~IPCChannelBadMessageTest() {} |
+ |
+ virtual void SetUp() OVERRIDE { |
+ IPCTestBase::SetUp(); |
+ |
+ Init("ChannelProxyClient"); |
+ |
+ listener_.reset(new QuitListener()); |
+ CreateChannel(listener_.get()); |
+ ASSERT_TRUE(ConnectChannel()); |
+ |
+ ASSERT_TRUE(StartClient()); |
+ } |
+ |
+ virtual void TearDown() { |
+ listener_.reset(); |
+ IPCTestBase::TearDown(); |
+ } |
+ |
+ void SendQuitMessageAndWaitForIdle() { |
+ sender()->Send(new WorkerMsg_Quit); |
+ base::MessageLoop::current()->Run(); |
+ EXPECT_TRUE(WaitForClientShutdown()); |
+ } |
+ |
+ bool DidListenerGetBadMessage() { |
+ return listener_->bad_message_received_; |
+ } |
+ |
+ private: |
+ scoped_ptr<QuitListener> listener_; |
+}; |
+ |
+TEST_F(IPCChannelBadMessageTest, BadMessage) { |
+ sender()->Send(new TestMsg_SendBadMessage()); |
+ SendQuitMessageAndWaitForIdle(); |
+ EXPECT_TRUE(DidListenerGetBadMessage()); |
+} |
+ |
+#endif |
+ |
MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ChannelProxyClient) { |
base::MessageLoopForIO main_message_loop; |
ChannelReflectorListener listener; |