Add ICU message format support
[chromium-blink-merge.git] / ipc / ipc_channel_proxy_unittest.cc
blob3ec4c4337b5dfd1cdc7aa7fbf11180b9b33a7344
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/pickle.h"
8 #include "base/threading/thread.h"
9 #include "ipc/ipc_message.h"
10 #include "ipc/ipc_test_base.h"
11 #include "ipc/message_filter.h"
13 // Get basic type definitions.
14 #define IPC_MESSAGE_IMPL
15 #include "ipc/ipc_channel_proxy_unittest_messages.h"
17 // Generate constructors.
18 #include "ipc/struct_constructor_macros.h"
19 #include "ipc/ipc_channel_proxy_unittest_messages.h"
21 // Generate destructors.
22 #include "ipc/struct_destructor_macros.h"
23 #include "ipc/ipc_channel_proxy_unittest_messages.h"
25 // Generate param traits write methods.
26 #include "ipc/param_traits_write_macros.h"
27 namespace IPC {
28 #include "ipc/ipc_channel_proxy_unittest_messages.h"
29 } // namespace IPC
31 // Generate param traits read methods.
32 #include "ipc/param_traits_read_macros.h"
33 namespace IPC {
34 #include "ipc/ipc_channel_proxy_unittest_messages.h"
35 } // namespace IPC
37 // Generate param traits log methods.
38 #include "ipc/param_traits_log_macros.h"
39 namespace IPC {
40 #include "ipc/ipc_channel_proxy_unittest_messages.h"
41 } // namespace IPC
44 namespace {
46 class QuitListener : public IPC::Listener {
47 public:
48 QuitListener() : bad_message_received_(false) {}
50 bool OnMessageReceived(const IPC::Message& message) override {
51 IPC_BEGIN_MESSAGE_MAP(QuitListener, message)
52 IPC_MESSAGE_HANDLER(WorkerMsg_Quit, OnQuit)
53 IPC_MESSAGE_HANDLER(TestMsg_BadMessage, OnBadMessage)
54 IPC_END_MESSAGE_MAP()
55 return true;
58 void OnBadMessageReceived(const IPC::Message& message) override {
59 bad_message_received_ = true;
62 void OnQuit() {
63 base::MessageLoop::current()->QuitWhenIdle();
66 void OnBadMessage(const BadType& bad_type) {
67 // Should never be called since IPC wouldn't be deserialized correctly.
68 CHECK(false);
71 bool bad_message_received_;
74 class ChannelReflectorListener : public IPC::Listener {
75 public:
76 ChannelReflectorListener() : channel_(NULL) {}
78 void Init(IPC::Channel* channel) {
79 DCHECK(!channel_);
80 channel_ = channel;
83 bool OnMessageReceived(const IPC::Message& message) override {
84 IPC_BEGIN_MESSAGE_MAP(ChannelReflectorListener, message)
85 IPC_MESSAGE_HANDLER(TestMsg_Bounce, OnTestBounce)
86 IPC_MESSAGE_HANDLER(TestMsg_SendBadMessage, OnSendBadMessage)
87 IPC_MESSAGE_HANDLER(UtilityMsg_Bounce, OnUtilityBounce)
88 IPC_MESSAGE_HANDLER(WorkerMsg_Bounce, OnBounce)
89 IPC_MESSAGE_HANDLER(WorkerMsg_Quit, OnQuit)
90 IPC_END_MESSAGE_MAP()
91 return true;
94 void OnTestBounce() {
95 channel_->Send(new TestMsg_Bounce());
98 void OnSendBadMessage() {
99 channel_->Send(new TestMsg_BadMessage(BadType()));
102 void OnUtilityBounce() {
103 channel_->Send(new UtilityMsg_Bounce());
106 void OnBounce() {
107 channel_->Send(new WorkerMsg_Bounce());
110 void OnQuit() {
111 channel_->Send(new WorkerMsg_Quit());
112 base::MessageLoop::current()->QuitWhenIdle();
115 private:
116 IPC::Channel* channel_;
119 class MessageCountFilter : public IPC::MessageFilter {
120 public:
121 enum FilterEvent {
122 NONE,
123 FILTER_ADDED,
124 CHANNEL_CONNECTED,
125 CHANNEL_ERROR,
126 CHANNEL_CLOSING,
127 FILTER_REMOVED
129 MessageCountFilter()
130 : messages_received_(0),
131 supported_message_class_(0),
132 is_global_filter_(true),
133 last_filter_event_(NONE),
134 message_filtering_enabled_(false) {}
136 MessageCountFilter(uint32 supported_message_class)
137 : messages_received_(0),
138 supported_message_class_(supported_message_class),
139 is_global_filter_(false),
140 last_filter_event_(NONE),
141 message_filtering_enabled_(false) {}
143 void OnFilterAdded(IPC::Sender* sender) override {
144 EXPECT_TRUE(sender);
145 EXPECT_EQ(NONE, last_filter_event_);
146 last_filter_event_ = FILTER_ADDED;
149 void OnChannelConnected(int32_t peer_pid) override {
150 EXPECT_EQ(FILTER_ADDED, last_filter_event_);
151 EXPECT_NE(static_cast<int32_t>(base::kNullProcessId), peer_pid);
152 last_filter_event_ = CHANNEL_CONNECTED;
155 void OnChannelError() override {
156 EXPECT_EQ(CHANNEL_CONNECTED, last_filter_event_);
157 last_filter_event_ = CHANNEL_ERROR;
160 void OnChannelClosing() override {
161 // We may or may not have gotten OnChannelError; if not, the last event has
162 // to be OnChannelConnected.
163 if (last_filter_event_ != CHANNEL_ERROR)
164 EXPECT_EQ(CHANNEL_CONNECTED, last_filter_event_);
165 last_filter_event_ = CHANNEL_CLOSING;
168 void OnFilterRemoved() override {
169 // If the channel didn't get a chance to connect, we might see the
170 // OnFilterRemoved event with no other events preceding it. We still want
171 // OnFilterRemoved to be called to allow for deleting the Filter.
172 if (last_filter_event_ != NONE)
173 EXPECT_EQ(CHANNEL_CLOSING, last_filter_event_);
174 last_filter_event_ = FILTER_REMOVED;
177 bool OnMessageReceived(const IPC::Message& message) override {
178 // We should always get the OnFilterAdded and OnChannelConnected events
179 // prior to any messages.
180 EXPECT_EQ(CHANNEL_CONNECTED, last_filter_event_);
182 if (!is_global_filter_) {
183 EXPECT_EQ(supported_message_class_, IPC_MESSAGE_CLASS(message));
185 ++messages_received_;
187 if (!message_filtering_enabled_)
188 return false;
190 bool handled = true;
191 IPC_BEGIN_MESSAGE_MAP(MessageCountFilter, message)
192 IPC_MESSAGE_HANDLER(TestMsg_BadMessage, OnBadMessage)
193 IPC_MESSAGE_UNHANDLED(handled = false)
194 IPC_END_MESSAGE_MAP()
195 return handled;
198 void OnBadMessage(const BadType& bad_type) {
199 // Should never be called since IPC wouldn't be deserialized correctly.
200 CHECK(false);
203 bool GetSupportedMessageClasses(
204 std::vector<uint32>* supported_message_classes) const override {
205 if (is_global_filter_)
206 return false;
207 supported_message_classes->push_back(supported_message_class_);
208 return true;
211 void set_message_filtering_enabled(bool enabled) {
212 message_filtering_enabled_ = enabled;
215 size_t messages_received() const { return messages_received_; }
216 FilterEvent last_filter_event() const { return last_filter_event_; }
218 private:
219 ~MessageCountFilter() override {}
221 size_t messages_received_;
222 uint32 supported_message_class_;
223 bool is_global_filter_;
225 FilterEvent last_filter_event_;
226 bool message_filtering_enabled_;
229 class IPCChannelProxyTest : public IPCTestBase {
230 public:
231 IPCChannelProxyTest() {}
232 ~IPCChannelProxyTest() override {}
234 void SetUp() override {
235 IPCTestBase::SetUp();
237 Init("ChannelProxyClient");
239 thread_.reset(new base::Thread("ChannelProxyTestServerThread"));
240 base::Thread::Options options;
241 options.message_loop_type = base::MessageLoop::TYPE_IO;
242 thread_->StartWithOptions(options);
244 listener_.reset(new QuitListener());
245 CreateChannelProxy(listener_.get(), thread_->task_runner().get());
247 ASSERT_TRUE(StartClient());
250 void TearDown() override {
251 DestroyChannelProxy();
252 thread_.reset();
253 listener_.reset();
254 IPCTestBase::TearDown();
257 void SendQuitMessageAndWaitForIdle() {
258 sender()->Send(new WorkerMsg_Quit);
259 base::MessageLoop::current()->Run();
260 EXPECT_TRUE(WaitForClientShutdown());
263 bool DidListenerGetBadMessage() {
264 return listener_->bad_message_received_;
267 private:
268 scoped_ptr<base::Thread> thread_;
269 scoped_ptr<QuitListener> listener_;
272 #if defined(OS_ANDROID)
273 #define MAYBE_MessageClassFilters DISABLED_MessageClassFilters
274 #else
275 #define MAYBE_MessageClassFilters MessageClassFilters
276 #endif
277 TEST_F(IPCChannelProxyTest, MAYBE_MessageClassFilters) {
278 // Construct a filter per message class.
279 std::vector<scoped_refptr<MessageCountFilter> > class_filters;
280 class_filters.push_back(make_scoped_refptr(
281 new MessageCountFilter(TestMsgStart)));
282 class_filters.push_back(make_scoped_refptr(
283 new MessageCountFilter(UtilityMsgStart)));
284 for (size_t i = 0; i < class_filters.size(); ++i)
285 channel_proxy()->AddFilter(class_filters[i].get());
287 // Send a message for each class; each filter should receive just one message.
288 sender()->Send(new TestMsg_Bounce());
289 sender()->Send(new UtilityMsg_Bounce());
291 // Send some messages not assigned to a specific or valid message class.
292 sender()->Send(new WorkerMsg_Bounce);
294 // Each filter should have received just the one sent message of the
295 // corresponding class.
296 SendQuitMessageAndWaitForIdle();
297 for (size_t i = 0; i < class_filters.size(); ++i)
298 EXPECT_EQ(1U, class_filters[i]->messages_received());
301 #if defined(OS_ANDROID)
302 #define MAYBE_GlobalAndMessageClassFilters DISABLED_GlobalAndMessageClassFilters
303 #else
304 #define MAYBE_GlobalAndMessageClassFilters GlobalAndMessageClassFilters
305 #endif
306 TEST_F(IPCChannelProxyTest, MAYBE_GlobalAndMessageClassFilters) {
307 // Add a class and global filter.
308 scoped_refptr<MessageCountFilter> class_filter(
309 new MessageCountFilter(TestMsgStart));
310 class_filter->set_message_filtering_enabled(false);
311 channel_proxy()->AddFilter(class_filter.get());
313 scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
314 global_filter->set_message_filtering_enabled(false);
315 channel_proxy()->AddFilter(global_filter.get());
317 // A message of class Test should be seen by both the global filter and
318 // Test-specific filter.
319 sender()->Send(new TestMsg_Bounce);
321 // A message of a different class should be seen only by the global filter.
322 sender()->Send(new UtilityMsg_Bounce);
324 // Flush all messages.
325 SendQuitMessageAndWaitForIdle();
327 // The class filter should have received only the class-specific message.
328 EXPECT_EQ(1U, class_filter->messages_received());
330 // The global filter should have received both messages, as well as the final
331 // QUIT message.
332 EXPECT_EQ(3U, global_filter->messages_received());
335 #if defined(OS_ANDROID)
336 #define MAYBE_FilterRemoval DISABLED_FilterRemoval
337 #else
338 #define MAYBE_FilterRemoval FilterRemoval
339 #endif
340 TEST_F(IPCChannelProxyTest, MAYBE_FilterRemoval) {
341 // Add a class and global filter.
342 scoped_refptr<MessageCountFilter> class_filter(
343 new MessageCountFilter(TestMsgStart));
344 scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
346 // Add and remove both types of filters.
347 channel_proxy()->AddFilter(class_filter.get());
348 channel_proxy()->AddFilter(global_filter.get());
349 channel_proxy()->RemoveFilter(global_filter.get());
350 channel_proxy()->RemoveFilter(class_filter.get());
352 // Send some messages; they should not be seen by either filter.
353 sender()->Send(new TestMsg_Bounce);
354 sender()->Send(new UtilityMsg_Bounce);
356 // Ensure that the filters were removed and did not receive any messages.
357 SendQuitMessageAndWaitForIdle();
358 EXPECT_EQ(MessageCountFilter::FILTER_REMOVED,
359 global_filter->last_filter_event());
360 EXPECT_EQ(MessageCountFilter::FILTER_REMOVED,
361 class_filter->last_filter_event());
362 EXPECT_EQ(0U, class_filter->messages_received());
363 EXPECT_EQ(0U, global_filter->messages_received());
366 // The test that follow trigger DCHECKS in debug build.
367 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
369 TEST_F(IPCChannelProxyTest, BadMessageOnListenerThread) {
370 scoped_refptr<MessageCountFilter> class_filter(
371 new MessageCountFilter(TestMsgStart));
372 class_filter->set_message_filtering_enabled(false);
373 channel_proxy()->AddFilter(class_filter.get());
375 sender()->Send(new TestMsg_SendBadMessage());
377 SendQuitMessageAndWaitForIdle();
378 EXPECT_TRUE(DidListenerGetBadMessage());
381 TEST_F(IPCChannelProxyTest, BadMessageOnIPCThread) {
382 scoped_refptr<MessageCountFilter> class_filter(
383 new MessageCountFilter(TestMsgStart));
384 class_filter->set_message_filtering_enabled(true);
385 channel_proxy()->AddFilter(class_filter.get());
387 sender()->Send(new TestMsg_SendBadMessage());
389 SendQuitMessageAndWaitForIdle();
390 EXPECT_TRUE(DidListenerGetBadMessage());
393 class IPCChannelBadMessageTest : public IPCTestBase {
394 public:
395 void SetUp() override {
396 IPCTestBase::SetUp();
398 Init("ChannelProxyClient");
400 listener_.reset(new QuitListener());
401 CreateChannel(listener_.get());
402 ASSERT_TRUE(ConnectChannel());
404 ASSERT_TRUE(StartClient());
407 void TearDown() override {
408 listener_.reset();
409 IPCTestBase::TearDown();
412 void SendQuitMessageAndWaitForIdle() {
413 sender()->Send(new WorkerMsg_Quit);
414 base::MessageLoop::current()->Run();
415 EXPECT_TRUE(WaitForClientShutdown());
418 bool DidListenerGetBadMessage() {
419 return listener_->bad_message_received_;
422 private:
423 scoped_ptr<QuitListener> listener_;
426 #if !defined(OS_WIN)
427 // TODO(jam): for some reason this is flaky on win buildbots.
428 TEST_F(IPCChannelBadMessageTest, BadMessage) {
429 sender()->Send(new TestMsg_SendBadMessage());
430 SendQuitMessageAndWaitForIdle();
431 EXPECT_TRUE(DidListenerGetBadMessage());
433 #endif
435 #endif
437 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ChannelProxyClient) {
438 base::MessageLoopForIO main_message_loop;
439 ChannelReflectorListener listener;
440 scoped_ptr<IPC::Channel> channel(IPC::Channel::CreateClient(
441 IPCTestBase::GetChannelName("ChannelProxyClient"), &listener, nullptr));
442 CHECK(channel->Connect());
443 listener.Init(channel.get());
445 base::MessageLoop::current()->Run();
446 return 0;
449 } // namespace