[mac] AmbientLight api verified on MacBookAir5,2 by François Beaufort
[chromium-blink-merge.git] / ipc / mojo / ipc_channel_mojo_unittest.cc
blob47e72fc0e5ea45d44d31d8e718ec12884b25d002
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 "ipc/mojo/ipc_channel_mojo.h"
7 #include "base/base_paths.h"
8 #include "base/files/file.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/path_service.h"
11 #include "base/pickle.h"
12 #include "base/threading/thread.h"
13 #include "ipc/ipc_message.h"
14 #include "ipc/ipc_test_base.h"
15 #include "ipc/ipc_test_channel_listener.h"
16 #include "ipc/mojo/ipc_channel_mojo_host.h"
18 #if defined(OS_POSIX)
19 #include "base/file_descriptor_posix.h"
20 #endif
22 namespace {
24 class ListenerThatExpectsOK : public IPC::Listener {
25 public:
26 ListenerThatExpectsOK()
27 : received_ok_(false) {}
29 ~ListenerThatExpectsOK() override {}
31 bool OnMessageReceived(const IPC::Message& message) override {
32 PickleIterator iter(message);
33 std::string should_be_ok;
34 EXPECT_TRUE(iter.ReadString(&should_be_ok));
35 EXPECT_EQ(should_be_ok, "OK");
36 received_ok_ = true;
37 base::MessageLoop::current()->Quit();
38 return true;
41 void OnChannelError() override {
42 // The connection should be healthy while the listener is waiting
43 // message. An error can occur after that because the peer
44 // process dies.
45 DCHECK(received_ok_);
48 static void SendOK(IPC::Sender* sender) {
49 IPC::Message* message = new IPC::Message(
50 0, 2, IPC::Message::PRIORITY_NORMAL);
51 message->WriteString(std::string("OK"));
52 ASSERT_TRUE(sender->Send(message));
55 private:
56 bool received_ok_;
59 class ChannelClient {
60 public:
61 explicit ChannelClient(IPC::Listener* listener, const char* name) {
62 channel_ = IPC::ChannelMojo::Create(NULL,
63 IPCTestBase::GetChannelName(name),
64 IPC::Channel::MODE_CLIENT,
65 listener);
68 void Connect() {
69 CHECK(channel_->Connect());
72 IPC::ChannelMojo* channel() const { return channel_.get(); }
74 private:
75 base::MessageLoopForIO main_message_loop_;
76 scoped_ptr<IPC::ChannelMojo> channel_;
79 class IPCChannelMojoTest : public IPCTestBase {
80 protected:
81 scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
82 const IPC::ChannelHandle& handle,
83 base::TaskRunner* runner) override {
84 host_.reset(new IPC::ChannelMojoHost(task_runner()));
85 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
86 handle);
89 bool DidStartClient() override {
90 bool ok = IPCTestBase::DidStartClient();
91 DCHECK(ok);
92 host_->OnClientLaunched(client_process().Handle());
93 return ok;
96 private:
97 scoped_ptr<IPC::ChannelMojoHost> host_;
101 class TestChannelListenerWithExtraExpectations
102 : public IPC::TestChannelListener {
103 public:
104 TestChannelListenerWithExtraExpectations()
105 : is_connected_called_(false) {
108 void OnChannelConnected(int32 peer_pid) override {
109 IPC::TestChannelListener::OnChannelConnected(peer_pid);
110 EXPECT_TRUE(base::kNullProcessId != peer_pid);
111 is_connected_called_ = true;
114 bool is_connected_called() const { return is_connected_called_; }
116 private:
117 bool is_connected_called_;
120 TEST_F(IPCChannelMojoTest, ConnectedFromClient) {
121 Init("IPCChannelMojoTestClient");
123 // Set up IPC channel and start client.
124 TestChannelListenerWithExtraExpectations listener;
125 CreateChannel(&listener);
126 listener.Init(sender());
127 ASSERT_TRUE(ConnectChannel());
128 ASSERT_TRUE(StartClient());
130 IPC::TestChannelListener::SendOneMessage(
131 sender(), "hello from parent");
133 base::MessageLoop::current()->Run();
134 EXPECT_TRUE(base::kNullProcessId != this->channel()->GetPeerPID());
136 this->channel()->Close();
138 EXPECT_TRUE(WaitForClientShutdown());
139 EXPECT_TRUE(listener.is_connected_called());
140 EXPECT_TRUE(listener.HasSentAll());
142 DestroyChannel();
145 // A long running process that connects to us
146 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) {
147 TestChannelListenerWithExtraExpectations listener;
148 ChannelClient client(&listener, "IPCChannelMojoTestClient");
149 client.Connect();
150 listener.Init(client.channel());
152 IPC::TestChannelListener::SendOneMessage(
153 client.channel(), "hello from child");
154 base::MessageLoop::current()->Run();
155 EXPECT_TRUE(listener.is_connected_called());
156 EXPECT_TRUE(listener.HasSentAll());
158 return 0;
161 class ListenerExpectingErrors : public IPC::Listener {
162 public:
163 ListenerExpectingErrors()
164 : has_error_(false) {
167 void OnChannelConnected(int32 peer_pid) override {
168 base::MessageLoop::current()->Quit();
171 bool OnMessageReceived(const IPC::Message& message) override { return true; }
173 void OnChannelError() override {
174 has_error_ = true;
175 base::MessageLoop::current()->Quit();
178 bool has_error() const { return has_error_; }
180 private:
181 bool has_error_;
185 class IPCChannelMojoErrorTest : public IPCTestBase {
186 protected:
187 scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
188 const IPC::ChannelHandle& handle,
189 base::TaskRunner* runner) override {
190 host_.reset(new IPC::ChannelMojoHost(task_runner()));
191 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
192 handle);
195 bool DidStartClient() override {
196 bool ok = IPCTestBase::DidStartClient();
197 DCHECK(ok);
198 host_->OnClientLaunched(client_process().Handle());
199 return ok;
202 private:
203 scoped_ptr<IPC::ChannelMojoHost> host_;
206 class ListenerThatQuits : public IPC::Listener {
207 public:
208 ListenerThatQuits() {
211 bool OnMessageReceived(const IPC::Message& message) override {
212 return true;
215 void OnChannelConnected(int32 peer_pid) override {
216 base::MessageLoop::current()->Quit();
220 // A long running process that connects to us.
221 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient) {
222 ListenerThatQuits listener;
223 ChannelClient client(&listener, "IPCChannelMojoErraticTestClient");
224 client.Connect();
226 base::MessageLoop::current()->Run();
228 return 0;
231 TEST_F(IPCChannelMojoErrorTest, SendFailWithPendingMessages) {
232 Init("IPCChannelMojoErraticTestClient");
234 // Set up IPC channel and start client.
235 ListenerExpectingErrors listener;
236 CreateChannel(&listener);
237 ASSERT_TRUE(ConnectChannel());
239 // This matches a value in mojo/edk/system/constants.h
240 const int kMaxMessageNumBytes = 4 * 1024 * 1024;
241 std::string overly_large_data(kMaxMessageNumBytes, '*');
242 // This messages are queued as pending.
243 for (size_t i = 0; i < 10; ++i) {
244 IPC::TestChannelListener::SendOneMessage(
245 sender(), overly_large_data.c_str());
248 ASSERT_TRUE(StartClient());
249 base::MessageLoop::current()->Run();
251 this->channel()->Close();
253 EXPECT_TRUE(WaitForClientShutdown());
254 EXPECT_TRUE(listener.has_error());
256 DestroyChannel();
259 #if defined(OS_WIN)
260 class IPCChannelMojoDeadHandleTest : public IPCTestBase {
261 protected:
262 virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
263 const IPC::ChannelHandle& handle,
264 base::TaskRunner* runner) override {
265 host_.reset(new IPC::ChannelMojoHost(task_runner()));
266 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
267 handle);
270 virtual bool DidStartClient() override {
271 IPCTestBase::DidStartClient();
272 const base::ProcessHandle client = client_process().Handle();
273 // Forces GetFileHandleForProcess() fail. It happens occasionally
274 // in production, so we should exercise it somehow.
275 // TODO(morrita): figure out how to safely test this.
276 // ::CloseHandle(client);
277 host_->OnClientLaunched(client);
278 return true;
281 private:
282 scoped_ptr<IPC::ChannelMojoHost> host_;
285 TEST_F(IPCChannelMojoDeadHandleTest, InvalidClientHandle) {
286 // Any client type is fine as it is going to be killed anyway.
287 Init("IPCChannelMojoTestDoNothingClient");
289 // Set up IPC channel and start client.
290 ListenerExpectingErrors listener;
291 CreateChannel(&listener);
292 ASSERT_TRUE(ConnectChannel());
294 ASSERT_TRUE(StartClient());
295 base::MessageLoop::current()->Run();
297 this->channel()->Close();
299 // WaitForClientShutdown() fails as client_hanadle() is already
300 // closed.
301 EXPECT_FALSE(WaitForClientShutdown());
302 EXPECT_TRUE(listener.has_error());
304 DestroyChannel();
307 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestDoNothingClient) {
308 ListenerThatQuits listener;
309 ChannelClient client(&listener, "IPCChannelMojoTestDoNothingClient");
310 client.Connect();
312 // Quits without running the message loop as this client won't
313 // receive any messages from the server.
315 return 0;
317 #endif
319 #if defined(OS_POSIX)
320 class ListenerThatExpectsFile : public IPC::Listener {
321 public:
322 ListenerThatExpectsFile()
323 : sender_(NULL) {}
325 ~ListenerThatExpectsFile() override {}
327 bool OnMessageReceived(const IPC::Message& message) override {
328 PickleIterator iter(message);
330 base::ScopedFD fd;
331 EXPECT_TRUE(message.ReadFile(&iter, &fd));
332 base::File file(fd.release());
333 std::string content(GetSendingFileContent().size(), ' ');
334 file.Read(0, &content[0], content.size());
335 EXPECT_EQ(content, GetSendingFileContent());
336 base::MessageLoop::current()->Quit();
337 ListenerThatExpectsOK::SendOK(sender_);
338 return true;
341 void OnChannelError() override {
342 NOTREACHED();
345 static std::string GetSendingFileContent() {
346 return "Hello";
349 static base::FilePath GetSendingFilePath() {
350 base::FilePath path;
351 bool ok = PathService::Get(base::DIR_CACHE, &path);
352 EXPECT_TRUE(ok);
353 return path.Append("ListenerThatExpectsFile.txt");
356 static void WriteAndSendFile(IPC::Sender* sender, base::File& file) {
357 std::string content = GetSendingFileContent();
358 file.WriteAtCurrentPos(content.data(), content.size());
359 file.Flush();
360 IPC::Message* message = new IPC::Message(
361 0, 2, IPC::Message::PRIORITY_NORMAL);
362 message->WriteFile(base::ScopedFD(file.TakePlatformFile()));
363 ASSERT_TRUE(sender->Send(message));
366 void set_sender(IPC::Sender* sender) { sender_ = sender; }
368 private:
369 IPC::Sender* sender_;
373 TEST_F(IPCChannelMojoTest, SendPlatformHandle) {
374 Init("IPCChannelMojoTestSendPlatformHandleClient");
376 ListenerThatExpectsOK listener;
377 CreateChannel(&listener);
378 ASSERT_TRUE(ConnectChannel());
379 ASSERT_TRUE(StartClient());
381 base::File file(ListenerThatExpectsFile::GetSendingFilePath(),
382 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
383 base::File::FLAG_READ);
384 ListenerThatExpectsFile::WriteAndSendFile(channel(), file);
385 base::MessageLoop::current()->Run();
387 this->channel()->Close();
389 EXPECT_TRUE(WaitForClientShutdown());
390 DestroyChannel();
393 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient) {
394 ListenerThatExpectsFile listener;
395 ChannelClient client(
396 &listener, "IPCChannelMojoTestSendPlatformHandleClient");
397 client.Connect();
398 listener.set_sender(client.channel());
400 base::MessageLoop::current()->Run();
402 return 0;
404 #endif
406 } // namespace