Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ipc / ipc_channel_proxy_unittest.cc
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.
4
5 #include "build/build_config.h"
6
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_message_macros.h"
12 #include "ipc/ipc_test_base.h"
13 #include "ipc/message_filter.h"
14
15 namespace {
16
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 {
38  public:
39   QuitListener() {}
40   virtual ~QuitListener() {}
41
42   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
43     PickleIterator iter(message);
44
45     int command = SEND;
46     EXPECT_TRUE(iter.ReadInt(&command));
47     if (command == QUIT)
48       base::MessageLoop::current()->QuitWhenIdle();
49
50     return true;
51   }
52 };
53
54 class ChannelReflectorListener : public IPC::Listener {
55  public:
56   ChannelReflectorListener() : channel_(NULL) {}
57   virtual ~ChannelReflectorListener() {}
58
59   void Init(IPC::Channel* channel) {
60     DCHECK(!channel_);
61     channel_ = channel;
62   }
63
64   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
65     CHECK(channel_);
66
67     PickleIterator iter(message);
68
69     int command = SEND;
70     EXPECT_TRUE(iter.ReadInt(&command));
71     if (command == QUIT) {
72       channel_->Send(new IPC::Message(message));
73       base::MessageLoop::current()->QuitWhenIdle();
74       return true;
75     }
76
77     channel_->Send(new IPC::Message(message));
78     return true;
79   }
80
81  private:
82   IPC::Channel* channel_;
83 };
84
85 class MessageCountFilter : public IPC::MessageFilter {
86  public:
87   enum FilterEvent {
88     NONE,
89     FILTER_ADDED,
90     CHANNEL_CONNECTED,
91     CHANNEL_ERROR,
92     CHANNEL_CLOSING,
93     FILTER_REMOVED
94   };
95   MessageCountFilter()
96       : messages_received_(0),
97         supported_message_class_(0),
98         is_global_filter_(true),
99         last_filter_event_(NONE),
100         message_filtering_enabled_(false) {}
101
102   MessageCountFilter(uint32 supported_message_class)
103       : messages_received_(0),
104         supported_message_class_(supported_message_class),
105         is_global_filter_(false),
106         last_filter_event_(NONE),
107         message_filtering_enabled_(false) {}
108
109   virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE {
110     EXPECT_TRUE(channel);
111     EXPECT_EQ(NONE, last_filter_event_);
112     last_filter_event_ = FILTER_ADDED;
113   }
114
115   virtual void OnChannelConnected(int32_t peer_pid) OVERRIDE {
116     EXPECT_EQ(FILTER_ADDED, last_filter_event_);
117     EXPECT_NE(static_cast<int32_t>(base::kNullProcessId), peer_pid);
118     last_filter_event_ = CHANNEL_CONNECTED;
119   }
120
121   virtual void OnChannelError() OVERRIDE {
122     EXPECT_EQ(CHANNEL_CONNECTED, last_filter_event_);
123     last_filter_event_ = CHANNEL_ERROR;
124   }
125
126   virtual void OnChannelClosing() OVERRIDE {
127     // We may or may not have gotten OnChannelError; if not, the last event has
128     // to be OnChannelConnected.
129     if (last_filter_event_ != CHANNEL_ERROR)
130       EXPECT_EQ(CHANNEL_CONNECTED, last_filter_event_);
131     last_filter_event_ = CHANNEL_CLOSING;
132   }
133
134   virtual void OnFilterRemoved() OVERRIDE {
135     // If the channel didn't get a chance to connect, we might see the
136     // OnFilterRemoved event with no other events preceding it. We still want
137     // OnFilterRemoved to be called to allow for deleting the Filter.
138     if (last_filter_event_ != NONE)
139       EXPECT_EQ(CHANNEL_CLOSING, last_filter_event_);
140     last_filter_event_ = FILTER_REMOVED;
141   }
142
143   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
144     // We should always get the OnFilterAdded and OnChannelConnected events
145     // prior to any messages.
146     EXPECT_EQ(CHANNEL_CONNECTED, last_filter_event_);
147
148     if (!is_global_filter_) {
149       EXPECT_EQ(supported_message_class_, IPC_MESSAGE_CLASS(message));
150     }
151     ++messages_received_;
152     return message_filtering_enabled_;
153   }
154
155   virtual bool GetSupportedMessageClasses(
156       std::vector<uint32>* supported_message_classes) const OVERRIDE {
157     if (is_global_filter_)
158       return false;
159     supported_message_classes->push_back(supported_message_class_);
160     return true;
161   }
162
163   void set_message_filtering_enabled(bool enabled) {
164     message_filtering_enabled_ = enabled;
165   }
166
167   size_t messages_received() const { return messages_received_; }
168   FilterEvent last_filter_event() const { return last_filter_event_; }
169
170  private:
171   virtual ~MessageCountFilter() {}
172
173   size_t messages_received_;
174   uint32 supported_message_class_;
175   bool is_global_filter_;
176
177   FilterEvent last_filter_event_;
178   bool message_filtering_enabled_;
179 };
180
181 class IPCChannelProxyTest : public IPCTestBase {
182  public:
183   IPCChannelProxyTest() {}
184   virtual ~IPCChannelProxyTest() {}
185
186   virtual void SetUp() OVERRIDE {
187     IPCTestBase::SetUp();
188
189     Init("ChannelProxyClient");
190
191     thread_.reset(new base::Thread("ChannelProxyTestServerThread"));
192     base::Thread::Options options;
193     options.message_loop_type = base::MessageLoop::TYPE_IO;
194     thread_->StartWithOptions(options);
195
196     listener_.reset(new QuitListener());
197     CreateChannelProxy(listener_.get(), thread_->message_loop_proxy().get());
198
199     ASSERT_TRUE(StartClient());
200   }
201
202   virtual void TearDown() {
203     DestroyChannelProxy();
204     thread_.reset();
205     listener_.reset();
206     IPCTestBase::TearDown();
207   }
208
209   void SendQuitMessageAndWaitForIdle() {
210     Send(sender(), -1, QUIT);
211     base::MessageLoop::current()->Run();
212     EXPECT_TRUE(WaitForClientShutdown());
213   }
214
215  private:
216   scoped_ptr<base::Thread> thread_;
217   scoped_ptr<QuitListener> listener_;
218 };
219
220 TEST_F(IPCChannelProxyTest, MessageClassFilters) {
221   // Construct a filter per message class.
222   std::vector<scoped_refptr<MessageCountFilter> > class_filters;
223   for (uint32 i = 0; i < LastIPCMsgStart; ++i) {
224     class_filters.push_back(make_scoped_refptr(
225         new MessageCountFilter(i)));
226     channel_proxy()->AddFilter(class_filters.back().get());
227   }
228
229   // Send a message for each class; each filter should receive just one message.
230   for (uint32 i = 0; i < LastIPCMsgStart; ++i)
231     Send(sender(), i, SEND);
232
233   // Send some messages not assigned to a specific or valid message class.
234   Send(sender(), -1, SEND);
235   Send(sender(), LastIPCMsgStart, SEND);
236   Send(sender(), LastIPCMsgStart + 1, SEND);
237
238   // Each filter should have received just the one sent message of the
239   // corresponding class.
240   SendQuitMessageAndWaitForIdle();
241   for (size_t i = 0; i < class_filters.size(); ++i)
242     EXPECT_EQ(1U, class_filters[i]->messages_received());
243 }
244
245 TEST_F(IPCChannelProxyTest, GlobalAndMessageClassFilters) {
246   // Add a class and global filter.
247   const int kMessageClass = 7;
248   scoped_refptr<MessageCountFilter> class_filter(
249       new MessageCountFilter(kMessageClass));
250   class_filter->set_message_filtering_enabled(false);
251   channel_proxy()->AddFilter(class_filter.get());
252
253   scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
254   global_filter->set_message_filtering_enabled(false);
255   channel_proxy()->AddFilter(global_filter.get());
256
257   // A message  of class |kMessageClass| should be seen by both the global
258   // filter and |kMessageClass|-specific filter.
259   Send(sender(), kMessageClass, SEND);
260
261   // A message of a different class should be seen only by the global filter.
262   Send(sender(), kMessageClass + 1, SEND);
263
264   // Flush all messages.
265   SendQuitMessageAndWaitForIdle();
266
267   // The class filter should have received only the class-specific message.
268   EXPECT_EQ(1U, class_filter->messages_received());
269
270   // The global filter should have received both SEND messages, as well as the
271   // final QUIT message.
272   EXPECT_EQ(3U, global_filter->messages_received());
273 }
274
275 TEST_F(IPCChannelProxyTest, FilterRemoval) {
276   // Add a class and global filter.
277   const int kMessageClass = 7;
278   scoped_refptr<MessageCountFilter> class_filter(
279       new MessageCountFilter(kMessageClass));
280   scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
281
282   // Add and remove both types of filters.
283   channel_proxy()->AddFilter(class_filter.get());
284   channel_proxy()->AddFilter(global_filter.get());
285   channel_proxy()->RemoveFilter(global_filter.get());
286   channel_proxy()->RemoveFilter(class_filter.get());
287
288   // Send some messages; they should not be seen by either filter.
289   Send(sender(), 0, SEND);
290   Send(sender(), kMessageClass, SEND);
291
292   // Ensure that the filters were removed and did not receive any messages.
293   SendQuitMessageAndWaitForIdle();
294   EXPECT_EQ(MessageCountFilter::FILTER_REMOVED,
295             global_filter->last_filter_event());
296   EXPECT_EQ(MessageCountFilter::FILTER_REMOVED,
297             class_filter->last_filter_event());
298   EXPECT_EQ(0U, class_filter->messages_received());
299   EXPECT_EQ(0U, global_filter->messages_received());
300 }
301
302 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ChannelProxyClient) {
303   base::MessageLoopForIO main_message_loop;
304   ChannelReflectorListener listener;
305   IPC::Channel channel(IPCTestBase::GetChannelName("ChannelProxyClient"),
306                        IPC::Channel::MODE_CLIENT,
307                        &listener);
308   CHECK(channel.Connect());
309   listener.Init(&channel);
310
311   base::MessageLoop::current()->Run();
312   return 0;
313 }
314
315 }  // namespace