<webview>: Define API endpoints for webview.contextMenus API.
[chromium-blink-merge.git] / ipc / ipc_channel_proxy_unittest.cc
blob431f410d7fa08f7cd791ca57091382511d3db69e
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_message_macros.h"
12 #include "ipc/ipc_test_base.h"
14 namespace {
16 #if defined(IPC_MESSAGE_START)
17 #undef IPC_MESSAGE_START
18 #endif
20 enum Command {
21 SEND,
22 QUIT
25 static void Send(IPC::Sender* sender,
26 int message_class,
27 Command command) {
28 const int IPC_MESSAGE_START = message_class;
29 IPC::Message* message = new IPC::Message(0,
30 IPC_MESSAGE_ID(),
31 IPC::Message::PRIORITY_NORMAL);
32 message->WriteInt(command);
33 sender->Send(message);
36 class QuitListener : public IPC::Listener {
37 public:
38 QuitListener() {}
39 virtual ~QuitListener() {}
41 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
42 PickleIterator iter(message);
44 int command = SEND;
45 EXPECT_TRUE(iter.ReadInt(&command));
46 if (command == QUIT)
47 base::MessageLoop::current()->QuitWhenIdle();
49 return true;
53 class ChannelReflectorListener : public IPC::Listener {
54 public:
55 ChannelReflectorListener() : channel_(NULL) {}
56 virtual ~ChannelReflectorListener() {}
58 void Init(IPC::Channel* channel) {
59 DCHECK(!channel_);
60 channel_ = channel;
63 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
64 CHECK(channel_);
66 PickleIterator iter(message);
68 int command = SEND;
69 EXPECT_TRUE(iter.ReadInt(&command));
70 if (command == QUIT) {
71 channel_->Send(new IPC::Message(message));
72 base::MessageLoop::current()->QuitWhenIdle();
73 return true;
76 channel_->Send(new IPC::Message(message));
77 return true;
80 private:
81 IPC::Channel* channel_;
84 class MessageCountFilter : public IPC::ChannelProxy::MessageFilter {
85 public:
86 MessageCountFilter()
87 : messages_received_(0),
88 supported_message_class_(0),
89 is_global_filter_(true),
90 filter_removed_(false),
91 message_filtering_enabled_(false) {}
93 MessageCountFilter(uint32 supported_message_class)
94 : messages_received_(0),
95 supported_message_class_(supported_message_class),
96 is_global_filter_(false),
97 filter_removed_(false),
98 message_filtering_enabled_(false) {}
100 virtual void OnFilterRemoved() OVERRIDE {
101 EXPECT_FALSE(filter_removed_);
102 filter_removed_ = true;
105 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
106 if (!is_global_filter_) {
107 EXPECT_EQ(supported_message_class_, IPC_MESSAGE_CLASS(message));
109 ++messages_received_;
110 return message_filtering_enabled_;
113 virtual bool GetSupportedMessageClasses(
114 std::vector<uint32>* supported_message_classes) const OVERRIDE {
115 if (is_global_filter_)
116 return false;
117 supported_message_classes->push_back(supported_message_class_);
118 return true;
121 void set_message_filtering_enabled(bool enabled) {
122 message_filtering_enabled_ = enabled;
125 size_t messages_received() const { return messages_received_; }
126 bool filter_removed() const { return filter_removed_; }
128 private:
129 virtual ~MessageCountFilter() {}
131 size_t messages_received_;
132 uint32 supported_message_class_;
133 bool is_global_filter_;
134 bool filter_removed_;
135 bool message_filtering_enabled_;
138 class IPCChannelProxyTest : public IPCTestBase {
139 public:
140 IPCChannelProxyTest() {}
141 virtual ~IPCChannelProxyTest() {}
143 virtual void SetUp() OVERRIDE {
144 IPCTestBase::SetUp();
146 Init("ChannelProxyClient");
148 thread_.reset(new base::Thread("ChannelProxyTestServerThread"));
149 base::Thread::Options options;
150 options.message_loop_type = base::MessageLoop::TYPE_IO;
151 thread_->StartWithOptions(options);
153 listener_.reset(new QuitListener());
154 CreateChannelProxy(listener_.get(), thread_->message_loop_proxy().get());
156 ASSERT_TRUE(StartClient());
159 virtual void TearDown() {
160 DestroyChannelProxy();
161 thread_.reset();
162 listener_.reset();
163 IPCTestBase::TearDown();
166 void SendQuitMessageAndWaitForIdle() {
167 Send(sender(), -1, QUIT);
168 base::MessageLoop::current()->Run();
169 EXPECT_TRUE(WaitForClientShutdown());
172 private:
173 scoped_ptr<base::Thread> thread_;
174 scoped_ptr<QuitListener> listener_;
177 TEST_F(IPCChannelProxyTest, MessageClassFilters) {
178 // Construct a filter per message class.
179 std::vector<scoped_refptr<MessageCountFilter> > class_filters;
180 for (uint32 i = 0; i < LastIPCMsgStart; ++i) {
181 class_filters.push_back(make_scoped_refptr(
182 new MessageCountFilter(i)));
183 channel_proxy()->AddFilter(class_filters.back().get());
186 // Send a message for each class; each filter should receive just one message.
187 for (uint32 i = 0; i < LastIPCMsgStart; ++i)
188 Send(sender(), i, SEND);
190 // Send some messages not assigned to a specific or valid message class.
191 Send(sender(), -1, SEND);
192 Send(sender(), LastIPCMsgStart, SEND);
193 Send(sender(), LastIPCMsgStart + 1, SEND);
195 // Each filter should have received just the one sent message of the
196 // corresponding class.
197 SendQuitMessageAndWaitForIdle();
198 for (size_t i = 0; i < class_filters.size(); ++i)
199 EXPECT_EQ(1U, class_filters[i]->messages_received());
202 TEST_F(IPCChannelProxyTest, GlobalAndMessageClassFilters) {
203 // Add a class and global filter.
204 const int kMessageClass = 7;
205 scoped_refptr<MessageCountFilter> class_filter(
206 new MessageCountFilter(kMessageClass));
207 class_filter->set_message_filtering_enabled(false);
208 channel_proxy()->AddFilter(class_filter.get());
210 scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
211 global_filter->set_message_filtering_enabled(false);
212 channel_proxy()->AddFilter(global_filter.get());
214 // A message of class |kMessageClass| should be seen by both the global
215 // filter and |kMessageClass|-specific filter.
216 Send(sender(), kMessageClass, SEND);
218 // A message of a different class should be seen only by the global filter.
219 Send(sender(), kMessageClass + 1, SEND);
221 // Flush all messages.
222 SendQuitMessageAndWaitForIdle();
224 // The class filter should have received only the class-specific message.
225 EXPECT_EQ(1U, class_filter->messages_received());
227 // The global filter should have received both SEND messages, as well as the
228 // final QUIT message.
229 EXPECT_EQ(3U, global_filter->messages_received());
232 TEST_F(IPCChannelProxyTest, FilterRemoval) {
233 // Add a class and global filter.
234 const int kMessageClass = 7;
235 scoped_refptr<MessageCountFilter> class_filter(
236 new MessageCountFilter(kMessageClass));
237 scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
239 // Add and remove both types of filters.
240 channel_proxy()->AddFilter(class_filter.get());
241 channel_proxy()->AddFilter(global_filter.get());
242 channel_proxy()->RemoveFilter(global_filter.get());
243 channel_proxy()->RemoveFilter(class_filter.get());
245 // Send some messages; they should not be seen by either filter.
246 Send(sender(), 0, SEND);
247 Send(sender(), kMessageClass, SEND);
249 // Ensure that the filters were removed and did not receive any messages.
250 SendQuitMessageAndWaitForIdle();
251 EXPECT_TRUE(global_filter->filter_removed());
252 EXPECT_TRUE(class_filter->filter_removed());
253 EXPECT_EQ(0U, class_filter->messages_received());
254 EXPECT_EQ(0U, global_filter->messages_received());
257 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ChannelProxyClient) {
258 base::MessageLoopForIO main_message_loop;
259 ChannelReflectorListener listener;
260 IPC::Channel channel(IPCTestBase::GetChannelName("ChannelProxyClient"),
261 IPC::Channel::MODE_CLIENT,
262 &listener);
263 CHECK(channel.Connect());
264 listener.Init(&channel);
266 base::MessageLoop::current()->Run();
267 return 0;
270 } // namespace