Index: ipc/ipc_send_fds_test.cc |
diff --git a/ipc/ipc_send_fds_test.cc b/ipc/ipc_send_fds_test.cc |
index 005103c3dbb8cd3c38d35be6bf7b0507bb8e6200..5699e6d99f7649248b09c033cdc039c22562ee36 100644 |
--- a/ipc/ipc_send_fds_test.cc |
+++ b/ipc/ipc_send_fds_test.cc |
@@ -4,6 +4,7 @@ |
#include "build/build_config.h" |
+#if defined(OS_POSIX) |
#if defined(OS_MACOSX) |
extern "C" { |
#include <sandbox.h> |
@@ -11,18 +12,15 @@ extern "C" { |
#endif |
#include <fcntl.h> |
#include <sys/stat.h> |
+#include <unistd.h> |
+#include "base/file_descriptor_posix.h" |
#include "base/message_loop.h" |
+#include "base/pickle.h" |
#include "base/posix/eintr_wrapper.h" |
-#include "ipc/ipc_channel.h" |
-#include "ipc/ipc_listener.h" |
#include "ipc/ipc_message_utils.h" |
-#include "ipc/ipc_multiprocess_test.h" |
#include "ipc/ipc_test_base.h" |
-#if defined(OS_POSIX) |
-#include "base/file_descriptor_posix.h" |
- |
namespace { |
const unsigned kNumFDsToSend = 20; |
@@ -33,21 +31,21 @@ static void VerifyAndCloseDescriptor(int fd, ino_t inode_num) { |
char buf; |
ssize_t amt_read = read(fd, &buf, 1); |
ASSERT_EQ(amt_read, 1); |
- ASSERT_EQ(buf, 0); // /dev/zero always reads NUL bytes. |
+ ASSERT_EQ(buf, 0); // /dev/zero always reads 0 bytes. |
struct stat st; |
ASSERT_EQ(fstat(fd, &st), 0); |
ASSERT_EQ(close(fd), 0); |
- // We compare iNode numbers to check that the file sent over the wire |
- // was actually the same physical file as the one we were expecting. |
+ // Compare inode numbers to check that the file sent over the wire is actually |
+ // the one expected. |
ASSERT_EQ(inode_num, st.st_ino); |
} |
class MyChannelDescriptorListener : public IPC::Listener { |
public: |
- MyChannelDescriptorListener(ino_t expected_inode_num) |
+ explicit MyChannelDescriptorListener(ino_t expected_inode_num) |
: expected_inode_num_(expected_inode_num), |
num_fds_received_(0) {} |
@@ -57,13 +55,12 @@ class MyChannelDescriptorListener : public IPC::Listener { |
++num_fds_received_; |
base::FileDescriptor descriptor; |
- IPC::ParamTraits<base::FileDescriptor>::Read( |
- &message, &iter, &descriptor); |
+ IPC::ParamTraits<base::FileDescriptor>::Read(&message, &iter, &descriptor); |
VerifyAndCloseDescriptor(descriptor.fd, expected_inode_num_); |
- if (num_fds_received_ == kNumFDsToSend) { |
+ if (num_fds_received_ == kNumFDsToSend) |
MessageLoop::current()->Quit(); |
- } |
+ |
return true; |
} |
@@ -71,8 +68,8 @@ class MyChannelDescriptorListener : public IPC::Listener { |
MessageLoop::current()->Quit(); |
} |
- bool GotExpectedNumberOfDescriptors() { |
- return kNumFDsToSend == num_fds_received_; |
+ bool GotExpectedNumberOfDescriptors() const { |
+ return num_fds_received_ == kNumFDsToSend; |
} |
private: |
@@ -80,126 +77,107 @@ class MyChannelDescriptorListener : public IPC::Listener { |
unsigned num_fds_received_; |
}; |
-void TestDescriptorServer(IPC::Channel& chan, |
- base::ProcessHandle process_handle) { |
- ASSERT_TRUE(process_handle); |
+class IPCSendFdsTest : public IPCTestBase { |
+ protected: |
+ void RunServer() { |
+ // Set up IPC channel and start client. |
+ MyChannelDescriptorListener listener(-1); |
+ CreateChannel(&listener); |
+ ASSERT_TRUE(ConnectChannel()); |
+ ASSERT_TRUE(StartClient()); |
+ |
+ for (unsigned i = 0; i < kNumFDsToSend; ++i) { |
+ const int fd = open(kDevZeroPath, O_RDONLY); |
+ ASSERT_GE(fd, 0); |
+ base::FileDescriptor descriptor(fd, true); |
+ |
+ IPC::Message* message = |
+ new IPC::Message(0, 3, IPC::Message::PRIORITY_NORMAL); |
+ IPC::ParamTraits<base::FileDescriptor>::Write(message, descriptor); |
+ ASSERT_TRUE(sender()->Send(message)); |
+ } |
- for (unsigned i = 0; i < kNumFDsToSend; ++i) { |
- base::FileDescriptor descriptor; |
- const int fd = open(kDevZeroPath, O_RDONLY); |
- ASSERT_GE(fd, 0); |
- descriptor.auto_close = true; |
- descriptor.fd = fd; |
- |
- IPC::Message* message = new IPC::Message(0, // routing_id |
- 3, // message type |
- IPC::Message::PRIORITY_NORMAL); |
- IPC::ParamTraits<base::FileDescriptor>::Write(message, descriptor); |
- ASSERT_TRUE(chan.Send(message)); |
- } |
+ // Run message loop. |
+ MessageLoop::current()->Run(); |
- // Run message loop. |
- MessageLoop::current()->Run(); |
+ // Close the channel so the client's OnChannelError() gets fired. |
+ channel()->Close(); |
- // Close Channel so client gets its OnChannelError() callback fired. |
- chan.Close(); |
+ EXPECT_TRUE(WaitForClientShutdown()); |
+ DestroyChannel(); |
+ } |
+}; |
- // Cleanup child process. |
- EXPECT_TRUE(base::WaitForSingleProcess( |
- process_handle, base::TimeDelta::FromSeconds(5))); |
+TEST_F(IPCSendFdsTest, DescriptorTest) { |
+ Init("SendFdsClient"); |
+ RunServer(); |
} |
-int TestDescriptorClient(ino_t expected_inode_num) { |
+int SendFdsClientCommon(const std::string& test_client_name, |
+ ino_t expected_inode_num) { |
MessageLoopForIO main_message_loop; |
MyChannelDescriptorListener listener(expected_inode_num); |
- // Setup IPC channel. |
- IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_CLIENT, |
- &listener); |
- CHECK(chan.Connect()); |
+ // Set up IPC channel. |
+ IPC::Channel channel(IPCTestBase::GetChannelName(test_client_name), |
+ IPC::Channel::MODE_CLIENT, |
+ &listener); |
+ CHECK(channel.Connect()); |
- // Run message loop so IPC Channel can handle message IO. |
+ // Run message loop. |
MessageLoop::current()->Run(); |
- // Verify that the message loop was exited due to getting the correct |
- // number of descriptors, and not because the channel closing unexpectedly. |
+ // Verify that the message loop was exited due to getting the correct number |
+ // of descriptors, and not because of the channel closing unexpectedly. |
CHECK(listener.GotExpectedNumberOfDescriptors()); |
return 0; |
} |
-class IPCSendFdsTest : public IPCTestBase { |
-}; |
+MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendFdsClient) { |
+ struct stat st; |
+ int fd = open(kDevZeroPath, O_RDONLY); |
+ fstat(fd, &st); |
+ EXPECT_GE(HANDLE_EINTR(close(fd)), 0); |
+ return SendFdsClientCommon("SendFdsClient", st.st_ino); |
+} |
#if defined(OS_MACOSX) |
+// Test that FDs are correctly sent to a sandboxed process. |
// TODO(port): Make this test cross-platform. |
-MULTIPROCESS_IPC_TEST_MAIN(RunTestDescriptorClientSandboxed) { |
+TEST_F(IPCSendFdsTest, DescriptorTestSandboxed) { |
+ Init("SendFdsSandboxedClient"); |
+ RunServer(); |
+} |
+ |
+MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendFdsSandboxedClient) { |
struct stat st; |
const int fd = open(kDevZeroPath, O_RDONLY); |
fstat(fd, &st); |
- if (HANDLE_EINTR(close(fd)) < 0) { |
+ if (HANDLE_EINTR(close(fd)) < 0) |
return -1; |
- } |
- // Enable the Sandbox. |
+ // Enable the sandbox. |
char* error_buff = NULL; |
int error = sandbox_init(kSBXProfilePureComputation, SANDBOX_NAMED, |
&error_buff); |
bool success = (error == 0 && error_buff == NULL); |
- if (!success) { |
+ if (!success) |
return -1; |
- } |
sandbox_free_error(error_buff); |
- // Make sure Sandbox is really enabled. |
+ // Make sure sandbox is really enabled. |
if (open(kDevZeroPath, O_RDONLY) != -1) { |
LOG(ERROR) << "Sandbox wasn't properly enabled"; |
return -1; |
} |
// See if we can receive a file descriptor. |
- return TestDescriptorClient(st.st_ino); |
-} |
- |
-// Test that FDs are correctly sent to a sandboxed process. |
-TEST_F(IPCSendFdsTest, DescriptorTestSandboxed) { |
- // Setup IPC channel. |
- MyChannelDescriptorListener listener(-1); |
- |
- IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER, |
- &listener); |
- ASSERT_TRUE(chan.Connect()); |
- |
- base::ProcessHandle process_handle = SpawnChild( |
- TEST_DESCRIPTOR_CLIENT_SANDBOXED, |
- &chan); |
- TestDescriptorServer(chan, process_handle); |
+ return SendFdsClientCommon("SendFdsSandboxedClient", st.st_ino); |
} |
#endif // defined(OS_MACOSX) |
-MULTIPROCESS_IPC_TEST_MAIN(RunTestDescriptorClient) { |
- struct stat st; |
- const int fd = open(kDevZeroPath, O_RDONLY); |
- fstat(fd, &st); |
- EXPECT_GE(HANDLE_EINTR(close(fd)), 0); |
- |
- return TestDescriptorClient(st.st_ino); |
-} |
- |
-TEST_F(IPCSendFdsTest, DescriptorTest) { |
- // Setup IPC channel. |
- MyChannelDescriptorListener listener(-1); |
- |
- IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER, |
- &listener); |
- ASSERT_TRUE(chan.Connect()); |
- |
- base::ProcessHandle process_handle = SpawnChild(TEST_DESCRIPTOR_CLIENT, |
- &chan); |
- TestDescriptorServer(chan, process_handle); |
-} |
- |
} // namespace |
#endif // defined(OS_POSIX) |