Sort string IDs used in Files.app and friends.
[chromium-blink-merge.git] / ipc / ipc_channel_proxy_unittest.cc
blob848367ec782bd2e481d7b3deba85b8b916ae09a0
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) {}
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)
56 IPC_END_MESSAGE_MAP()
57 return true;
60 void OnBadMessageReceived(const IPC::Message& message) override {
61 bad_message_received_ = true;
64 void OnQuit() {
65 base::MessageLoop::current()->QuitWhenIdle();
68 void OnBadMessage(const BadType& bad_type) {
69 // Should never be called since IPC wouldn't be deserialized correctly.
70 CHECK(false);
73 bool bad_message_received_;
76 class ChannelReflectorListener : public IPC::Listener {
77 public:
78 ChannelReflectorListener() : channel_(NULL) {}
79 ~ChannelReflectorListener() override {}
81 void Init(IPC::Channel* channel) {
82 DCHECK(!channel_);
83 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)
93 IPC_END_MESSAGE_MAP()
94 return true;
97 void OnTestBounce() {
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());
109 void OnBounce() {
110 channel_->Send(new WorkerMsg_Bounce());
113 void OnQuit() {
114 channel_->Send(new WorkerMsg_Quit());
115 base::MessageLoop::current()->QuitWhenIdle();
118 private:
119 IPC::Channel* channel_;
122 class MessageCountFilter : public IPC::MessageFilter {
123 public:
124 enum FilterEvent {
125 NONE,
126 FILTER_ADDED,
127 CHANNEL_CONNECTED,
128 CHANNEL_ERROR,
129 CHANNEL_CLOSING,
130 FILTER_REMOVED
132 MessageCountFilter()
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 {
147 EXPECT_TRUE(sender);
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_)
191 return false;
193 bool handled = true;
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()
198 return handled;
201 void OnBadMessage(const BadType& bad_type) {
202 // Should never be called since IPC wouldn't be deserialized correctly.
203 CHECK(false);
206 bool GetSupportedMessageClasses(
207 std::vector<uint32>* supported_message_classes) const override {
208 if (is_global_filter_)
209 return false;
210 supported_message_classes->push_back(supported_message_class_);
211 return true;
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_; }
221 private:
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 {
233 public:
234 IPCChannelProxyTest() {}
235 virtual ~IPCChannelProxyTest() {}
237 virtual 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 virtual void TearDown() {
254 DestroyChannelProxy();
255 thread_.reset();
256 listener_.reset();
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_;
270 private:
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
324 // QUIT message.
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 {
382 public:
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() {
399 listener_.reset();
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_;
413 private:
414 scoped_ptr<QuitListener> listener_;
417 #if !defined(OS_WIN)
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());
424 #endif
426 #endif
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"),
433 &listener));
434 CHECK(channel->Connect());
435 listener.Init(channel.get());
437 base::MessageLoop::current()->Run();
438 return 0;
441 } // namespace