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) {}
51 bool OnMessageReceived(const IPC::Message
& message
) override
{
52 IPC_BEGIN_MESSAGE_MAP(QuitListener
, message
)
53 IPC_MESSAGE_HANDLER(WorkerMsg_Quit
, OnQuit
)
54 IPC_MESSAGE_HANDLER(TestMsg_BadMessage
, OnBadMessage
)
59 void OnBadMessageReceived(const IPC::Message
& message
) override
{
60 bad_message_received_
= true;
64 base::MessageLoop::current()->QuitWhenIdle();
67 void OnBadMessage(const BadType
& bad_type
) {
68 // Should never be called since IPC wouldn't be deserialized correctly.
72 bool bad_message_received_
;
75 class ChannelReflectorListener
: public IPC::Listener
{
77 ChannelReflectorListener() : channel_(NULL
) {}
79 void Init(IPC::Channel
* channel
) {
84 bool OnMessageReceived(const IPC::Message
& message
) override
{
85 IPC_BEGIN_MESSAGE_MAP(ChannelReflectorListener
, message
)
86 IPC_MESSAGE_HANDLER(TestMsg_Bounce
, OnTestBounce
)
87 IPC_MESSAGE_HANDLER(TestMsg_SendBadMessage
, OnSendBadMessage
)
88 IPC_MESSAGE_HANDLER(UtilityMsg_Bounce
, OnUtilityBounce
)
89 IPC_MESSAGE_HANDLER(WorkerMsg_Bounce
, OnBounce
)
90 IPC_MESSAGE_HANDLER(WorkerMsg_Quit
, OnQuit
)
96 channel_
->Send(new TestMsg_Bounce());
99 void OnSendBadMessage() {
100 channel_
->Send(new TestMsg_BadMessage(BadType()));
103 void OnUtilityBounce() {
104 channel_
->Send(new UtilityMsg_Bounce());
108 channel_
->Send(new WorkerMsg_Bounce());
112 channel_
->Send(new WorkerMsg_Quit());
113 base::MessageLoop::current()->QuitWhenIdle();
117 IPC::Channel
* channel_
;
120 class MessageCountFilter
: public IPC::MessageFilter
{
131 : messages_received_(0),
132 supported_message_class_(0),
133 is_global_filter_(true),
134 last_filter_event_(NONE
),
135 message_filtering_enabled_(false) {}
137 MessageCountFilter(uint32 supported_message_class
)
138 : messages_received_(0),
139 supported_message_class_(supported_message_class
),
140 is_global_filter_(false),
141 last_filter_event_(NONE
),
142 message_filtering_enabled_(false) {}
144 void OnFilterAdded(IPC::Sender
* sender
) override
{
146 EXPECT_EQ(NONE
, last_filter_event_
);
147 last_filter_event_
= FILTER_ADDED
;
150 void OnChannelConnected(int32_t peer_pid
) override
{
151 EXPECT_EQ(FILTER_ADDED
, last_filter_event_
);
152 EXPECT_NE(static_cast<int32_t>(base::kNullProcessId
), peer_pid
);
153 last_filter_event_
= CHANNEL_CONNECTED
;
156 void OnChannelError() override
{
157 EXPECT_EQ(CHANNEL_CONNECTED
, last_filter_event_
);
158 last_filter_event_
= CHANNEL_ERROR
;
161 void OnChannelClosing() override
{
162 // We may or may not have gotten OnChannelError; if not, the last event has
163 // to be OnChannelConnected.
164 if (last_filter_event_
!= CHANNEL_ERROR
)
165 EXPECT_EQ(CHANNEL_CONNECTED
, last_filter_event_
);
166 last_filter_event_
= CHANNEL_CLOSING
;
169 void OnFilterRemoved() override
{
170 // If the channel didn't get a chance to connect, we might see the
171 // OnFilterRemoved event with no other events preceding it. We still want
172 // OnFilterRemoved to be called to allow for deleting the Filter.
173 if (last_filter_event_
!= NONE
)
174 EXPECT_EQ(CHANNEL_CLOSING
, last_filter_event_
);
175 last_filter_event_
= FILTER_REMOVED
;
178 bool OnMessageReceived(const IPC::Message
& message
) override
{
179 // We should always get the OnFilterAdded and OnChannelConnected events
180 // prior to any messages.
181 EXPECT_EQ(CHANNEL_CONNECTED
, last_filter_event_
);
183 if (!is_global_filter_
) {
184 EXPECT_EQ(supported_message_class_
, IPC_MESSAGE_CLASS(message
));
186 ++messages_received_
;
188 if (!message_filtering_enabled_
)
192 IPC_BEGIN_MESSAGE_MAP(MessageCountFilter
, message
)
193 IPC_MESSAGE_HANDLER(TestMsg_BadMessage
, OnBadMessage
)
194 IPC_MESSAGE_UNHANDLED(handled
= false)
195 IPC_END_MESSAGE_MAP()
199 void OnBadMessage(const BadType
& bad_type
) {
200 // Should never be called since IPC wouldn't be deserialized correctly.
204 bool GetSupportedMessageClasses(
205 std::vector
<uint32
>* supported_message_classes
) const override
{
206 if (is_global_filter_
)
208 supported_message_classes
->push_back(supported_message_class_
);
212 void set_message_filtering_enabled(bool enabled
) {
213 message_filtering_enabled_
= enabled
;
216 size_t messages_received() const { return messages_received_
; }
217 FilterEvent
last_filter_event() const { return last_filter_event_
; }
220 ~MessageCountFilter() override
{}
222 size_t messages_received_
;
223 uint32 supported_message_class_
;
224 bool is_global_filter_
;
226 FilterEvent last_filter_event_
;
227 bool message_filtering_enabled_
;
230 class IPCChannelProxyTest
: public IPCTestBase
{
232 IPCChannelProxyTest() {}
233 ~IPCChannelProxyTest() override
{}
235 void SetUp() override
{
236 IPCTestBase::SetUp();
238 Init("ChannelProxyClient");
240 thread_
.reset(new base::Thread("ChannelProxyTestServerThread"));
241 base::Thread::Options options
;
242 options
.message_loop_type
= base::MessageLoop::TYPE_IO
;
243 thread_
->StartWithOptions(options
);
245 listener_
.reset(new QuitListener());
246 CreateChannelProxy(listener_
.get(), thread_
->message_loop_proxy().get());
248 ASSERT_TRUE(StartClient());
251 void TearDown() override
{
252 DestroyChannelProxy();
255 IPCTestBase::TearDown();
258 void SendQuitMessageAndWaitForIdle() {
259 sender()->Send(new WorkerMsg_Quit
);
260 base::MessageLoop::current()->Run();
261 EXPECT_TRUE(WaitForClientShutdown());
264 bool DidListenerGetBadMessage() {
265 return listener_
->bad_message_received_
;
269 scoped_ptr
<base::Thread
> thread_
;
270 scoped_ptr
<QuitListener
> listener_
;
273 TEST_F(IPCChannelProxyTest
, MessageClassFilters
) {
274 // Construct a filter per message class.
275 std::vector
<scoped_refptr
<MessageCountFilter
> > class_filters
;
276 class_filters
.push_back(make_scoped_refptr(
277 new MessageCountFilter(TestMsgStart
)));
278 class_filters
.push_back(make_scoped_refptr(
279 new MessageCountFilter(UtilityMsgStart
)));
280 for (size_t i
= 0; i
< class_filters
.size(); ++i
)
281 channel_proxy()->AddFilter(class_filters
[i
].get());
283 // Send a message for each class; each filter should receive just one message.
284 sender()->Send(new TestMsg_Bounce());
285 sender()->Send(new UtilityMsg_Bounce());
287 // Send some messages not assigned to a specific or valid message class.
288 sender()->Send(new WorkerMsg_Bounce
);
290 // Each filter should have received just the one sent message of the
291 // corresponding class.
292 SendQuitMessageAndWaitForIdle();
293 for (size_t i
= 0; i
< class_filters
.size(); ++i
)
294 EXPECT_EQ(1U, class_filters
[i
]->messages_received());
297 TEST_F(IPCChannelProxyTest
, GlobalAndMessageClassFilters
) {
298 // Add a class and global filter.
299 scoped_refptr
<MessageCountFilter
> class_filter(
300 new MessageCountFilter(TestMsgStart
));
301 class_filter
->set_message_filtering_enabled(false);
302 channel_proxy()->AddFilter(class_filter
.get());
304 scoped_refptr
<MessageCountFilter
> global_filter(new MessageCountFilter());
305 global_filter
->set_message_filtering_enabled(false);
306 channel_proxy()->AddFilter(global_filter
.get());
308 // A message of class Test should be seen by both the global filter and
309 // Test-specific filter.
310 sender()->Send(new TestMsg_Bounce
);
312 // A message of a different class should be seen only by the global filter.
313 sender()->Send(new UtilityMsg_Bounce
);
315 // Flush all messages.
316 SendQuitMessageAndWaitForIdle();
318 // The class filter should have received only the class-specific message.
319 EXPECT_EQ(1U, class_filter
->messages_received());
321 // The global filter should have received both messages, as well as the final
323 EXPECT_EQ(3U, global_filter
->messages_received());
326 TEST_F(IPCChannelProxyTest
, FilterRemoval
) {
327 // Add a class and global filter.
328 scoped_refptr
<MessageCountFilter
> class_filter(
329 new MessageCountFilter(TestMsgStart
));
330 scoped_refptr
<MessageCountFilter
> global_filter(new MessageCountFilter());
332 // Add and remove both types of filters.
333 channel_proxy()->AddFilter(class_filter
.get());
334 channel_proxy()->AddFilter(global_filter
.get());
335 channel_proxy()->RemoveFilter(global_filter
.get());
336 channel_proxy()->RemoveFilter(class_filter
.get());
338 // Send some messages; they should not be seen by either filter.
339 sender()->Send(new TestMsg_Bounce
);
340 sender()->Send(new UtilityMsg_Bounce
);
342 // Ensure that the filters were removed and did not receive any messages.
343 SendQuitMessageAndWaitForIdle();
344 EXPECT_EQ(MessageCountFilter::FILTER_REMOVED
,
345 global_filter
->last_filter_event());
346 EXPECT_EQ(MessageCountFilter::FILTER_REMOVED
,
347 class_filter
->last_filter_event());
348 EXPECT_EQ(0U, class_filter
->messages_received());
349 EXPECT_EQ(0U, global_filter
->messages_received());
352 // The test that follow trigger DCHECKS in debug build.
353 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
355 TEST_F(IPCChannelProxyTest
, BadMessageOnListenerThread
) {
356 scoped_refptr
<MessageCountFilter
> class_filter(
357 new MessageCountFilter(TestMsgStart
));
358 class_filter
->set_message_filtering_enabled(false);
359 channel_proxy()->AddFilter(class_filter
.get());
361 sender()->Send(new TestMsg_SendBadMessage());
363 SendQuitMessageAndWaitForIdle();
364 EXPECT_TRUE(DidListenerGetBadMessage());
367 TEST_F(IPCChannelProxyTest
, BadMessageOnIPCThread
) {
368 scoped_refptr
<MessageCountFilter
> class_filter(
369 new MessageCountFilter(TestMsgStart
));
370 class_filter
->set_message_filtering_enabled(true);
371 channel_proxy()->AddFilter(class_filter
.get());
373 sender()->Send(new TestMsg_SendBadMessage());
375 SendQuitMessageAndWaitForIdle();
376 EXPECT_TRUE(DidListenerGetBadMessage());
379 class IPCChannelBadMessageTest
: public IPCTestBase
{
381 void SetUp() override
{
382 IPCTestBase::SetUp();
384 Init("ChannelProxyClient");
386 listener_
.reset(new QuitListener());
387 CreateChannel(listener_
.get());
388 ASSERT_TRUE(ConnectChannel());
390 ASSERT_TRUE(StartClient());
393 void TearDown() override
{
395 IPCTestBase::TearDown();
398 void SendQuitMessageAndWaitForIdle() {
399 sender()->Send(new WorkerMsg_Quit
);
400 base::MessageLoop::current()->Run();
401 EXPECT_TRUE(WaitForClientShutdown());
404 bool DidListenerGetBadMessage() {
405 return listener_
->bad_message_received_
;
409 scoped_ptr
<QuitListener
> listener_
;
413 // TODO(jam): for some reason this is flaky on win buildbots.
414 TEST_F(IPCChannelBadMessageTest
, BadMessage
) {
415 sender()->Send(new TestMsg_SendBadMessage());
416 SendQuitMessageAndWaitForIdle();
417 EXPECT_TRUE(DidListenerGetBadMessage());
423 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ChannelProxyClient
) {
424 base::MessageLoopForIO main_message_loop
;
425 ChannelReflectorListener listener
;
426 scoped_ptr
<IPC::Channel
> channel(IPC::Channel::CreateClient(
427 IPCTestBase::GetChannelName("ChannelProxyClient"),
429 CHECK(channel
->Connect());
430 listener
.Init(channel
.get());
432 base::MessageLoop::current()->Run();