Files.app: Fix selection on creating new folder
[chromium-blink-merge.git] / ipc / ipc_channel_proxy_unittest.cc
blobc5e078a912ee207ee4b9b3074c803b02be974295
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"
13 #include "ipc/message_filter.h"
15 namespace {
17 #if defined(IPC_MESSAGE_START)
18 #undef IPC_MESSAGE_START
19 #endif
21 enum Command {
22 SEND,
23 QUIT
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);
37 class QuitListener : public IPC::Listener {
38 public:
39 QuitListener() {}
40 virtual ~QuitListener() {}
42 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
43 PickleIterator iter(message);
45 int command = SEND;
46 EXPECT_TRUE(iter.ReadInt(&command));
47 if (command == QUIT)
48 base::MessageLoop::current()->QuitWhenIdle();
50 return true;
54 class ChannelReflectorListener : public IPC::Listener {
55 public:
56 ChannelReflectorListener() : channel_(NULL) {}
57 virtual ~ChannelReflectorListener() {}
59 void Init(IPC::Channel* channel) {
60 DCHECK(!channel_);
61 channel_ = channel;
64 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
65 CHECK(channel_);
67 PickleIterator iter(message);
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;
77 channel_->Send(new IPC::Message(message));
78 return true;
81 private:
82 IPC::Channel* channel_;
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
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) {}
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) {}
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;
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;
121 virtual void OnChannelError() OVERRIDE {
122 EXPECT_EQ(CHANNEL_CONNECTED, last_filter_event_);
123 last_filter_event_ = CHANNEL_ERROR;
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;
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;
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_);
148 if (!is_global_filter_) {
149 EXPECT_EQ(supported_message_class_, IPC_MESSAGE_CLASS(message));
151 ++messages_received_;
152 return message_filtering_enabled_;
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;
163 void set_message_filtering_enabled(bool enabled) {
164 message_filtering_enabled_ = enabled;
167 size_t messages_received() const { return messages_received_; }
168 FilterEvent last_filter_event() const { return last_filter_event_; }
170 private:
171 virtual ~MessageCountFilter() {}
173 size_t messages_received_;
174 uint32 supported_message_class_;
175 bool is_global_filter_;
177 FilterEvent last_filter_event_;
178 bool message_filtering_enabled_;
181 class IPCChannelProxyTest : public IPCTestBase {
182 public:
183 IPCChannelProxyTest() {}
184 virtual ~IPCChannelProxyTest() {}
186 virtual void SetUp() OVERRIDE {
187 IPCTestBase::SetUp();
189 Init("ChannelProxyClient");
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);
196 listener_.reset(new QuitListener());
197 CreateChannelProxy(listener_.get(), thread_->message_loop_proxy().get());
199 ASSERT_TRUE(StartClient());
202 virtual void TearDown() {
203 DestroyChannelProxy();
204 thread_.reset();
205 listener_.reset();
206 IPCTestBase::TearDown();
209 void SendQuitMessageAndWaitForIdle() {
210 Send(sender(), -1, QUIT);
211 base::MessageLoop::current()->Run();
212 EXPECT_TRUE(WaitForClientShutdown());
215 private:
216 scoped_ptr<base::Thread> thread_;
217 scoped_ptr<QuitListener> listener_;
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());
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);
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);
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());
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());
253 scoped_refptr<MessageCountFilter> global_filter(new MessageCountFilter());
254 global_filter->set_message_filtering_enabled(false);
255 channel_proxy()->AddFilter(global_filter.get());
257 // A message of class |kMessageClass| should be seen by both the global
258 // filter and |kMessageClass|-specific filter.
259 Send(sender(), kMessageClass, SEND);
261 // A message of a different class should be seen only by the global filter.
262 Send(sender(), kMessageClass + 1, SEND);
264 // Flush all messages.
265 SendQuitMessageAndWaitForIdle();
267 // The class filter should have received only the class-specific message.
268 EXPECT_EQ(1U, class_filter->messages_received());
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());
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());
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());
288 // Send some messages; they should not be seen by either filter.
289 Send(sender(), 0, SEND);
290 Send(sender(), kMessageClass, SEND);
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());
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);
311 base::MessageLoop::current()->Run();
312 return 0;
315 } // namespace