1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "build/build_config.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/pickle.h"
9 #include "base/threading/thread.h"
10 #include "ipc/ipc_message.h"
11 #include "ipc/ipc_test_base.h"
12 #include "ipc/message_filter.h"
14 // Get basic type definitions.
15 #define IPC_MESSAGE_IMPL
16 #include "ipc/ipc_channel_proxy_unittest_messages.h"
18 // Generate constructors.
19 #include "ipc/struct_constructor_macros.h"
20 #include "ipc/ipc_channel_proxy_unittest_messages.h"
22 // Generate destructors.
23 #include "ipc/struct_destructor_macros.h"
24 #include "ipc/ipc_channel_proxy_unittest_messages.h"
26 // Generate param traits write methods.
27 #include "ipc/param_traits_write_macros.h"
29 #include "ipc/ipc_channel_proxy_unittest_messages.h"
32 // Generate param traits read methods.
33 #include "ipc/param_traits_read_macros.h"
35 #include "ipc/ipc_channel_proxy_unittest_messages.h"
38 // Generate param traits log methods.
39 #include "ipc/param_traits_log_macros.h"
41 #include "ipc/ipc_channel_proxy_unittest_messages.h"
47 class QuitListener
: public IPC::Listener
{
49 QuitListener() : bad_message_received_(false) {}
50 ~QuitListener() override
{}
52 bool OnMessageReceived(const IPC::Message
& message
) override
{
53 IPC_BEGIN_MESSAGE_MAP(QuitListener
, message
)
54 IPC_MESSAGE_HANDLER(WorkerMsg_Quit
, OnQuit
)
55 IPC_MESSAGE_HANDLER(TestMsg_BadMessage
, OnBadMessage
)
60 void OnBadMessageReceived(const IPC::Message
& message
) override
{
61 bad_message_received_
= true;
65 base::MessageLoop::current()->QuitWhenIdle();
68 void OnBadMessage(const BadType
& bad_type
) {
69 // Should never be called since IPC wouldn't be deserialized correctly.
73 bool bad_message_received_
;
76 class ChannelReflectorListener
: public IPC::Listener
{
78 ChannelReflectorListener() : channel_(NULL
) {}
79 ~ChannelReflectorListener() override
{}
81 void Init(IPC::Channel
* channel
) {
86 bool OnMessageReceived(const IPC::Message
& message
) override
{
87 IPC_BEGIN_MESSAGE_MAP(ChannelReflectorListener
, message
)
88 IPC_MESSAGE_HANDLER(TestMsg_Bounce
, OnTestBounce
)
89 IPC_MESSAGE_HANDLER(TestMsg_SendBadMessage
, OnSendBadMessage
)
90 IPC_MESSAGE_HANDLER(UtilityMsg_Bounce
, OnUtilityBounce
)
91 IPC_MESSAGE_HANDLER(WorkerMsg_Bounce
, OnBounce
)
92 IPC_MESSAGE_HANDLER(WorkerMsg_Quit
, OnQuit
)
98 channel_
->Send(new TestMsg_Bounce());
101 void OnSendBadMessage() {
102 channel_
->Send(new TestMsg_BadMessage(BadType()));
105 void OnUtilityBounce() {
106 channel_
->Send(new UtilityMsg_Bounce());
110 channel_
->Send(new WorkerMsg_Bounce());
114 channel_
->Send(new WorkerMsg_Quit());
115 base::MessageLoop::current()->QuitWhenIdle();
119 IPC::Channel
* channel_
;
122 class MessageCountFilter
: public IPC::MessageFilter
{
133 : messages_received_(0),
134 supported_message_class_(0),
135 is_global_filter_(true),
136 last_filter_event_(NONE
),
137 message_filtering_enabled_(false) {}
139 MessageCountFilter(uint32 supported_message_class
)
140 : messages_received_(0),
141 supported_message_class_(supported_message_class
),
142 is_global_filter_(false),
143 last_filter_event_(NONE
),
144 message_filtering_enabled_(false) {}
146 void OnFilterAdded(IPC::Sender
* sender
) override
{
148 EXPECT_EQ(NONE
, last_filter_event_
);
149 last_filter_event_
= FILTER_ADDED
;
152 void OnChannelConnected(int32_t peer_pid
) override
{
153 EXPECT_EQ(FILTER_ADDED
, last_filter_event_
);
154 EXPECT_NE(static_cast<int32_t>(base::kNullProcessId
), peer_pid
);
155 last_filter_event_
= CHANNEL_CONNECTED
;
158 void OnChannelError() override
{
159 EXPECT_EQ(CHANNEL_CONNECTED
, last_filter_event_
);
160 last_filter_event_
= CHANNEL_ERROR
;
163 void OnChannelClosing() override
{
164 // We may or may not have gotten OnChannelError; if not, the last event has
165 // to be OnChannelConnected.
166 if (last_filter_event_
!= CHANNEL_ERROR
)
167 EXPECT_EQ(CHANNEL_CONNECTED
, last_filter_event_
);
168 last_filter_event_
= CHANNEL_CLOSING
;
171 void OnFilterRemoved() override
{
172 // If the channel didn't get a chance to connect, we might see the
173 // OnFilterRemoved event with no other events preceding it. We still want
174 // OnFilterRemoved to be called to allow for deleting the Filter.
175 if (last_filter_event_
!= NONE
)
176 EXPECT_EQ(CHANNEL_CLOSING
, last_filter_event_
);
177 last_filter_event_
= FILTER_REMOVED
;
180 bool OnMessageReceived(const IPC::Message
& message
) override
{
181 // We should always get the OnFilterAdded and OnChannelConnected events
182 // prior to any messages.
183 EXPECT_EQ(CHANNEL_CONNECTED
, last_filter_event_
);
185 if (!is_global_filter_
) {
186 EXPECT_EQ(supported_message_class_
, IPC_MESSAGE_CLASS(message
));
188 ++messages_received_
;
190 if (!message_filtering_enabled_
)
194 IPC_BEGIN_MESSAGE_MAP(MessageCountFilter
, message
)
195 IPC_MESSAGE_HANDLER(TestMsg_BadMessage
, OnBadMessage
)
196 IPC_MESSAGE_UNHANDLED(handled
= false)
197 IPC_END_MESSAGE_MAP()
201 void OnBadMessage(const BadType
& bad_type
) {
202 // Should never be called since IPC wouldn't be deserialized correctly.
206 bool GetSupportedMessageClasses(
207 std::vector
<uint32
>* supported_message_classes
) const override
{
208 if (is_global_filter_
)
210 supported_message_classes
->push_back(supported_message_class_
);
214 void set_message_filtering_enabled(bool enabled
) {
215 message_filtering_enabled_
= enabled
;
218 size_t messages_received() const { return messages_received_
; }
219 FilterEvent
last_filter_event() const { return last_filter_event_
; }
222 ~MessageCountFilter() override
{}
224 size_t messages_received_
;
225 uint32 supported_message_class_
;
226 bool is_global_filter_
;
228 FilterEvent last_filter_event_
;
229 bool message_filtering_enabled_
;
232 class IPCChannelProxyTest
: public IPCTestBase
{
234 IPCChannelProxyTest() {}
235 ~IPCChannelProxyTest() override
{}
237 void SetUp() override
{
238 IPCTestBase::SetUp();
240 Init("ChannelProxyClient");
242 thread_
.reset(new base::Thread("ChannelProxyTestServerThread"));
243 base::Thread::Options options
;
244 options
.message_loop_type
= base::MessageLoop::TYPE_IO
;
245 thread_
->StartWithOptions(options
);
247 listener_
.reset(new QuitListener());
248 CreateChannelProxy(listener_
.get(), thread_
->message_loop_proxy().get());
250 ASSERT_TRUE(StartClient());
253 void TearDown() override
{
254 DestroyChannelProxy();
257 IPCTestBase::TearDown();
260 void SendQuitMessageAndWaitForIdle() {
261 sender()->Send(new WorkerMsg_Quit
);
262 base::MessageLoop::current()->Run();
263 EXPECT_TRUE(WaitForClientShutdown());
266 bool DidListenerGetBadMessage() {
267 return listener_
->bad_message_received_
;
271 scoped_ptr
<base::Thread
> thread_
;
272 scoped_ptr
<QuitListener
> listener_
;
275 TEST_F(IPCChannelProxyTest
, MessageClassFilters
) {
276 // Construct a filter per message class.
277 std::vector
<scoped_refptr
<MessageCountFilter
> > class_filters
;
278 class_filters
.push_back(make_scoped_refptr(
279 new MessageCountFilter(TestMsgStart
)));
280 class_filters
.push_back(make_scoped_refptr(
281 new MessageCountFilter(UtilityMsgStart
)));
282 for (size_t i
= 0; i
< class_filters
.size(); ++i
)
283 channel_proxy()->AddFilter(class_filters
[i
].get());
285 // Send a message for each class; each filter should receive just one message.
286 sender()->Send(new TestMsg_Bounce());
287 sender()->Send(new UtilityMsg_Bounce());
289 // Send some messages not assigned to a specific or valid message class.
290 sender()->Send(new WorkerMsg_Bounce
);
292 // Each filter should have received just the one sent message of the
293 // corresponding class.
294 SendQuitMessageAndWaitForIdle();
295 for (size_t i
= 0; i
< class_filters
.size(); ++i
)
296 EXPECT_EQ(1U, class_filters
[i
]->messages_received());
299 TEST_F(IPCChannelProxyTest
, GlobalAndMessageClassFilters
) {
300 // Add a class and global filter.
301 scoped_refptr
<MessageCountFilter
> class_filter(
302 new MessageCountFilter(TestMsgStart
));
303 class_filter
->set_message_filtering_enabled(false);
304 channel_proxy()->AddFilter(class_filter
.get());
306 scoped_refptr
<MessageCountFilter
> global_filter(new MessageCountFilter());
307 global_filter
->set_message_filtering_enabled(false);
308 channel_proxy()->AddFilter(global_filter
.get());
310 // A message of class Test should be seen by both the global filter and
311 // Test-specific filter.
312 sender()->Send(new TestMsg_Bounce
);
314 // A message of a different class should be seen only by the global filter.
315 sender()->Send(new UtilityMsg_Bounce
);
317 // Flush all messages.
318 SendQuitMessageAndWaitForIdle();
320 // The class filter should have received only the class-specific message.
321 EXPECT_EQ(1U, class_filter
->messages_received());
323 // The global filter should have received both messages, as well as the final
325 EXPECT_EQ(3U, global_filter
->messages_received());
328 TEST_F(IPCChannelProxyTest
, FilterRemoval
) {
329 // Add a class and global filter.
330 scoped_refptr
<MessageCountFilter
> class_filter(
331 new MessageCountFilter(TestMsgStart
));
332 scoped_refptr
<MessageCountFilter
> global_filter(new MessageCountFilter());
334 // Add and remove both types of filters.
335 channel_proxy()->AddFilter(class_filter
.get());
336 channel_proxy()->AddFilter(global_filter
.get());
337 channel_proxy()->RemoveFilter(global_filter
.get());
338 channel_proxy()->RemoveFilter(class_filter
.get());
340 // Send some messages; they should not be seen by either filter.
341 sender()->Send(new TestMsg_Bounce
);
342 sender()->Send(new UtilityMsg_Bounce
);
344 // Ensure that the filters were removed and did not receive any messages.
345 SendQuitMessageAndWaitForIdle();
346 EXPECT_EQ(MessageCountFilter::FILTER_REMOVED
,
347 global_filter
->last_filter_event());
348 EXPECT_EQ(MessageCountFilter::FILTER_REMOVED
,
349 class_filter
->last_filter_event());
350 EXPECT_EQ(0U, class_filter
->messages_received());
351 EXPECT_EQ(0U, global_filter
->messages_received());
354 // The test that follow trigger DCHECKS in debug build.
355 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
357 TEST_F(IPCChannelProxyTest
, BadMessageOnListenerThread
) {
358 scoped_refptr
<MessageCountFilter
> class_filter(
359 new MessageCountFilter(TestMsgStart
));
360 class_filter
->set_message_filtering_enabled(false);
361 channel_proxy()->AddFilter(class_filter
.get());
363 sender()->Send(new TestMsg_SendBadMessage());
365 SendQuitMessageAndWaitForIdle();
366 EXPECT_TRUE(DidListenerGetBadMessage());
369 TEST_F(IPCChannelProxyTest
, BadMessageOnIPCThread
) {
370 scoped_refptr
<MessageCountFilter
> class_filter(
371 new MessageCountFilter(TestMsgStart
));
372 class_filter
->set_message_filtering_enabled(true);
373 channel_proxy()->AddFilter(class_filter
.get());
375 sender()->Send(new TestMsg_SendBadMessage());
377 SendQuitMessageAndWaitForIdle();
378 EXPECT_TRUE(DidListenerGetBadMessage());
381 class IPCChannelBadMessageTest
: public IPCTestBase
{
383 IPCChannelBadMessageTest() {}
384 virtual ~IPCChannelBadMessageTest() {}
386 virtual void SetUp() override
{
387 IPCTestBase::SetUp();
389 Init("ChannelProxyClient");
391 listener_
.reset(new QuitListener());
392 CreateChannel(listener_
.get());
393 ASSERT_TRUE(ConnectChannel());
395 ASSERT_TRUE(StartClient());
398 virtual void TearDown() {
400 IPCTestBase::TearDown();
403 void SendQuitMessageAndWaitForIdle() {
404 sender()->Send(new WorkerMsg_Quit
);
405 base::MessageLoop::current()->Run();
406 EXPECT_TRUE(WaitForClientShutdown());
409 bool DidListenerGetBadMessage() {
410 return listener_
->bad_message_received_
;
414 scoped_ptr
<QuitListener
> listener_
;
418 // TODO(jam): for some reason this is flaky on win buildbots.
419 TEST_F(IPCChannelBadMessageTest
, BadMessage
) {
420 sender()->Send(new TestMsg_SendBadMessage());
421 SendQuitMessageAndWaitForIdle();
422 EXPECT_TRUE(DidListenerGetBadMessage());
428 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ChannelProxyClient
) {
429 base::MessageLoopForIO main_message_loop
;
430 ChannelReflectorListener listener
;
431 scoped_ptr
<IPC::Channel
> channel(IPC::Channel::CreateClient(
432 IPCTestBase::GetChannelName("ChannelProxyClient"),
434 CHECK(channel
->Connect());
435 listener
.Init(channel
.get());
437 base::MessageLoop::current()->Run();