[Mac] Fixes a bug where instant suggest text would disappear on every other keystroke.
[chromium-blink-merge.git] / ipc / ipc_send_fds_test.cc
blob183a06ce9ed4a94eaf13ace04e45dfd6070e3600
1 // Copyright (c) 2009 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 "ipc/ipc_tests.h"
9 #if defined(OS_MACOSX)
10 extern "C" {
11 #include <sandbox.h>
13 #endif
14 #include <fcntl.h>
15 #include <sys/stat.h>
17 #include "base/eintr_wrapper.h"
18 #include "base/message_loop.h"
19 #include "ipc/ipc_channel.h"
20 #include "ipc/ipc_message_utils.h"
21 #include "testing/multiprocess_func_list.h"
23 #if defined(OS_POSIX)
24 #include "base/file_descriptor_posix.h"
26 namespace {
28 const unsigned kNumFDsToSend = 20;
29 const char* kDevZeroPath = "/dev/zero";
31 static void VerifyAndCloseDescriptor(int fd, ino_t inode_num) {
32 // Check that we can read from the FD.
33 char buf;
34 ssize_t amt_read = read(fd, &buf, 1);
35 ASSERT_EQ(amt_read, 1);
36 ASSERT_EQ(buf, 0); // /dev/zero always reads NUL bytes.
38 struct stat st;
39 ASSERT_EQ(fstat(fd, &st), 0);
41 ASSERT_EQ(close(fd), 0);
43 // We compare iNode numbers to check that the file sent over the wire
44 // was actually the same physical file as the one we were expecting.
45 ASSERT_EQ(inode_num, st.st_ino);
48 class MyChannelDescriptorListener : public IPC::Channel::Listener {
49 public:
50 MyChannelDescriptorListener(ino_t expected_inode_num)
51 : expected_inode_num_(expected_inode_num),
52 num_fds_received_(0) {}
54 virtual void OnMessageReceived(const IPC::Message& message) {
55 void* iter = NULL;
57 ++num_fds_received_;
58 base::FileDescriptor descriptor;
60 ASSERT_TRUE(
61 IPC::ParamTraits<base::FileDescriptor>::Read(
62 &message, &iter, &descriptor));
64 VerifyAndCloseDescriptor(descriptor.fd, expected_inode_num_);
65 if (num_fds_received_ == kNumFDsToSend) {
66 MessageLoop::current()->Quit();
70 virtual void OnChannelError() {
71 MessageLoop::current()->Quit();
73 private:
74 ino_t expected_inode_num_;
75 unsigned num_fds_received_;
78 void TestDescriptorServer(IPC::Channel &chan,
79 base::ProcessHandle process_handle) {
80 ASSERT_TRUE(process_handle);
82 for (unsigned i = 0; i < kNumFDsToSend; ++i) {
83 base::FileDescriptor descriptor;
84 const int fd = open(kDevZeroPath, O_RDONLY);
85 ASSERT_GE(fd, 0);
86 descriptor.auto_close = true;
87 descriptor.fd = fd;
89 IPC::Message* message = new IPC::Message(0, // routing_id
90 3, // message type
91 IPC::Message::PRIORITY_NORMAL);
92 IPC::ParamTraits<base::FileDescriptor>::Write(message, descriptor);
93 chan.Send(message);
96 // Run message loop.
97 MessageLoop::current()->Run();
99 // Close Channel so client gets its OnChannelError() callback fired.
100 chan.Close();
102 // Cleanup child process.
103 EXPECT_TRUE(base::WaitForSingleProcess(process_handle, 5000));
106 int TestDescriptorClient(ino_t expected_inode_num) {
107 MessageLoopForIO main_message_loop;
108 MyChannelDescriptorListener listener(expected_inode_num);
110 // Setup IPC channel.
111 IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_CLIENT,
112 &listener);
113 CHECK(chan.Connect());
114 MessageLoop::current()->Run();
116 return 0;
119 } // namespace
121 // ---------------------------------------------------------------------------
122 #if defined(OS_MACOSX)
123 // TODO(port): Make this test cross-platform.
124 MULTIPROCESS_TEST_MAIN(RunTestDescriptorClientSandboxed) {
125 struct stat st;
126 const int fd = open(kDevZeroPath, O_RDONLY);
127 fstat(fd, &st);
128 if (HANDLE_EINTR(close(fd)) < 0) {
129 return -1;
132 // Enable the Sandbox.
133 char* error_buff = NULL;
134 int error = sandbox_init(kSBXProfilePureComputation, SANDBOX_NAMED,
135 &error_buff);
136 bool success = (error == 0 && error_buff == NULL);
137 if (!success) {
138 return -1;
141 sandbox_free_error(error_buff);
143 // Make sure Sandbox is really enabled.
144 if (open(kDevZeroPath, O_RDONLY) != -1) {
145 LOG(ERROR) << "Sandbox wasn't properly enabled";
146 return -1;
149 // See if we can receive a file descriptor.
150 return TestDescriptorClient(st.st_ino);
153 // Test that FDs are correctly sent to a sandboxed process.
154 TEST_F(IPCChannelTest, DescriptorTestSandboxed) {
155 // Setup IPC channel.
156 MyChannelDescriptorListener listener(-1);
158 IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER,
159 &listener);
160 ASSERT_TRUE(chan.Connect());
162 base::ProcessHandle process_handle = SpawnChild(
163 TEST_DESCRIPTOR_CLIENT_SANDBOXED,
164 &chan);
165 TestDescriptorServer(chan, process_handle);
167 #endif // defined(OS_MACOSX)
169 MULTIPROCESS_TEST_MAIN(RunTestDescriptorClient) {
170 struct stat st;
171 const int fd = open(kDevZeroPath, O_RDONLY);
172 fstat(fd, &st);
173 EXPECT_GE(HANDLE_EINTR(close(fd)), 0);
175 return TestDescriptorClient(st.st_ino);
178 TEST_F(IPCChannelTest, DescriptorTest) {
179 // Setup IPC channel.
180 MyChannelDescriptorListener listener(-1);
182 IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER,
183 &listener);
184 ASSERT_TRUE(chan.Connect());
186 base::ProcessHandle process_handle = SpawnChild(TEST_DESCRIPTOR_CLIENT,
187 &chan);
188 TestDescriptorServer(chan, process_handle);
191 #endif // defined(OS_POSIX)