| Index: util/mach/notify_server_test.cc
|
| diff --git a/util/mach/notify_server_test.cc b/util/mach/notify_server_test.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..56529032c5113829e7eb174e7a70acd593b4a8c2
|
| --- /dev/null
|
| +++ b/util/mach/notify_server_test.cc
|
| @@ -0,0 +1,550 @@
|
| +// Copyright 2014 The Crashpad Authors. All rights reserved.
|
| +//
|
| +// Licensed under the Apache License, Version 2.0 (the "License");
|
| +// you may not use this file except in compliance with the License.
|
| +// You may obtain a copy of the License at
|
| +//
|
| +// http://www.apache.org/licenses/LICENSE-2.0
|
| +//
|
| +// Unless required by applicable law or agreed to in writing, software
|
| +// distributed under the License is distributed on an "AS IS" BASIS,
|
| +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| +// See the License for the specific language governing permissions and
|
| +// limitations under the License.
|
| +
|
| +#include "util/mach/notify_server.h"
|
| +
|
| +#include "base/compiler_specific.h"
|
| +#include "base/mac/scoped_mach_port.h"
|
| +#include "gmock/gmock.h"
|
| +#include "gtest/gtest.h"
|
| +#include "util/mach/mach_extensions.h"
|
| +#include "util/mach/mach_message.h"
|
| +#include "util/mach/mach_message_server.h"
|
| +#include "util/test/mac/mach_errors.h"
|
| +
|
| +namespace crashpad {
|
| +namespace test {
|
| +namespace {
|
| +
|
| +using testing::AllOf;
|
| +using testing::Eq;
|
| +using testing::Invoke;
|
| +using testing::Ne;
|
| +using testing::Pointee;
|
| +using testing::ResultOf;
|
| +using testing::Return;
|
| +using testing::SetArgPointee;
|
| +using testing::StrictMock;
|
| +using testing::WithArg;
|
| +
|
| +//! \brief Allocates and returns a new receive right.
|
| +//!
|
| +//! \return The new receive right. On failure, `MACH_PORT_NULL` with a gtest
|
| +//! failure added.
|
| +mach_port_t NewReceiveRight() {
|
| + mach_port_t receive_right;
|
| + kern_return_t kr = mach_port_allocate(
|
| + mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &receive_right);
|
| + if (kr != KERN_SUCCESS) {
|
| + EXPECT_EQ(KERN_SUCCESS, kr) << MachErrorMessage(kr, "mach_port_allocate");
|
| + return MACH_PORT_NULL;
|
| + }
|
| + return receive_right;
|
| +}
|
| +
|
| +//! \brief Adds a send right to an existing receive right.
|
| +//!
|
| +//! \param[in] receive_right The receive right to add a send right to.
|
| +//!
|
| +//! \return The send right, which will have the same name as the receive right.
|
| +//! On failure, `MACH_PORT_NULL` with a gtest failure added.
|
| +mach_port_t SendRightFromReceiveRight(mach_port_t receive_right) {
|
| + kern_return_t kr = mach_port_insert_right(
|
| + mach_task_self(), receive_right, receive_right, MACH_MSG_TYPE_MAKE_SEND);
|
| + if (kr != KERN_SUCCESS) {
|
| + EXPECT_EQ(KERN_SUCCESS, kr)
|
| + << MachErrorMessage(kr, "mach_port_insert_right");
|
| + return MACH_PORT_NULL;
|
| + }
|
| +
|
| + return receive_right;
|
| +}
|
| +
|
| +//! \brief Extracts a send-once right from a receive right.
|
| +//!
|
| +//! \param[in] receive_right The receive right to make a send-once right from.
|
| +//!
|
| +//! \return The send-once right. On failure, `MACH_PORT_NULL` with a gtest
|
| +//! failure added.
|
| +mach_port_t SendOnceRightFromReceiveRight(mach_port_t receive_right) {
|
| + mach_port_t send_once_right;
|
| + mach_msg_type_name_t acquired_type;
|
| + kern_return_t kr = mach_port_extract_right(mach_task_self(),
|
| + receive_right,
|
| + MACH_MSG_TYPE_MAKE_SEND_ONCE,
|
| + &send_once_right,
|
| + &acquired_type);
|
| + if (kr != KERN_SUCCESS) {
|
| + EXPECT_EQ(KERN_SUCCESS, kr)
|
| + << MachErrorMessage(kr, "mach_port_extract_right");
|
| + return MACH_PORT_NULL;
|
| + }
|
| +
|
| + EXPECT_EQ(implicit_cast<mach_msg_type_name_t>(MACH_MSG_TYPE_PORT_SEND_ONCE),
|
| + acquired_type);
|
| +
|
| + return send_once_right;
|
| +}
|
| +
|
| +//! \brief Deallocates a Mach port by calling `mach_port_deallocate()`.
|
| +//!
|
| +//! This function exists to adapt `mach_port_deallocate()` to a function that
|
| +//! accepts a single argument and has no return value. It can be used with the
|
| +//! testing::Invoke() gmock action.
|
| +//!
|
| +//! On failure, a gtest failure will be added.
|
| +void MachPortDeallocate(mach_port_t port) {
|
| + kern_return_t kr = mach_port_deallocate(mach_task_self(), port);
|
| + EXPECT_EQ(KERN_SUCCESS, kr) << MachErrorMessage(kr, "mach_port_deallocate");
|
| +}
|
| +
|
| +//! \brief Determines whether a specific right is held for a Mach port.
|
| +//!
|
| +//! \param[in] port The port to check for a right.
|
| +//! \param[in] right The right to check for.
|
| +//!
|
| +//! \return `true` if \a port has \a right, `false` otherwise. On faliure,
|
| +//! `false` with a gtest failure added.
|
| +bool IsRight(mach_port_t port, mach_port_type_t right) {
|
| + mach_port_type_t type;
|
| + kern_return_t kr = mach_port_type(mach_task_self(), port, &type);
|
| + if (kr != KERN_SUCCESS) {
|
| + EXPECT_EQ(KERN_SUCCESS, kr) << MachErrorMessage(kr, "mach_port_type");
|
| + return false;
|
| + }
|
| +
|
| + return type & right;
|
| +}
|
| +
|
| +//! \brief Determines whether a receive right is held for a Mach port.
|
| +//!
|
| +//! This is a special single-argument form of IsRight() for ease of use in a
|
| +//! gmock matcher.
|
| +//!
|
| +//! \param[in] port The port to check for a receive right.
|
| +//!
|
| +//! \return `true` if a receive right is held, `false` otherwise. On faliure,
|
| +//! `false` with a gtest failure added.
|
| +bool IsReceiveRight(mach_port_t port) {
|
| + return IsRight(port, MACH_PORT_TYPE_RECEIVE);
|
| +}
|
| +
|
| +//! \brief Returns the user reference count for port rights.
|
| +//!
|
| +//! \param[in] port The port whose user reference count should be returned.
|
| +//! \param[in] right The port right to return the user reference count for.
|
| +//!
|
| +//! \return The user reference count for the specified port and right. On
|
| +//! failure, `-1` with a gtest failure added.
|
| +mach_port_urefs_t RightRefCount(mach_port_t port, mach_port_right_t right) {
|
| + mach_port_urefs_t refs;
|
| + kern_return_t kr = mach_port_get_refs(mach_task_self(), port, right, &refs);
|
| + if (kr != KERN_SUCCESS) {
|
| + EXPECT_EQ(KERN_SUCCESS, kr) << MachErrorMessage(kr, "mach_port_get_refs");
|
| + return -1;
|
| + }
|
| +
|
| + return refs;
|
| +}
|
| +
|
| +//! \brief Returns the user reference count for a port’s dead-name rights.
|
| +//!
|
| +//! This is a special single-argument form of RightRefCount() for ease of use in
|
| +//! a gmock matcher.
|
| +//!
|
| +//! \param[in] port The port whose dead-name user reference count should be
|
| +//! returned.
|
| +//!
|
| +//! \return The user reference count for the port’s dead-name rights. On
|
| +//! failure, `-1` with a gtest failure added.
|
| +mach_port_urefs_t DeadNameRightRefCount(mach_port_t port) {
|
| + return RightRefCount(port, MACH_PORT_RIGHT_DEAD_NAME);
|
| +}
|
| +
|
| +class NotifyServerTestBase : public testing::Test,
|
| + public NotifyServer::Interface {
|
| + public:
|
| + // NotifyServer::Interface:
|
| +
|
| + MOCK_METHOD3(DoMachNotifyPortDeleted,
|
| + kern_return_t(notify_port_t notify,
|
| + mach_port_name_t name,
|
| + const mach_msg_trailer_t* trailer));
|
| +
|
| + MOCK_METHOD4(DoMachNotifyPortDestroyed,
|
| + kern_return_t(notify_port_t notify,
|
| + mach_port_t rights,
|
| + const mach_msg_trailer_t* trailer,
|
| + bool* destroy_request));
|
| +
|
| + MOCK_METHOD3(DoMachNotifyNoSenders,
|
| + kern_return_t(notify_port_t notify,
|
| + mach_port_mscount_t mscount,
|
| + const mach_msg_trailer_t* trailer));
|
| +
|
| + MOCK_METHOD2(DoMachNotifySendOnce,
|
| + kern_return_t(notify_port_t notify,
|
| + const mach_msg_trailer_t* trailer));
|
| +
|
| + MOCK_METHOD3(DoMachNotifyDeadName,
|
| + kern_return_t(notify_port_t notify,
|
| + mach_port_name_t name,
|
| + const mach_msg_trailer_t* trailer));
|
| +
|
| + protected:
|
| + NotifyServerTestBase() : testing::Test(), NotifyServer::Interface() {}
|
| +
|
| + ~NotifyServerTestBase() override {}
|
| +
|
| + //! \brief Requests a Mach port notification.
|
| + //!
|
| + //! \a name, \a variant, and \a sync are passed as-is to
|
| + //! `mach_port_request_notification()`. The notification will be sent to a
|
| + //! send-once right made from ServerPort(). Any previous send right for the
|
| + //! notification will be deallocated.
|
| + //!
|
| + //! \return `true` on success, `false` on failure with a gtest failure added.
|
| + bool RequestMachPortNotification(mach_port_t name,
|
| + mach_msg_id_t variant,
|
| + mach_port_mscount_t sync) {
|
| + mach_port_t previous;
|
| + kern_return_t kr =
|
| + mach_port_request_notification(mach_task_self(),
|
| + name,
|
| + variant,
|
| + sync,
|
| + ServerPort(),
|
| + MACH_MSG_TYPE_MAKE_SEND_ONCE,
|
| + &previous);
|
| + if (kr != KERN_SUCCESS) {
|
| + EXPECT_EQ(KERN_SUCCESS, kr)
|
| + << MachErrorMessage(kr, "mach_port_request_notification");
|
| + return false;
|
| + }
|
| +
|
| + base::mac::ScopedMachSendRight previous_owner(previous);
|
| + EXPECT_EQ(kMachPortNull, previous);
|
| +
|
| + return true;
|
| + }
|
| +
|
| + //! \brief Runs a NotifyServer Mach message server.
|
| + //!
|
| + //! The server will listen on ServerPort() in persistent nonblocking mode, and
|
| + //! dispatch received messages to the appropriate NotifyServer::Interface
|
| + //! method. gmock expectations check that the proper method, if any, is called
|
| + //! exactly once, and that no undesired methods are called.
|
| + //!
|
| + //! MachMessageServer::Run() is expected to return `MACH_RCV_TIMED_OUT`,
|
| + //! because it runs in persistent nonblocking mode. If it returns anything
|
| + //! else, a gtest assertion is added.
|
| + void RunServer() {
|
| + NotifyServer notify_server(this);
|
| + mach_msg_return_t mr =
|
| + MachMessageServer::Run(¬ify_server,
|
| + ServerPort(),
|
| + MACH_MSG_OPTION_NONE,
|
| + MachMessageServer::kPersistent,
|
| + MachMessageServer::kReceiveLargeError,
|
| + kMachMessageTimeoutNonblocking);
|
| + ASSERT_EQ(MACH_RCV_TIMED_OUT, mr)
|
| + << MachErrorMessage(mr, "MachMessageServer::Run");
|
| + }
|
| +
|
| + //! \brief Returns the receive right to be used for the server.
|
| + //!
|
| + //! This receive right is created lazily on a per-test basis. It is destroyed
|
| + //! by TearDown() at the conclusion of each test.
|
| + //!
|
| + //! \return The server port receive right, creating it if one has not yet been
|
| + //! established for the current test. On failure, returns `MACH_PORT_NULL`
|
| + //! with a gtest failure added.
|
| + mach_port_t ServerPort() {
|
| + if (!server_port_) {
|
| + server_port_.reset(NewReceiveRight());
|
| + }
|
| +
|
| + return server_port_;
|
| + }
|
| +
|
| + // testing::Test:
|
| + void TearDown() override {
|
| + server_port_.reset();
|
| + }
|
| +
|
| + private:
|
| + base::mac::ScopedMachReceiveRight server_port_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(NotifyServerTestBase);
|
| +};
|
| +
|
| +using NotifyServerTest = StrictMock<NotifyServerTestBase>;
|
| +
|
| +TEST_F(NotifyServerTest, Basic) {
|
| + NotifyServer server(this);
|
| +
|
| + std::set<mach_msg_id_t> expect_request_ids;
|
| + expect_request_ids.insert(MACH_NOTIFY_PORT_DELETED);
|
| + expect_request_ids.insert(MACH_NOTIFY_PORT_DESTROYED);
|
| + expect_request_ids.insert(MACH_NOTIFY_NO_SENDERS);
|
| + expect_request_ids.insert(MACH_NOTIFY_SEND_ONCE);
|
| + expect_request_ids.insert(MACH_NOTIFY_DEAD_NAME);
|
| + EXPECT_EQ(expect_request_ids, server.MachMessageServerRequestIDs());
|
| +
|
| + // The port-destroyed notification is the largest request message in the
|
| + // subsystem. <mach/notify.h> defines the same structure, but with a basic
|
| + // trailer, so use offsetof to get the size of the basic structure without any
|
| + // trailer.
|
| + EXPECT_EQ(offsetof(mach_port_destroyed_notification_t, trailer),
|
| + server.MachMessageServerRequestSize());
|
| +
|
| + mig_reply_error_t reply;
|
| + EXPECT_EQ(sizeof(reply), server.MachMessageServerReplySize());
|
| +}
|
| +
|
| +// When no notifications are requested, nothing should happen.
|
| +TEST_F(NotifyServerTest, NoNotification) {
|
| + RunServer();
|
| +}
|
| +
|
| +// When a send-once right with a dead-name notification request is deallocated,
|
| +// a port-deleted notification should be generated.
|
| +TEST_F(NotifyServerTest, MachNotifyPortDeleted) {
|
| + base::mac::ScopedMachReceiveRight receive_right(NewReceiveRight());
|
| + ASSERT_NE(kMachPortNull, receive_right);
|
| +
|
| + base::mac::ScopedMachSendRight send_once_right(
|
| + SendOnceRightFromReceiveRight(receive_right));
|
| + ASSERT_NE(kMachPortNull, send_once_right);
|
| +
|
| + ASSERT_TRUE(RequestMachPortNotification(
|
| + send_once_right, MACH_NOTIFY_DEAD_NAME, 0));
|
| +
|
| + EXPECT_CALL(*this, DoMachNotifyPortDeleted(ServerPort(),
|
| + send_once_right.get(),
|
| + Ne(nullptr)))
|
| + .WillOnce(Return(MIG_NO_REPLY))
|
| + .RetiresOnSaturation();
|
| +
|
| + send_once_right.reset();
|
| +
|
| + RunServer();
|
| +}
|
| +
|
| +// When a receive right with a port-destroyed notification request is destroyed,
|
| +// a port-destroyed notification should be generated.
|
| +TEST_F(NotifyServerTest, MachNotifyPortDestroyed) {
|
| + base::mac::ScopedMachReceiveRight receive_right(NewReceiveRight());
|
| + ASSERT_NE(kMachPortNull, receive_right);
|
| +
|
| + ASSERT_TRUE(RequestMachPortNotification(
|
| + receive_right, MACH_NOTIFY_PORT_DESTROYED, 0));
|
| +
|
| + EXPECT_CALL(*this, DoMachNotifyPortDestroyed(ServerPort(),
|
| + ResultOf(IsReceiveRight, true),
|
| + Ne(nullptr),
|
| + Pointee(Eq(false))))
|
| + .WillOnce(DoAll(SetArgPointee<3>(true), Return(MIG_NO_REPLY)))
|
| + .RetiresOnSaturation();
|
| +
|
| + receive_right.reset();
|
| +
|
| + RunServer();
|
| +}
|
| +
|
| +// When a receive right with a port-destroyed notification request is not
|
| +// destroyed, no port-destroyed notification should be generated.
|
| +TEST_F(NotifyServerTest, MachNotifyPortDestroyed_NoNotification) {
|
| + base::mac::ScopedMachReceiveRight receive_right(NewReceiveRight());
|
| + ASSERT_NE(kMachPortNull, receive_right);
|
| +
|
| + ASSERT_TRUE(RequestMachPortNotification(
|
| + receive_right, MACH_NOTIFY_PORT_DESTROYED, 0));
|
| +
|
| + RunServer();
|
| +}
|
| +
|
| +// When a no-senders notification request is registered for a receive right with
|
| +// no senders, a no-senders notification should be generated.
|
| +TEST_F(NotifyServerTest, MachNotifyNoSenders_NoSendRight) {
|
| + base::mac::ScopedMachReceiveRight receive_right(NewReceiveRight());
|
| + ASSERT_NE(kMachPortNull, receive_right);
|
| +
|
| + ASSERT_TRUE(RequestMachPortNotification(
|
| + receive_right, MACH_NOTIFY_NO_SENDERS, 0));
|
| +
|
| + EXPECT_CALL(*this, DoMachNotifyNoSenders(ServerPort(), 0, Ne(nullptr)))
|
| + .WillOnce(Return(MIG_NO_REPLY))
|
| + .RetiresOnSaturation();
|
| +
|
| + RunServer();
|
| +}
|
| +
|
| +// When the last send right corresponding to a receive right with a no-senders
|
| +// notification request is deallocated, a no-senders notification should be
|
| +// generated.
|
| +TEST_F(NotifyServerTest, MachNotifyNoSenders_SendRightDeallocated) {
|
| + base::mac::ScopedMachReceiveRight receive_right(NewReceiveRight());
|
| + ASSERT_NE(kMachPortNull, receive_right);
|
| +
|
| + base::mac::ScopedMachSendRight send_right(
|
| + SendRightFromReceiveRight(receive_right));
|
| + ASSERT_NE(kMachPortNull, send_right);
|
| +
|
| + ASSERT_TRUE(RequestMachPortNotification(
|
| + receive_right, MACH_NOTIFY_NO_SENDERS, 1));
|
| +
|
| + EXPECT_CALL(*this, DoMachNotifyNoSenders(ServerPort(), 1, Ne(nullptr)))
|
| + .WillOnce(Return(MIG_NO_REPLY))
|
| + .RetiresOnSaturation();
|
| +
|
| + send_right.reset();
|
| +
|
| + RunServer();
|
| +}
|
| +
|
| +// When the a receive right with a no-senders notification request never loses
|
| +// all senders, no no-senders notification should be generated.
|
| +TEST_F(NotifyServerTest, MachNotifyNoSenders_NoNotification) {
|
| + base::mac::ScopedMachReceiveRight receive_right(NewReceiveRight());
|
| + ASSERT_NE(kMachPortNull, receive_right);
|
| +
|
| + base::mac::ScopedMachSendRight send_right_0(
|
| + SendRightFromReceiveRight(receive_right));
|
| + ASSERT_NE(kMachPortNull, send_right_0);
|
| +
|
| + base::mac::ScopedMachSendRight send_right_1(
|
| + SendRightFromReceiveRight(receive_right));
|
| + ASSERT_NE(kMachPortNull, send_right_1);
|
| +
|
| + ASSERT_TRUE(RequestMachPortNotification(
|
| + receive_right, MACH_NOTIFY_NO_SENDERS, 1));
|
| +
|
| + send_right_1.reset();
|
| +
|
| + RunServer();
|
| +
|
| + EXPECT_EQ(1u, RightRefCount(receive_right, MACH_PORT_RIGHT_RECEIVE));
|
| + EXPECT_EQ(1u, RightRefCount(receive_right, MACH_PORT_RIGHT_SEND));
|
| +}
|
| +
|
| +// When a send-once right is deallocated without being used, a send-once
|
| +// notification notification should be sent via the send-once right.
|
| +TEST_F(NotifyServerTest, MachNotifySendOnce_ExplicitDeallocation) {
|
| + base::mac::ScopedMachSendRight send_once_right(
|
| + SendOnceRightFromReceiveRight(ServerPort()));
|
| + ASSERT_NE(kMachPortNull, send_once_right);
|
| +
|
| + EXPECT_CALL(*this, DoMachNotifySendOnce(ServerPort(), Ne(nullptr)))
|
| + .WillOnce(Return(MIG_NO_REPLY))
|
| + .RetiresOnSaturation();
|
| +
|
| + send_once_right.reset();
|
| +
|
| + RunServer();
|
| +}
|
| +
|
| +// When a send-once right is sent to a receiver that never dequeues the message,
|
| +// the send-once right is destroyed, and a send-once notification should appear
|
| +// on the reply port.
|
| +TEST_F(NotifyServerTest, MachNotifySendOnce_ImplicitDeallocation) {
|
| + base::mac::ScopedMachReceiveRight receive_right(NewReceiveRight());
|
| + ASSERT_NE(kMachPortNull, receive_right);
|
| +
|
| + mach_msg_empty_send_t message = {};
|
| + message.header.msgh_bits =
|
| + MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE);
|
| + message.header.msgh_size = sizeof(message);
|
| + message.header.msgh_remote_port = receive_right;
|
| + message.header.msgh_local_port = ServerPort();
|
| + mach_msg_return_t mr = mach_msg(&message.header,
|
| + MACH_SEND_MSG | MACH_SEND_TIMEOUT,
|
| + message.header.msgh_size,
|
| + 0,
|
| + MACH_PORT_NULL,
|
| + 0,
|
| + MACH_PORT_NULL);
|
| + ASSERT_EQ(MACH_MSG_SUCCESS, mr) << MachErrorMessage(mr, "mach_msg");
|
| +
|
| + EXPECT_CALL(*this, DoMachNotifySendOnce(ServerPort(), Ne(nullptr)))
|
| + .WillOnce(Return(MIG_NO_REPLY))
|
| + .RetiresOnSaturation();
|
| +
|
| + receive_right.reset();
|
| +
|
| + RunServer();
|
| +}
|
| +
|
| +// When the receive right corresponding to a send-once right with a dead-name
|
| +// notification request is destroyed, a dead-name notification should be
|
| +// generated.
|
| +TEST_F(NotifyServerTest, MachNotifyDeadName) {
|
| + base::mac::ScopedMachReceiveRight receive_right(NewReceiveRight());
|
| + ASSERT_NE(kMachPortNull, receive_right);
|
| +
|
| + base::mac::ScopedMachSendRight send_once_right(
|
| + SendOnceRightFromReceiveRight(receive_right));
|
| + ASSERT_NE(kMachPortNull, send_once_right);
|
| +
|
| + ASSERT_TRUE(RequestMachPortNotification(
|
| + send_once_right, MACH_NOTIFY_DEAD_NAME, 0));
|
| +
|
| + // send_once_right becomes a dead name with the send-once right’s original
|
| + // user reference count of 1, but the dead-name notification increments the
|
| + // dead-name reference count, so it becomes 2. Take care to deallocate that
|
| + // reference. The original reference is managed by send_once_right_owner.
|
| + EXPECT_CALL(*this,
|
| + DoMachNotifyDeadName(ServerPort(),
|
| + AllOf(send_once_right.get(),
|
| + ResultOf(DeadNameRightRefCount, 2)),
|
| + Ne(nullptr)))
|
| + .WillOnce(DoAll(WithArg<1>(Invoke(MachPortDeallocate)),
|
| + Return(MIG_NO_REPLY)))
|
| + .RetiresOnSaturation();
|
| +
|
| + receive_right.reset();
|
| +
|
| + RunServer();
|
| +
|
| + EXPECT_TRUE(IsRight(send_once_right, MACH_PORT_TYPE_DEAD_NAME));
|
| +
|
| + EXPECT_EQ(0u, RightRefCount(send_once_right, MACH_PORT_RIGHT_SEND_ONCE));
|
| + EXPECT_EQ(1u, DeadNameRightRefCount(send_once_right));
|
| +}
|
| +
|
| +// When the receive right corresponding to a send-once right with a dead-name
|
| +// notification request is not destroyed, no dead-name notification should be
|
| +// generated.
|
| +TEST_F(NotifyServerTest, MachNotifyDeadName_NoNotification) {
|
| + base::mac::ScopedMachReceiveRight receive_right(NewReceiveRight());
|
| + ASSERT_NE(kMachPortNull, receive_right);
|
| +
|
| + base::mac::ScopedMachSendRight send_once_right(
|
| + SendOnceRightFromReceiveRight(receive_right));
|
| + ASSERT_NE(kMachPortNull, send_once_right);
|
| +
|
| + ASSERT_TRUE(RequestMachPortNotification(
|
| + send_once_right, MACH_NOTIFY_DEAD_NAME, 0));
|
| +
|
| + RunServer();
|
| +
|
| + EXPECT_FALSE(IsRight(send_once_right, MACH_PORT_TYPE_DEAD_NAME));
|
| +
|
| + EXPECT_EQ(1u, RightRefCount(send_once_right, MACH_PORT_RIGHT_SEND_ONCE));
|
| + EXPECT_EQ(0u, DeadNameRightRefCount(send_once_right));
|
| +}
|
| +
|
| +} // namespace
|
| +} // namespace test
|
| +} // namespace crashpad
|
|
|