Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(383)

Side by Side Diff: ipc/ipc_send_fds_test.cc

Issue 12051048: Refactor (many) IPC tests, notably most of the multiprocess tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix win Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ipc/ipc_perftests.cc ('k') | ipc/ipc_test_base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "build/build_config.h" 5 #include "build/build_config.h"
6 6
7 #if defined(OS_POSIX)
7 #if defined(OS_MACOSX) 8 #if defined(OS_MACOSX)
8 extern "C" { 9 extern "C" {
9 #include <sandbox.h> 10 #include <sandbox.h>
10 } 11 }
11 #endif 12 #endif
12 #include <fcntl.h> 13 #include <fcntl.h>
13 #include <sys/stat.h> 14 #include <sys/stat.h>
15 #include <unistd.h>
14 16
17 #include "base/file_descriptor_posix.h"
15 #include "base/message_loop.h" 18 #include "base/message_loop.h"
19 #include "base/pickle.h"
16 #include "base/posix/eintr_wrapper.h" 20 #include "base/posix/eintr_wrapper.h"
17 #include "ipc/ipc_channel.h"
18 #include "ipc/ipc_listener.h"
19 #include "ipc/ipc_message_utils.h" 21 #include "ipc/ipc_message_utils.h"
20 #include "ipc/ipc_multiprocess_test.h"
21 #include "ipc/ipc_test_base.h" 22 #include "ipc/ipc_test_base.h"
22 23
23 #if defined(OS_POSIX)
24 #include "base/file_descriptor_posix.h"
25
26 namespace { 24 namespace {
27 25
28 const unsigned kNumFDsToSend = 20; 26 const unsigned kNumFDsToSend = 20;
29 const char* kDevZeroPath = "/dev/zero"; 27 const char* kDevZeroPath = "/dev/zero";
30 28
31 static void VerifyAndCloseDescriptor(int fd, ino_t inode_num) { 29 static void VerifyAndCloseDescriptor(int fd, ino_t inode_num) {
32 // Check that we can read from the FD. 30 // Check that we can read from the FD.
33 char buf; 31 char buf;
34 ssize_t amt_read = read(fd, &buf, 1); 32 ssize_t amt_read = read(fd, &buf, 1);
35 ASSERT_EQ(amt_read, 1); 33 ASSERT_EQ(amt_read, 1);
36 ASSERT_EQ(buf, 0); // /dev/zero always reads NUL bytes. 34 ASSERT_EQ(buf, 0); // /dev/zero always reads 0 bytes.
37 35
38 struct stat st; 36 struct stat st;
39 ASSERT_EQ(fstat(fd, &st), 0); 37 ASSERT_EQ(fstat(fd, &st), 0);
40 38
41 ASSERT_EQ(close(fd), 0); 39 ASSERT_EQ(close(fd), 0);
42 40
43 // We compare iNode numbers to check that the file sent over the wire 41 // Compare inode numbers to check that the file sent over the wire is actually
44 // was actually the same physical file as the one we were expecting. 42 // the one expected.
45 ASSERT_EQ(inode_num, st.st_ino); 43 ASSERT_EQ(inode_num, st.st_ino);
46 } 44 }
47 45
48 class MyChannelDescriptorListener : public IPC::Listener { 46 class MyChannelDescriptorListener : public IPC::Listener {
49 public: 47 public:
50 MyChannelDescriptorListener(ino_t expected_inode_num) 48 explicit MyChannelDescriptorListener(ino_t expected_inode_num)
51 : expected_inode_num_(expected_inode_num), 49 : expected_inode_num_(expected_inode_num),
52 num_fds_received_(0) {} 50 num_fds_received_(0) {}
53 51
54 virtual bool OnMessageReceived(const IPC::Message& message) { 52 virtual bool OnMessageReceived(const IPC::Message& message) {
55 PickleIterator iter(message); 53 PickleIterator iter(message);
56 54
57 ++num_fds_received_; 55 ++num_fds_received_;
58 base::FileDescriptor descriptor; 56 base::FileDescriptor descriptor;
59 57
60 IPC::ParamTraits<base::FileDescriptor>::Read( 58 IPC::ParamTraits<base::FileDescriptor>::Read(&message, &iter, &descriptor);
61 &message, &iter, &descriptor);
62 59
63 VerifyAndCloseDescriptor(descriptor.fd, expected_inode_num_); 60 VerifyAndCloseDescriptor(descriptor.fd, expected_inode_num_);
64 if (num_fds_received_ == kNumFDsToSend) { 61 if (num_fds_received_ == kNumFDsToSend)
65 MessageLoop::current()->Quit(); 62 MessageLoop::current()->Quit();
66 } 63
67 return true; 64 return true;
68 } 65 }
69 66
70 virtual void OnChannelError() { 67 virtual void OnChannelError() {
71 MessageLoop::current()->Quit(); 68 MessageLoop::current()->Quit();
72 } 69 }
73 70
74 bool GotExpectedNumberOfDescriptors() { 71 bool GotExpectedNumberOfDescriptors() const {
75 return kNumFDsToSend == num_fds_received_; 72 return num_fds_received_ == kNumFDsToSend;
76 } 73 }
77 74
78 private: 75 private:
79 ino_t expected_inode_num_; 76 ino_t expected_inode_num_;
80 unsigned num_fds_received_; 77 unsigned num_fds_received_;
81 }; 78 };
82 79
83 void TestDescriptorServer(IPC::Channel& chan, 80 class IPCSendFdsTest : public IPCTestBase {
84 base::ProcessHandle process_handle) { 81 protected:
85 ASSERT_TRUE(process_handle); 82 void RunServer() {
83 // Set up IPC channel and start client.
84 MyChannelDescriptorListener listener(-1);
85 CreateChannel(&listener);
86 ASSERT_TRUE(ConnectChannel());
87 ASSERT_TRUE(StartClient());
86 88
87 for (unsigned i = 0; i < kNumFDsToSend; ++i) { 89 for (unsigned i = 0; i < kNumFDsToSend; ++i) {
88 base::FileDescriptor descriptor; 90 const int fd = open(kDevZeroPath, O_RDONLY);
89 const int fd = open(kDevZeroPath, O_RDONLY); 91 ASSERT_GE(fd, 0);
90 ASSERT_GE(fd, 0); 92 base::FileDescriptor descriptor(fd, true);
91 descriptor.auto_close = true;
92 descriptor.fd = fd;
93 93
94 IPC::Message* message = new IPC::Message(0, // routing_id 94 IPC::Message* message =
95 3, // message type 95 new IPC::Message(0, 3, IPC::Message::PRIORITY_NORMAL);
96 IPC::Message::PRIORITY_NORMAL); 96 IPC::ParamTraits<base::FileDescriptor>::Write(message, descriptor);
97 IPC::ParamTraits<base::FileDescriptor>::Write(message, descriptor); 97 ASSERT_TRUE(sender()->Send(message));
98 ASSERT_TRUE(chan.Send(message)); 98 }
99
100 // Run message loop.
101 MessageLoop::current()->Run();
102
103 // Close the channel so the client's OnChannelError() gets fired.
104 channel()->Close();
105
106 EXPECT_TRUE(WaitForClientShutdown());
107 DestroyChannel();
99 } 108 }
109 };
110
111 TEST_F(IPCSendFdsTest, DescriptorTest) {
112 Init("SendFdsClient");
113 RunServer();
114 }
115
116 int SendFdsClientCommon(const std::string& test_client_name,
117 ino_t expected_inode_num) {
118 MessageLoopForIO main_message_loop;
119 MyChannelDescriptorListener listener(expected_inode_num);
120
121 // Set up IPC channel.
122 IPC::Channel channel(IPCTestBase::GetChannelName(test_client_name),
123 IPC::Channel::MODE_CLIENT,
124 &listener);
125 CHECK(channel.Connect());
100 126
101 // Run message loop. 127 // Run message loop.
102 MessageLoop::current()->Run(); 128 MessageLoop::current()->Run();
103 129
104 // Close Channel so client gets its OnChannelError() callback fired. 130 // Verify that the message loop was exited due to getting the correct number
105 chan.Close(); 131 // of descriptors, and not because of the channel closing unexpectedly.
106
107 // Cleanup child process.
108 EXPECT_TRUE(base::WaitForSingleProcess(
109 process_handle, base::TimeDelta::FromSeconds(5)));
110 }
111
112 int TestDescriptorClient(ino_t expected_inode_num) {
113 MessageLoopForIO main_message_loop;
114 MyChannelDescriptorListener listener(expected_inode_num);
115
116 // Setup IPC channel.
117 IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_CLIENT,
118 &listener);
119 CHECK(chan.Connect());
120
121 // Run message loop so IPC Channel can handle message IO.
122 MessageLoop::current()->Run();
123
124 // Verify that the message loop was exited due to getting the correct
125 // number of descriptors, and not because the channel closing unexpectedly.
126 CHECK(listener.GotExpectedNumberOfDescriptors()); 132 CHECK(listener.GotExpectedNumberOfDescriptors());
127 133
128 return 0; 134 return 0;
129 } 135 }
130 136
131 class IPCSendFdsTest : public IPCTestBase { 137 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendFdsClient) {
132 }; 138 struct stat st;
139 int fd = open(kDevZeroPath, O_RDONLY);
140 fstat(fd, &st);
141 EXPECT_GE(HANDLE_EINTR(close(fd)), 0);
142 return SendFdsClientCommon("SendFdsClient", st.st_ino);
143 }
133 144
134 #if defined(OS_MACOSX) 145 #if defined(OS_MACOSX)
146 // Test that FDs are correctly sent to a sandboxed process.
135 // TODO(port): Make this test cross-platform. 147 // TODO(port): Make this test cross-platform.
136 MULTIPROCESS_IPC_TEST_MAIN(RunTestDescriptorClientSandboxed) { 148 TEST_F(IPCSendFdsTest, DescriptorTestSandboxed) {
149 Init("SendFdsSandboxedClient");
150 RunServer();
151 }
152
153 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendFdsSandboxedClient) {
137 struct stat st; 154 struct stat st;
138 const int fd = open(kDevZeroPath, O_RDONLY); 155 const int fd = open(kDevZeroPath, O_RDONLY);
139 fstat(fd, &st); 156 fstat(fd, &st);
140 if (HANDLE_EINTR(close(fd)) < 0) { 157 if (HANDLE_EINTR(close(fd)) < 0)
141 return -1; 158 return -1;
142 }
143 159
144 // Enable the Sandbox. 160 // Enable the sandbox.
145 char* error_buff = NULL; 161 char* error_buff = NULL;
146 int error = sandbox_init(kSBXProfilePureComputation, SANDBOX_NAMED, 162 int error = sandbox_init(kSBXProfilePureComputation, SANDBOX_NAMED,
147 &error_buff); 163 &error_buff);
148 bool success = (error == 0 && error_buff == NULL); 164 bool success = (error == 0 && error_buff == NULL);
149 if (!success) { 165 if (!success)
150 return -1; 166 return -1;
151 }
152 167
153 sandbox_free_error(error_buff); 168 sandbox_free_error(error_buff);
154 169
155 // Make sure Sandbox is really enabled. 170 // Make sure sandbox is really enabled.
156 if (open(kDevZeroPath, O_RDONLY) != -1) { 171 if (open(kDevZeroPath, O_RDONLY) != -1) {
157 LOG(ERROR) << "Sandbox wasn't properly enabled"; 172 LOG(ERROR) << "Sandbox wasn't properly enabled";
158 return -1; 173 return -1;
159 } 174 }
160 175
161 // See if we can receive a file descriptor. 176 // See if we can receive a file descriptor.
162 return TestDescriptorClient(st.st_ino); 177 return SendFdsClientCommon("SendFdsSandboxedClient", st.st_ino);
163 }
164
165 // Test that FDs are correctly sent to a sandboxed process.
166 TEST_F(IPCSendFdsTest, DescriptorTestSandboxed) {
167 // Setup IPC channel.
168 MyChannelDescriptorListener listener(-1);
169
170 IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER,
171 &listener);
172 ASSERT_TRUE(chan.Connect());
173
174 base::ProcessHandle process_handle = SpawnChild(
175 TEST_DESCRIPTOR_CLIENT_SANDBOXED,
176 &chan);
177 TestDescriptorServer(chan, process_handle);
178 } 178 }
179 #endif // defined(OS_MACOSX) 179 #endif // defined(OS_MACOSX)
180 180
181 MULTIPROCESS_IPC_TEST_MAIN(RunTestDescriptorClient) {
182 struct stat st;
183 const int fd = open(kDevZeroPath, O_RDONLY);
184 fstat(fd, &st);
185 EXPECT_GE(HANDLE_EINTR(close(fd)), 0);
186
187 return TestDescriptorClient(st.st_ino);
188 }
189
190 TEST_F(IPCSendFdsTest, DescriptorTest) {
191 // Setup IPC channel.
192 MyChannelDescriptorListener listener(-1);
193
194 IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER,
195 &listener);
196 ASSERT_TRUE(chan.Connect());
197
198 base::ProcessHandle process_handle = SpawnChild(TEST_DESCRIPTOR_CLIENT,
199 &chan);
200 TestDescriptorServer(chan, process_handle);
201 }
202
203 } // namespace 181 } // namespace
204 182
205 #endif // defined(OS_POSIX) 183 #endif // defined(OS_POSIX)
OLDNEW
« no previous file with comments | « ipc/ipc_perftests.cc ('k') | ipc/ipc_test_base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698