Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: ipc/ipc_channel_proxy_unittest.cc

Issue 282303014: Add regression tests to ensure that IPC::Listener::OnBadMessageReceived is always called for all ca… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "build/build_config.h" 5 #include "build/build_config.h"
6 6
7 #include "base/message_loop/message_loop.h" 7 #include "base/message_loop/message_loop.h"
8 #include "base/pickle.h" 8 #include "base/pickle.h"
9 #include "base/threading/thread.h" 9 #include "base/threading/thread.h"
10 #include "ipc/ipc_message.h" 10 #include "ipc/ipc_message.h"
11 #include "ipc/ipc_message_macros.h"
12 #include "ipc/ipc_test_base.h" 11 #include "ipc/ipc_test_base.h"
13 #include "ipc/message_filter.h" 12 #include "ipc/message_filter.h"
14 13
14 // Get basic type definitions.
15 #define IPC_MESSAGE_IMPL
16 #include "ipc/ipc_channel_proxy_unittest_messages.h"
17
18 // Generate constructors.
19 #include "ipc/struct_constructor_macros.h"
20 #include "ipc/ipc_channel_proxy_unittest_messages.h"
21
22 // Generate destructors.
23 #include "ipc/struct_destructor_macros.h"
24 #include "ipc/ipc_channel_proxy_unittest_messages.h"
25
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
31
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
37
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
43
44
15 namespace { 45 namespace {
16 46
17 #if defined(IPC_MESSAGE_START)
18 #undef IPC_MESSAGE_START
19 #endif
20
21 enum Command {
22 SEND,
23 QUIT
24 };
25
26 static void Send(IPC::Sender* sender,
27 int message_class,
28 Command command) {
29 const int IPC_MESSAGE_START = message_class;
30 IPC::Message* message = new IPC::Message(0,
31 IPC_MESSAGE_ID(),
32 IPC::Message::PRIORITY_NORMAL);
33 message->WriteInt(command);
34 sender->Send(message);
35 }
36
37 class QuitListener : public IPC::Listener { 47 class QuitListener : public IPC::Listener {
38 public: 48 public:
39 QuitListener() {} 49 QuitListener() : bad_message_received_(false) {}
40 virtual ~QuitListener() {} 50 virtual ~QuitListener() {}
41 51
42 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { 52 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
43 PickleIterator iter(message); 53 IPC_BEGIN_MESSAGE_MAP(QuitListener, message)
44 54 IPC_MESSAGE_HANDLER(WorkerMsg_Quit, OnQuit)
45 int command = SEND; 55 IPC_MESSAGE_HANDLER(TestMsg_BadMessage, OnBadMessage)
46 EXPECT_TRUE(iter.ReadInt(&command)); 56 IPC_END_MESSAGE_MAP()
47 if (command == QUIT)
48 base::MessageLoop::current()->QuitWhenIdle();
49
50 return true; 57 return true;
51 } 58 }
59
60 virtual void OnBadMessageReceived(const IPC::Message& message) OVERRIDE {
61 bad_message_received_ = true;
62 }
63
64 void OnQuit() {
65 base::MessageLoop::current()->QuitWhenIdle();
66 }
67
68 void OnBadMessage(const BadType& bad_type) {
69 // Should never be called since IPC wouldn't be deserialized correctly.
70 CHECK(false);
71 }
72
73 bool bad_message_received_;
52 }; 74 };
53 75
54 class ChannelReflectorListener : public IPC::Listener { 76 class ChannelReflectorListener : public IPC::Listener {
55 public: 77 public:
56 ChannelReflectorListener() : channel_(NULL) {} 78 ChannelReflectorListener() : channel_(NULL) {}
57 virtual ~ChannelReflectorListener() {} 79 virtual ~ChannelReflectorListener() {}
58 80
59 void Init(IPC::Channel* channel) { 81 void Init(IPC::Channel* channel) {
60 DCHECK(!channel_); 82 DCHECK(!channel_);
61 channel_ = channel; 83 channel_ = channel;
62 } 84 }
63 85
64 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { 86 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
65 CHECK(channel_); 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;
95 }
66 96
67 PickleIterator iter(message); 97 void OnTestBounce() {
98 channel_->Send(new TestMsg_Bounce());
99 }
68 100
69 int command = SEND; 101 void OnSendBadMessage() {
70 EXPECT_TRUE(iter.ReadInt(&command)); 102 channel_->Send(new TestMsg_BadMessage(BadType()));
71 if (command == QUIT) { 103 }
72 channel_->Send(new IPC::Message(message));
73 base::MessageLoop::current()->QuitWhenIdle();
74 return true;
75 }
76 104
77 channel_->Send(new IPC::Message(message)); 105 void OnUtilityBounce() {
78 return true; 106 channel_->Send(new UtilityMsg_Bounce());
107 }
108
109 void OnBounce() {
110 channel_->Send(new WorkerMsg_Bounce());
111 }
112
113 void OnQuit() {
114 channel_->Send(new WorkerMsg_Quit());
115 base::MessageLoop::current()->QuitWhenIdle();
79 } 116 }
80 117
81 private: 118 private:
82 IPC::Channel* channel_; 119 IPC::Channel* channel_;
83 }; 120 };
84 121
85 class MessageCountFilter : public IPC::MessageFilter { 122 class MessageCountFilter : public IPC::MessageFilter {
86 public: 123 public:
87 enum FilterEvent { 124 enum FilterEvent {
88 NONE, 125 NONE,
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 179
143 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { 180 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
144 // We should always get the OnFilterAdded and OnChannelConnected events 181 // We should always get the OnFilterAdded and OnChannelConnected events
145 // prior to any messages. 182 // prior to any messages.
146 EXPECT_EQ(CHANNEL_CONNECTED, last_filter_event_); 183 EXPECT_EQ(CHANNEL_CONNECTED, last_filter_event_);
147 184
148 if (!is_global_filter_) { 185 if (!is_global_filter_) {
149 EXPECT_EQ(supported_message_class_, IPC_MESSAGE_CLASS(message)); 186 EXPECT_EQ(supported_message_class_, IPC_MESSAGE_CLASS(message));
150 } 187 }
151 ++messages_received_; 188 ++messages_received_;
152 return message_filtering_enabled_; 189
190 if (!message_filtering_enabled_)
191 return false;
192
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;
199 }
200
201 void OnBadMessage(const BadType& bad_type) {
202 // Should never be called since IPC wouldn't be deserialized correctly.
203 CHECK(false);
153 } 204 }
154 205
155 virtual bool GetSupportedMessageClasses( 206 virtual bool GetSupportedMessageClasses(
156 std::vector<uint32>* supported_message_classes) const OVERRIDE { 207 std::vector<uint32>* supported_message_classes) const OVERRIDE {
157 if (is_global_filter_) 208 if (is_global_filter_)
158 return false; 209 return false;
159 supported_message_classes->push_back(supported_message_class_); 210 supported_message_classes->push_back(supported_message_class_);
160 return true; 211 return true;
161 } 212 }
162 213
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 } 251 }
201 252
202 virtual void TearDown() { 253 virtual void TearDown() {
203 DestroyChannelProxy(); 254 DestroyChannelProxy();
204 thread_.reset(); 255 thread_.reset();
205 listener_.reset(); 256 listener_.reset();
206 IPCTestBase::TearDown(); 257 IPCTestBase::TearDown();
207 } 258 }
208 259
209 void SendQuitMessageAndWaitForIdle() { 260 void SendQuitMessageAndWaitForIdle() {
210 Send(sender(), -1, QUIT); 261 sender()->Send(new WorkerMsg_Quit);
211 base::MessageLoop::current()->Run(); 262 base::MessageLoop::current()->Run();
212 EXPECT_TRUE(WaitForClientShutdown()); 263 EXPECT_TRUE(WaitForClientShutdown());
213 } 264 }
214 265
266 bool DidListenerGetBadMessage() {
267 return listener_->bad_message_received_;
268 }
269
215 private: 270 private:
216 scoped_ptr<base::Thread> thread_; 271 scoped_ptr<base::Thread> thread_;
217 scoped_ptr<QuitListener> listener_; 272 scoped_ptr<QuitListener> listener_;
218 }; 273 };
219 274
220 TEST_F(IPCChannelProxyTest, MessageClassFilters) { 275 TEST_F(IPCChannelProxyTest, MessageClassFilters) {
221 // Construct a filter per message class. 276 // Construct a filter per message class.
222 std::vector<scoped_refptr<MessageCountFilter> > class_filters; 277 std::vector<scoped_refptr<MessageCountFilter> > class_filters;
223 for (uint32 i = 0; i < LastIPCMsgStart; ++i) { 278 class_filters.push_back(make_scoped_refptr(
224 class_filters.push_back(make_scoped_refptr( 279 new MessageCountFilter(TestMsgStart)));
225 new MessageCountFilter(i))); 280 class_filters.push_back(make_scoped_refptr(
226 channel_proxy()->AddFilter(class_filters.back().get()); 281 new MessageCountFilter(UtilityMsgStart)));
227 } 282 for (size_t i = 0; i < class_filters.size(); ++i)
283 channel_proxy()->AddFilter(class_filters[i].get());
228 284
229 // Send a message for each class; each filter should receive just one message. 285 // Send a message for each class; each filter should receive just one message.
230 for (uint32 i = 0; i < LastIPCMsgStart; ++i) 286 sender()->Send(new TestMsg_Bounce());
231 Send(sender(), i, SEND); 287 sender()->Send(new UtilityMsg_Bounce());
232 288
233 // Send some messages not assigned to a specific or valid message class. 289 // Send some messages not assigned to a specific or valid message class.
234 Send(sender(), -1, SEND); 290 sender()->Send(new WorkerMsg_Bounce);
235 Send(sender(), LastIPCMsgStart, SEND);
236 Send(sender(), LastIPCMsgStart + 1, SEND);
237 291
238 // Each filter should have received just the one sent message of the 292 // Each filter should have received just the one sent message of the
239 // corresponding class. 293 // corresponding class.
240 SendQuitMessageAndWaitForIdle(); 294 SendQuitMessageAndWaitForIdle();
241 for (size_t i = 0; i < class_filters.size(); ++i) 295 for (size_t i = 0; i < class_filters.size(); ++i)
242 EXPECT_EQ(1U, class_filters[i]->messages_received()); 296 EXPECT_EQ(1U, class_filters[i]->messages_received());
243 } 297 }
244 298
245 TEST_F(IPCChannelProxyTest, GlobalAndMessageClassFilters) { 299 TEST_F(IPCChannelProxyTest, GlobalAndMessageClassFilters) {
246 // Add a class and global filter. 300 // Add a class and global filter.
247 const int kMessageClass = 7;
248 scoped_refptr<MessageCountFilter> class_filter( 301 scoped_refptr<MessageCountFilter> class_filter(
249 new MessageCountFilter(kMessageClass)); 302 new MessageCountFilter(TestMsgStart));
250 class_filter->set_message_filtering_enabled(false); 303 class_filter->set_message_filtering_enabled(false);
251 channel_proxy()->AddFilter(class_filter.get()); 304 channel_proxy()->AddFilter(class_filter.get());
252 305
253 scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter()); 306 scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
254 global_filter->set_message_filtering_enabled(false); 307 global_filter->set_message_filtering_enabled(false);
255 channel_proxy()->AddFilter(global_filter.get()); 308 channel_proxy()->AddFilter(global_filter.get());
256 309
257 // A message of class |kMessageClass| should be seen by both the global 310 // A message of class Test should be seen by both the global filter and
258 // filter and |kMessageClass|-specific filter. 311 // Test-specific filter.
259 Send(sender(), kMessageClass, SEND); 312 sender()->Send(new TestMsg_Bounce);
260 313
261 // A message of a different class should be seen only by the global filter. 314 // A message of a different class should be seen only by the global filter.
262 Send(sender(), kMessageClass + 1, SEND); 315 sender()->Send(new UtilityMsg_Bounce);
263 316
264 // Flush all messages. 317 // Flush all messages.
265 SendQuitMessageAndWaitForIdle(); 318 SendQuitMessageAndWaitForIdle();
266 319
267 // The class filter should have received only the class-specific message. 320 // The class filter should have received only the class-specific message.
268 EXPECT_EQ(1U, class_filter->messages_received()); 321 EXPECT_EQ(1U, class_filter->messages_received());
269 322
270 // The global filter should have received both SEND messages, as well as the 323 // The global filter should have received both messages, as well as the final
271 // final QUIT message. 324 // QUIT message.
272 EXPECT_EQ(3U, global_filter->messages_received()); 325 EXPECT_EQ(3U, global_filter->messages_received());
273 } 326 }
274 327
275 TEST_F(IPCChannelProxyTest, FilterRemoval) { 328 TEST_F(IPCChannelProxyTest, FilterRemoval) {
276 // Add a class and global filter. 329 // Add a class and global filter.
277 const int kMessageClass = 7;
278 scoped_refptr<MessageCountFilter> class_filter( 330 scoped_refptr<MessageCountFilter> class_filter(
279 new MessageCountFilter(kMessageClass)); 331 new MessageCountFilter(TestMsgStart));
280 scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter()); 332 scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
281 333
282 // Add and remove both types of filters. 334 // Add and remove both types of filters.
283 channel_proxy()->AddFilter(class_filter.get()); 335 channel_proxy()->AddFilter(class_filter.get());
284 channel_proxy()->AddFilter(global_filter.get()); 336 channel_proxy()->AddFilter(global_filter.get());
285 channel_proxy()->RemoveFilter(global_filter.get()); 337 channel_proxy()->RemoveFilter(global_filter.get());
286 channel_proxy()->RemoveFilter(class_filter.get()); 338 channel_proxy()->RemoveFilter(class_filter.get());
287 339
288 // Send some messages; they should not be seen by either filter. 340 // Send some messages; they should not be seen by either filter.
289 Send(sender(), 0, SEND); 341 sender()->Send(new TestMsg_Bounce);
290 Send(sender(), kMessageClass, SEND); 342 sender()->Send(new UtilityMsg_Bounce);
291 343
292 // Ensure that the filters were removed and did not receive any messages. 344 // Ensure that the filters were removed and did not receive any messages.
293 SendQuitMessageAndWaitForIdle(); 345 SendQuitMessageAndWaitForIdle();
294 EXPECT_EQ(MessageCountFilter::FILTER_REMOVED, 346 EXPECT_EQ(MessageCountFilter::FILTER_REMOVED,
295 global_filter->last_filter_event()); 347 global_filter->last_filter_event());
296 EXPECT_EQ(MessageCountFilter::FILTER_REMOVED, 348 EXPECT_EQ(MessageCountFilter::FILTER_REMOVED,
297 class_filter->last_filter_event()); 349 class_filter->last_filter_event());
298 EXPECT_EQ(0U, class_filter->messages_received()); 350 EXPECT_EQ(0U, class_filter->messages_received());
299 EXPECT_EQ(0U, global_filter->messages_received()); 351 EXPECT_EQ(0U, global_filter->messages_received());
300 } 352 }
301 353
354 // The test that follow trigger DCHECKS in debug build.
355 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
356
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());
362
363 sender()->Send(new TestMsg_SendBadMessage());
364
365 SendQuitMessageAndWaitForIdle();
366 EXPECT_TRUE(DidListenerGetBadMessage());
367 }
368
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());
374
375 sender()->Send(new TestMsg_SendBadMessage());
376
377 SendQuitMessageAndWaitForIdle();
378 EXPECT_TRUE(DidListenerGetBadMessage());
379 }
380
381 class IPCChannelBadMessageTest : public IPCTestBase {
382 public:
383 IPCChannelBadMessageTest() {}
384 virtual ~IPCChannelBadMessageTest() {}
385
386 virtual void SetUp() OVERRIDE {
387 IPCTestBase::SetUp();
388
389 Init("ChannelProxyClient");
390
391 listener_.reset(new QuitListener());
392 CreateChannel(listener_.get());
393 ASSERT_TRUE(ConnectChannel());
394
395 ASSERT_TRUE(StartClient());
396 }
397
398 virtual void TearDown() {
399 listener_.reset();
400 IPCTestBase::TearDown();
401 }
402
403 void SendQuitMessageAndWaitForIdle() {
404 sender()->Send(new WorkerMsg_Quit);
405 base::MessageLoop::current()->Run();
406 EXPECT_TRUE(WaitForClientShutdown());
407 }
408
409 bool DidListenerGetBadMessage() {
410 return listener_->bad_message_received_;
411 }
412
413 private:
414 scoped_ptr<QuitListener> listener_;
415 };
416
417 TEST_F(IPCChannelBadMessageTest, BadMessage) {
418 sender()->Send(new TestMsg_SendBadMessage());
419 SendQuitMessageAndWaitForIdle();
420 EXPECT_TRUE(DidListenerGetBadMessage());
421 }
422
423 #endif
424
302 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ChannelProxyClient) { 425 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ChannelProxyClient) {
303 base::MessageLoopForIO main_message_loop; 426 base::MessageLoopForIO main_message_loop;
304 ChannelReflectorListener listener; 427 ChannelReflectorListener listener;
305 IPC::Channel channel(IPCTestBase::GetChannelName("ChannelProxyClient"), 428 IPC::Channel channel(IPCTestBase::GetChannelName("ChannelProxyClient"),
306 IPC::Channel::MODE_CLIENT, 429 IPC::Channel::MODE_CLIENT,
307 &listener); 430 &listener);
308 CHECK(channel.Connect()); 431 CHECK(channel.Connect());
309 listener.Init(&channel); 432 listener.Init(&channel);
310 433
311 base::MessageLoop::current()->Run(); 434 base::MessageLoop::current()->Run();
312 return 0; 435 return 0;
313 } 436 }
314 437
315 } // namespace 438 } // namespace
OLDNEW
« no previous file with comments | « content/browser/renderer_host/render_view_host_unittest.cc ('k') | ipc/ipc_channel_proxy_unittest_messages.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698