diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-03-08 10:28:10 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-03-20 13:40:30 +0000 |
commit | e733310db58160074f574c429d48f8308c0afe17 (patch) | |
tree | f8aef4b7e62a69928dbcf880620eece20f98c6df /chromium/ipc/ipc_send_fds_test.cc | |
parent | 2f583e4aec1ae3a86fa047829c96b310dc12ecdf (diff) | |
download | qtwebengine-chromium-e733310db58160074f574c429d48f8308c0afe17.tar.gz |
BASELINE: Update Chromium to 56.0.2924.122
Change-Id: I4e04de8f47e47e501c46ed934c76a431c6337ced
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/ipc/ipc_send_fds_test.cc')
-rw-r--r-- | chromium/ipc/ipc_send_fds_test.cc | 237 |
1 files changed, 29 insertions, 208 deletions
diff --git a/chromium/ipc/ipc_send_fds_test.cc b/chromium/ipc/ipc_send_fds_test.cc index f92b119a3ca..f648b6411ab 100644 --- a/chromium/ipc/ipc_send_fds_test.cc +++ b/chromium/ipc/ipc_send_fds_test.cc @@ -113,15 +113,13 @@ class MyChannelDescriptorListener : public MyChannelDescriptorListenerBase { unsigned num_fds_received_; }; - -class IPCSendFdsTest : public IPCTestBase { +class IPCSendFdsTest : public IPCChannelMojoTestBase { 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 < kNumMessages; ++i) { IPC::Message* message = @@ -151,33 +149,34 @@ TEST_F(IPCSendFdsTest, DescriptorTest) { RunServer(); } -int SendFdsClientCommon(const std::string& test_client_name, - ino_t expected_inode_num) { - base::MessageLoopForIO main_message_loop; - MyChannelDescriptorListener listener(expected_inode_num); +class SendFdsTestClientFixture : public IpcChannelMojoTestClient { + protected: + void SendFdsClientCommon(const std::string& test_client_name, + ino_t expected_inode_num) { + MyChannelDescriptorListener listener(expected_inode_num); - // Set up IPC channel. - std::unique_ptr<IPC::Channel> channel(IPC::Channel::CreateClient( - IPCTestBase::GetChannelName(test_client_name), &listener, - main_message_loop.task_runner())); - CHECK(channel->Connect()); + // Set up IPC channel. + Connect(&listener); - // Run message loop. - base::RunLoop().Run(); + // Run message loop. + base::RunLoop().Run(); - // 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()); + // Verify that the message loop was exited due to getting the correct number + // of descriptors, and not because of the channel closing unexpectedly. + EXPECT_TRUE(listener.GotExpectedNumberOfDescriptors()); - return 0; -} + Close(); + } +}; -MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendFdsClient) { +DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE( + SendFdsClient, + SendFdsTestClientFixture) { struct stat st; int fd = open(kDevZeroPath, O_RDONLY); fstat(fd, &st); EXPECT_GE(IGNORE_EINTR(close(fd)), 0); - return SendFdsClientCommon("SendFdsClient", st.st_ino); + SendFdsClientCommon("SendFdsClient", st.st_ino); } #if defined(OS_MACOSX) @@ -188,210 +187,32 @@ TEST_F(IPCSendFdsTest, DescriptorTestSandboxed) { RunServer(); } -MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendFdsSandboxedClient) { +DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE( + SendFdsSandboxedClient, + SendFdsTestClientFixture) { struct stat st; const int fd = open(kDevZeroPath, O_RDONLY); fstat(fd, &st); - if (IGNORE_EINTR(close(fd)) < 0) - return -1; + ASSERT_LE(0, IGNORE_EINTR(close(fd))); // Enable the sandbox. char* error_buff = NULL; int error = sandbox::Seatbelt::Init( sandbox::Seatbelt::kProfilePureComputation, SANDBOX_NAMED, &error_buff); - bool success = (error == 0 && error_buff == NULL); - if (!success) - return -1; + ASSERT_EQ(0, error); + ASSERT_FALSE(error_buff); sandbox::Seatbelt::FreeError(error_buff); // Make sure sandbox is really enabled. - if (open(kDevZeroPath, O_RDONLY) != -1) { - LOG(ERROR) << "Sandbox wasn't properly enabled"; - return -1; - } + ASSERT_EQ(-1, open(kDevZeroPath, O_RDONLY)) + << "Sandbox wasn't properly enabled"; // See if we can receive a file descriptor. - return SendFdsClientCommon("SendFdsSandboxedClient", st.st_ino); + SendFdsClientCommon("SendFdsSandboxedClient", st.st_ino); } #endif // defined(OS_MACOSX) - -class MyCBListener : public MyChannelDescriptorListenerBase { - public: - MyCBListener(base::Callback<void(int)> cb, int fds_to_send) - : MyChannelDescriptorListenerBase(), - cb_(cb) { - } - - protected: - void HandleFD(int fd) override { cb_.Run(fd); } - private: - base::Callback<void(int)> cb_; -}; - -std::pair<int, int> make_socket_pair() { - int pipe_fds[2]; - CHECK_EQ(0, HANDLE_EINTR(socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds))); - return std::pair<int, int>(pipe_fds[0], pipe_fds[1]); -} - -static void null_cb(int unused_fd) { - NOTREACHED(); -} - -class PipeChannelHelper { - public: - PipeChannelHelper(base::Thread* in_thread, - base::Thread* out_thread, - base::Callback<void(int)> cb, - int fds_to_send) : - in_thread_(in_thread), - out_thread_(out_thread), - cb_listener_(cb, fds_to_send), - null_listener_(base::Bind(&null_cb), 0) { - } - - void Init() { - IPC::ChannelHandle in_handle("IN"); - in = IPC::Channel::CreateServer( - in_handle, &null_listener_, in_thread_->task_runner()); - IPC::ChannelHandle out_handle( - "OUT", base::FileDescriptor(in->TakeClientFileDescriptor())); - out = IPC::Channel::CreateClient( - out_handle, &cb_listener_, out_thread_->task_runner()); - // PostTask the connect calls to make sure the callbacks happens - // on the right threads. - in_thread_->task_runner()->PostTask( - FROM_HERE, base::Bind(&PipeChannelHelper::Connect, in.get())); - out_thread_->task_runner()->PostTask( - FROM_HERE, base::Bind(&PipeChannelHelper::Connect, out.get())); - } - - static void DestroyChannel(std::unique_ptr<IPC::Channel>* c, - base::WaitableEvent* event) { - c->reset(0); - event->Signal(); - } - - ~PipeChannelHelper() { - base::WaitableEvent a(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - base::WaitableEvent b(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - in_thread_->task_runner()->PostTask( - FROM_HERE, base::Bind(&PipeChannelHelper::DestroyChannel, &in, &a)); - out_thread_->task_runner()->PostTask( - FROM_HERE, base::Bind(&PipeChannelHelper::DestroyChannel, &out, &b)); - a.Wait(); - b.Wait(); - } - - static void Connect(IPC::Channel *channel) { - EXPECT_TRUE(channel->Connect()); - } - - void Send(int fd) { - CHECK_EQ(base::MessageLoop::current(), in_thread_->message_loop()); - - 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(in->Send(message)); - } - - private: - std::unique_ptr<IPC::Channel> in, out; - base::Thread* in_thread_; - base::Thread* out_thread_; - MyCBListener cb_listener_; - MyCBListener null_listener_; -}; - -// This test is meant to provoke a kernel bug on OSX, and to prove -// that the workaround for it is working. It sets up two pipes and three -// threads, the producer thread creates socketpairs and sends one of the fds -// over pipe1 to the middleman thread. The middleman thread simply takes the fd -// sends it over pipe2 to the consumer thread. The consumer thread writes a byte -// to each fd it receives and then closes the pipe. The producer thread reads -// the bytes back from each pair of pipes and make sure that everything worked. -// This feedback mechanism makes sure that not too many file descriptors are -// in flight at the same time. For more info on the bug, see: -// http://crbug.com/298276 -class IPCMultiSendingFdsTest : public testing::Test { - public: - IPCMultiSendingFdsTest() - : received_(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED) {} - - void Producer(PipeChannelHelper* dest, - base::Thread* t, - int pipes_to_send) { - for (int i = 0; i < pipes_to_send; i++) { - received_.Reset(); - std::pair<int, int> pipe_fds = make_socket_pair(); - t->task_runner()->PostTask( - FROM_HERE, base::Bind(&PipeChannelHelper::Send, - base::Unretained(dest), pipe_fds.second)); - char tmp = 'x'; - CHECK_EQ(1, HANDLE_EINTR(write(pipe_fds.first, &tmp, 1))); - CHECK_EQ(0, IGNORE_EINTR(close(pipe_fds.first))); - received_.Wait(); - } - } - - void ConsumerHandleFD(int fd) { - char tmp = 'y'; - CHECK_EQ(1, HANDLE_EINTR(read(fd, &tmp, 1))); - CHECK_EQ(tmp, 'x'); - CHECK_EQ(0, IGNORE_EINTR(close(fd))); - received_.Signal(); - } - - base::Thread* CreateThread(const char* name) { - base::Thread* ret = new base::Thread(name); - base::Thread::Options options; - options.message_loop_type = base::MessageLoop::TYPE_IO; - ret->StartWithOptions(options); - return ret; - } - - void Run() { - // On my mac, this test fails roughly 35 times per - // million sends with low load, but much more with high load. - // Unless the workaround is in place. With 10000 sends, we - // should see at least a 3% failure rate. - const int pipes_to_send = 20000; - std::unique_ptr<base::Thread> producer(CreateThread("producer")); - std::unique_ptr<base::Thread> middleman(CreateThread("middleman")); - std::unique_ptr<base::Thread> consumer(CreateThread("consumer")); - PipeChannelHelper pipe1( - middleman.get(), - consumer.get(), - base::Bind(&IPCMultiSendingFdsTest::ConsumerHandleFD, - base::Unretained(this)), - pipes_to_send); - PipeChannelHelper pipe2( - producer.get(), - middleman.get(), - base::Bind(&PipeChannelHelper::Send, base::Unretained(&pipe1)), - pipes_to_send); - pipe1.Init(); - pipe2.Init(); - Producer(&pipe2, producer.get(), pipes_to_send); - } - - private: - base::WaitableEvent received_; -}; - -TEST_F(IPCMultiSendingFdsTest, StressTest) { - Run(); -} - } // namespace #endif // defined(OS_POSIX) |