Adding Peter Thatcher to the owners file.
[chromium-blink-merge.git] / ipc / ipc_channel_proxy_unittest.cc
blobe7ebe64bd82fdda165a2b9dd33f2a2a3dcd23acd
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"
28 namespace IPC {
29 #include "ipc/ipc_channel_proxy_unittest_messages.h"
30 } // namespace IPC
32 // Generate param traits read methods.
33 #include "ipc/param_traits_read_macros.h"
34 namespace IPC {
35 #include "ipc/ipc_channel_proxy_unittest_messages.h"
36 } // namespace IPC
38 // Generate param traits log methods.
39 #include "ipc/param_traits_log_macros.h"
40 namespace IPC {
41 #include "ipc/ipc_channel_proxy_unittest_messages.h"
42 } // namespace IPC
45 namespace {
47 class QuitListener : public IPC::Listener {
48 public:
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)
55 IPC_END_MESSAGE_MAP()
56 return true;
59 void OnBadMessageReceived(const IPC::Message& message) override {
60 bad_message_received_ = true;
63 void OnQuit() {
64 base::MessageLoop::current()->QuitWhenIdle();
67 void OnBadMessage(const BadType& bad_type) {
68 // Should never be called since IPC wouldn't be deserialized correctly.
69 CHECK(false);
72 bool bad_message_received_;
75 class ChannelReflectorListener : public IPC::Listener {
76 public:
77 ChannelReflectorListener() : channel_(NULL) {}
79 void Init(IPC::Channel* channel) {
80 DCHECK(!channel_);
81 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)
91 IPC_END_MESSAGE_MAP()
92 return true;
95 void OnTestBounce() {
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());
107 void OnBounce() {
108 channel_->Send(new WorkerMsg_Bounce());
111 void OnQuit() {
112 channel_->Send(new WorkerMsg_Quit());
113 base::MessageLoop::current()->QuitWhenIdle();
116 private:
117 IPC::Channel* channel_;
120 class MessageCountFilter : public IPC::MessageFilter {
121 public:
122 enum FilterEvent {
123 NONE,
124 FILTER_ADDED,
125 CHANNEL_CONNECTED,
126 CHANNEL_ERROR,
127 CHANNEL_CLOSING,
128 FILTER_REMOVED
130 MessageCountFilter()
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 {
145 EXPECT_TRUE(sender);
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_)
189 return false;
191 bool handled = true;
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()
196 return handled;
199 void OnBadMessage(const BadType& bad_type) {
200 // Should never be called since IPC wouldn't be deserialized correctly.
201 CHECK(false);
204 bool GetSupportedMessageClasses(
205 std::vector<uint32>* supported_message_classes) const override {
206 if (is_global_filter_)
207 return false;
208 supported_message_classes->push_back(supported_message_class_);
209 return true;
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_; }
219 private:
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 {
231 public:
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();
253 thread_.reset();
254 listener_.reset();
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_;
268 private:
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
322 // QUIT message.
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 {
380 public:
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 {
394 listener_.reset();
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_;
408 private:
409 scoped_ptr<QuitListener> listener_;
412 #if !defined(OS_WIN)
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());
419 #endif
421 #endif
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"),
428 &listener));
429 CHECK(channel->Connect());
430 listener.Init(channel.get());
432 base::MessageLoop::current()->Run();
433 return 0;
436 } // namespace