// 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 <stddef.h>

#include "base/compiler_specific.h"
#include "base/mac/scoped_mach_port.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test/mac/mach_errors.h"
#include "util/mach/mach_extensions.h"
#include "util/mach/mach_message.h"
#include "util/mach/mach_message_server.h"
#include "util/misc/implicit_cast.h"

namespace crashpad {
namespace test {
namespace {

using testing::AllOf;
using testing::DoAll;
using testing::Eq;
using testing::Invoke;
using testing::Pointee;
using testing::ResultOf;
using testing::Return;
using testing::SetArgPointee;
using testing::StrictMock;
using testing::WithArg;

//! \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 Google Test 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(kr, KERN_SUCCESS)
        << 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 Google Test
//!     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(kr, KERN_SUCCESS)
        << MachErrorMessage(kr, "mach_port_extract_right");
    return MACH_PORT_NULL;
  }

  EXPECT_EQ(acquired_type,
            implicit_cast<mach_msg_type_name_t>(MACH_MSG_TYPE_PORT_SEND_ONCE));

  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() Google Mock action.
//!
//! On failure, a Google Test failure will be added.
void MachPortDeallocate(mach_port_t port) {
  kern_return_t kr = mach_port_deallocate(mach_task_self(), port);
  EXPECT_EQ(kr, KERN_SUCCESS) << 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 Google Test 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(kr, KERN_SUCCESS) << 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
//! Google Mock 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 Google Test 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 Google Test 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(kr, KERN_SUCCESS) << 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 Google Mock 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 Google Test 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:
  NotifyServerTestBase(const NotifyServerTestBase&) = delete;
  NotifyServerTestBase& operator=(const NotifyServerTestBase&) = delete;

  // NotifyServer::Interface:

  MOCK_METHOD(kern_return_t,
              DoMachNotifyPortDeleted,
              (notify_port_t notify,
               mach_port_name_t name,
               const mach_msg_trailer_t* trailer),
              (override));

  MOCK_METHOD(kern_return_t,
              DoMachNotifyPortDestroyed,
              (notify_port_t notify,
               mach_port_t rights,
               const mach_msg_trailer_t* trailer,
               bool* destroy_request),
              (override));

  MOCK_METHOD(kern_return_t,
              DoMachNotifyNoSenders,
              (notify_port_t notify,
               mach_port_mscount_t mscount,
               const mach_msg_trailer_t* trailer),
              (override));

  MOCK_METHOD(kern_return_t,
              DoMachNotifySendOnce,
              (notify_port_t notify, const mach_msg_trailer_t* trailer),
              (override));

  MOCK_METHOD(kern_return_t,
              DoMachNotifyDeadName,
              (notify_port_t notify,
               mach_port_name_t name,
               const mach_msg_trailer_t* trailer),
              (override));

 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 Google Test 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(kr, KERN_SUCCESS)
          << MachErrorMessage(kr, "mach_port_request_notification");
      return false;
    }

    base::mac::ScopedMachSendRight previous_owner(previous);
    EXPECT_EQ(previous, kMachPortNull);

    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. Google Mock 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 Google Test assertion is added.
  void RunServer() {
    NotifyServer notify_server(this);
    mach_msg_return_t mr =
        MachMessageServer::Run(&notify_server,
                               ServerPort(),
                               kMachMessageReceiveAuditTrailer,
                               MachMessageServer::kPersistent,
                               MachMessageServer::kReceiveLargeError,
                               kMachMessageTimeoutNonblocking);
    ASSERT_EQ(mr, MACH_RCV_TIMED_OUT)
        << 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 Google Test failure added.
  mach_port_t ServerPort() {
    if (!server_port_.is_valid()) {
      server_port_.reset(NewMachPort(MACH_PORT_RIGHT_RECEIVE));
      EXPECT_TRUE(server_port_.is_valid());
    }

    return server_port_.get();
  }

  // testing::Test:
  void TearDown() override { server_port_.reset(); }

 private:
  base::mac::ScopedMachReceiveRight server_port_;
};

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(server.MachMessageServerRequestIDs(), expect_request_ids);

  // 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(server.MachMessageServerRequestSize(),
            offsetof(mach_port_destroyed_notification_t, trailer));

  mig_reply_error_t reply;
  EXPECT_EQ(server.MachMessageServerReplySize(), sizeof(reply));
}

// 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(
      NewMachPort(MACH_PORT_RIGHT_RECEIVE));
  ASSERT_TRUE(receive_right.is_valid());

  base::mac::ScopedMachSendRight send_once_right(
      SendOnceRightFromReceiveRight(receive_right.get()));
  ASSERT_TRUE(send_once_right.is_valid());

  ASSERT_TRUE(RequestMachPortNotification(
      send_once_right.get(), MACH_NOTIFY_DEAD_NAME, 0));

  EXPECT_CALL(
      *this,
      DoMachNotifyPortDeleted(ServerPort(),
                              send_once_right.get(),
                              ResultOf(AuditPIDFromMachMessageTrailer, 0)))
      .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(
      NewMachPort(MACH_PORT_RIGHT_RECEIVE));
  ASSERT_TRUE(receive_right.is_valid());

  ASSERT_TRUE(RequestMachPortNotification(
      receive_right.get(), MACH_NOTIFY_PORT_DESTROYED, 0));

  EXPECT_CALL(
      *this,
      DoMachNotifyPortDestroyed(ServerPort(),
                                ResultOf(IsReceiveRight, true),
                                ResultOf(AuditPIDFromMachMessageTrailer, 0),
                                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(
      NewMachPort(MACH_PORT_RIGHT_RECEIVE));
  ASSERT_TRUE(receive_right.is_valid());

  ASSERT_TRUE(RequestMachPortNotification(
      receive_right.get(), 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(
      NewMachPort(MACH_PORT_RIGHT_RECEIVE));
  ASSERT_TRUE(receive_right.is_valid());

  ASSERT_TRUE(RequestMachPortNotification(
      receive_right.get(), MACH_NOTIFY_NO_SENDERS, 0));

  EXPECT_CALL(*this,
              DoMachNotifyNoSenders(
                  ServerPort(), 0, ResultOf(AuditPIDFromMachMessageTrailer, 0)))
      .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(
      NewMachPort(MACH_PORT_RIGHT_RECEIVE));
  ASSERT_TRUE(receive_right.is_valid());

  base::mac::ScopedMachSendRight send_right(
      SendRightFromReceiveRight(receive_right.get()));
  ASSERT_TRUE(send_right.is_valid());

  ASSERT_TRUE(RequestMachPortNotification(
      receive_right.get(), MACH_NOTIFY_NO_SENDERS, 1));

  EXPECT_CALL(*this,
              DoMachNotifyNoSenders(
                  ServerPort(), 1, ResultOf(AuditPIDFromMachMessageTrailer, 0)))
      .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(
      NewMachPort(MACH_PORT_RIGHT_RECEIVE));
  ASSERT_TRUE(receive_right.is_valid());

  base::mac::ScopedMachSendRight send_right_0(
      SendRightFromReceiveRight(receive_right.get()));
  ASSERT_TRUE(send_right_0.is_valid());

  base::mac::ScopedMachSendRight send_right_1(
      SendRightFromReceiveRight(receive_right.get()));
  ASSERT_TRUE(send_right_1.is_valid());

  ASSERT_TRUE(RequestMachPortNotification(
      receive_right.get(), MACH_NOTIFY_NO_SENDERS, 1));

  send_right_1.reset();

  RunServer();

  EXPECT_EQ(RightRefCount(receive_right.get(), MACH_PORT_RIGHT_RECEIVE), 1u);
  EXPECT_EQ(RightRefCount(receive_right.get(), MACH_PORT_RIGHT_SEND), 1u);
}

// 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_TRUE(send_once_right.is_valid());

  EXPECT_CALL(*this,
              DoMachNotifySendOnce(ServerPort(),
                                   ResultOf(AuditPIDFromMachMessageTrailer, 0)))
      .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(
      NewMachPort(MACH_PORT_RIGHT_RECEIVE));
  ASSERT_TRUE(receive_right.is_valid());

  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.get();
  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(mr, MACH_MSG_SUCCESS) << MachErrorMessage(mr, "mach_msg");

  EXPECT_CALL(*this,
              DoMachNotifySendOnce(ServerPort(),
                                   ResultOf(AuditPIDFromMachMessageTrailer, 0)))
      .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(
      NewMachPort(MACH_PORT_RIGHT_RECEIVE));
  ASSERT_TRUE(receive_right.is_valid());

  base::mac::ScopedMachSendRight send_once_right(
      SendOnceRightFromReceiveRight(receive_right.get()));
  ASSERT_TRUE(send_once_right.is_valid());

  ASSERT_TRUE(RequestMachPortNotification(
      send_once_right.get(), 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)),
                                   ResultOf(AuditPIDFromMachMessageTrailer, 0)))
      .WillOnce(
          DoAll(WithArg<1>(Invoke(MachPortDeallocate)), Return(MIG_NO_REPLY)))
      .RetiresOnSaturation();

  receive_right.reset();

  RunServer();

  EXPECT_TRUE(IsRight(send_once_right.get(), MACH_PORT_TYPE_DEAD_NAME));

  EXPECT_EQ(RightRefCount(send_once_right.get(), MACH_PORT_RIGHT_SEND_ONCE),
            0u);
  EXPECT_EQ(DeadNameRightRefCount(send_once_right.get()), 1u);
}

// 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(
      NewMachPort(MACH_PORT_RIGHT_RECEIVE));
  ASSERT_TRUE(receive_right.is_valid());

  base::mac::ScopedMachSendRight send_once_right(
      SendOnceRightFromReceiveRight(receive_right.get()));
  ASSERT_TRUE(send_once_right.is_valid());

  ASSERT_TRUE(RequestMachPortNotification(
      send_once_right.get(), MACH_NOTIFY_DEAD_NAME, 0));

  RunServer();

  EXPECT_FALSE(IsRight(send_once_right.get(), MACH_PORT_TYPE_DEAD_NAME));

  EXPECT_EQ(RightRefCount(send_once_right.get(), MACH_PORT_RIGHT_SEND_ONCE),
            1u);
  EXPECT_EQ(DeadNameRightRefCount(send_once_right.get()), 0u);
}

}  // namespace
}  // namespace test
}  // namespace crashpad
