// Copyright 2014 The Crashpad Authors
//
// 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/mach_message_server.h"

#include <mach/mach.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>

#include <iterator>
#include <set>

#include "base/apple/scoped_mach_port.h"
#include "gtest/gtest.h"
#include "test/mac/mach_errors.h"
#include "test/mac/mach_multiprocess.h"
#include "util/file/file_io.h"
#include "util/mach/mach_extensions.h"
#include "util/mach/mach_message.h"
#include "util/misc/implicit_cast.h"

namespace crashpad {
namespace test {
namespace {

class TestMachMessageServer : public MachMessageServer::Interface,
                              public MachMultiprocess {
 public:
  struct Options {
    // The type of reply port that the client should put in its request message.
    enum ReplyPortType {
      // The normal reply port is the client’s local port, to which it holds
      // a receive right. This allows the server to respond directly to the
      // client. The client will expect a reply.
      kReplyPortNormal,

      // Use MACH_PORT_NULL as the reply port, which the server should detect
      // avoid attempting to send a message to, and return success. The client
      // will not expect a reply.
      kReplyPortNull,

      // Make the server see the reply port as a dead name by setting the reply
      // port to a receive right and then destroying that right before the
      // server processes the request. The server should return
      // MACH_SEND_INVALID_DEST, and the client will not expect a reply.
      kReplyPortDead,
    };

    Options()
        : expect_server_interface_method_called(true),
          parent_wait_for_child_pipe(false),
          server_options(MACH_MSG_OPTION_NONE),
          server_persistent(MachMessageServer::kOneShot),
          server_receive_large(MachMessageServer::kReceiveLargeError),
          server_timeout_ms(kMachMessageTimeoutWaitIndefinitely),
          server_mig_retcode(KERN_SUCCESS),
          server_destroy_complex(true),
          expect_server_destroyed_complex(true),
          expect_server_result(KERN_SUCCESS),
          expect_server_transaction_count(1),
          child_wait_for_parent_pipe_early(false),
          client_send_request_count(1),
          client_send_complex(false),
          client_send_large(false),
          client_reply_port_type(kReplyPortNormal),
          client_expect_reply(true),
          child_send_all_requests_before_receiving_any_replies(false),
          child_wait_for_parent_pipe_late(false) {
    }

    // true if MachMessageServerFunction() is expected to be called.
    bool expect_server_interface_method_called;

    // true if the parent should wait for the child to write a byte to the pipe
    // as a signal that the child is ready for the parent to begin its side of
    // the test. This is used for nonblocking tests, which require that there
    // be something in the server’s queue before attempting a nonblocking
    // receive if the receive is to be successful.
    bool parent_wait_for_child_pipe;

    // Options to pass to MachMessageServer::Run() as the |options| parameter.
    mach_msg_options_t server_options;

    // Whether the server should run in one-shot or persistent mode.
    MachMessageServer::Persistent server_persistent;

    // The strategy for handling large messages.
    MachMessageServer::ReceiveLarge server_receive_large;

    // The server’s timeout in milliseconds, or kMachMessageTimeoutNonblocking
    // or kMachMessageTimeoutWaitIndefinitely.
    mach_msg_timeout_t server_timeout_ms;

    // The return code that the server returns to the client via the
    // mig_reply_error_t::RetCode field. A client would normally see this as
    // a Mach RPC return value.
    kern_return_t server_mig_retcode;

    // The value that the server function should set its destroy_complex_request
    // parameter to. This is true if resources sent in complex request messages
    // should be destroyed, and false if they should not be destroyed, assuming
    // that the server function indicates success.
    bool server_destroy_complex;

    // Whether to expect the server to destroy a complex message. Even if
    // server_destroy_complex is false, a complex message will be destroyed if
    // the MIG return code was unsuccessful.
    bool expect_server_destroyed_complex;

    // The expected return value from MachMessageServer::Run().
    kern_return_t expect_server_result;

    // The number of transactions that the server is expected to handle.
    size_t expect_server_transaction_count;

    // true if the child should wait for the parent to signal that it’s ready
    // for the child to begin sending requests via the pipe. This is done if the
    // parent needs to perform operations on its receive port before the child
    // should be permitted to send anything to it. Currently, this is used to
    // allow the parent to ensure that the receive port’s queue length is high
    // enough before the child begins attempting to fill it.
    bool child_wait_for_parent_pipe_early;

    // The number of requests that the client should send to the server.
    size_t client_send_request_count;

    // true if the client should send a complex message, one that carries a port
    // descriptor in its body. Normally false.
    bool client_send_complex;

    // true if the client should send a larger message than the server has
    // allocated space to receive. The server’s response is directed by
    // server_receive_large.
    bool client_send_large;

    // The type of reply port that the client should provide in its request’s
    // mach_msg_header_t::msgh_local_port, which will appear to the server as
    // mach_msg_header_t::msgh_remote_port.
    ReplyPortType client_reply_port_type;

    // true if the client should wait for a reply from the server. For
    // non-normal reply ports or requests which the server responds to with no
    // reply (MIG_NO_REPLY), the server will either not send a reply or not
    // succeed in sending a reply, and the child process should not wait for
    // one.
    bool client_expect_reply;

    // true if the client should send all requests before attempting to receive
    // any replies from the server. This is used for the persistent nonblocking
    // test, which requires the client to fill the server’s queue before the
    // server can attempt processing it.
    bool child_send_all_requests_before_receiving_any_replies;

    // true if the child should wait to receive a byte from the parent before
    // exiting. This can be used to keep a receive right in the child alive
    // until the parent has a chance to verify that it’s holding a send right.
    // Otherwise, the right might appear in the parent as a dead name if the
    // child exited before the parent had a chance to examine it. This would be
    // a race.
    bool child_wait_for_parent_pipe_late;
  };

  explicit TestMachMessageServer(const Options& options)
      : MachMessageServer::Interface(),
        MachMultiprocess(),
        options_(options),
        child_complex_message_port_(),
        parent_complex_message_port_(MACH_PORT_NULL) {
  }

  TestMachMessageServer(const TestMachMessageServer&) = delete;
  TestMachMessageServer& operator=(const TestMachMessageServer&) = delete;

  // Runs the test.
  void Test() {
    EXPECT_EQ(replies_, requests_);
    uint32_t start = requests_;

    Run();

    EXPECT_EQ(replies_, requests_);
    EXPECT_EQ(requests_ - start, options_.expect_server_transaction_count);
  }

  // MachMessageServerInterface:

  virtual bool MachMessageServerFunction(
      const mach_msg_header_t* in,
      mach_msg_header_t* out,
      bool* destroy_complex_request) override {
    *destroy_complex_request = options_.server_destroy_complex;

    EXPECT_TRUE(options_.expect_server_interface_method_called);
    if (!options_.expect_server_interface_method_called) {
      return false;
    }

    struct ReceiveRequestMessage : public RequestMessage {
      mach_msg_trailer_t trailer;
    };

    struct ReceiveLargeRequestMessage : public LargeRequestMessage {
      mach_msg_trailer_t trailer;
    };

    const ReceiveRequestMessage* request =
        reinterpret_cast<const ReceiveRequestMessage*>(in);
    const mach_msg_bits_t expect_msgh_bits =
        MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND, MACH_MSG_TYPE_MOVE_SEND) |
        (options_.client_send_complex ? MACH_MSGH_BITS_COMPLEX : 0);
    EXPECT_EQ(request->header.msgh_bits, expect_msgh_bits);
    EXPECT_EQ(request->header.msgh_size,
              options_.client_send_large ? sizeof(LargeRequestMessage)
                                         : sizeof(RequestMessage));
    if (options_.client_reply_port_type == Options::kReplyPortNormal) {
      EXPECT_EQ(request->header.msgh_remote_port, RemotePort());
    }
    EXPECT_EQ(request->header.msgh_local_port, LocalPort());
    EXPECT_EQ(request->header.msgh_id, kRequestMessageID);
    if (options_.client_send_complex) {
      EXPECT_EQ(request->body.msgh_descriptor_count, 1u);
      EXPECT_NE(request->port_descriptor.name, kMachPortNull);
      parent_complex_message_port_ = request->port_descriptor.name;
      EXPECT_EQ(request->port_descriptor.disposition,
                implicit_cast<mach_msg_type_name_t>(MACH_MSG_TYPE_MOVE_SEND));
      EXPECT_EQ(
          request->port_descriptor.type,
          implicit_cast<mach_msg_descriptor_type_t>(MACH_MSG_PORT_DESCRIPTOR));
    } else {
      EXPECT_EQ(request->body.msgh_descriptor_count, 0u);
      EXPECT_EQ(request->port_descriptor.name, kMachPortNull);
      EXPECT_EQ(request->port_descriptor.disposition, 0u);
      EXPECT_EQ(request->port_descriptor.type, 0u);
    }
    EXPECT_EQ(memcmp(&request->ndr, &NDR_record, sizeof(NDR_record)), 0);
    EXPECT_EQ(request->number, requests_);

    // Look for the trailer in the right spot, depending on whether the request
    // message was a RequestMessage or a LargeRequestMessage.
    const mach_msg_trailer_t* trailer;
    if (options_.client_send_large) {
      const ReceiveLargeRequestMessage* large_request =
          reinterpret_cast<const ReceiveLargeRequestMessage*>(request);
      for (size_t index = 0; index < sizeof(large_request->data); ++index) {
        EXPECT_EQ(large_request->data[index], '!');
      }
      trailer = &large_request->trailer;
    } else {
      trailer = &request->trailer;
    }

    EXPECT_EQ(
        trailer->msgh_trailer_type,
        implicit_cast<mach_msg_trailer_type_t>(MACH_MSG_TRAILER_FORMAT_0));
    EXPECT_EQ(trailer->msgh_trailer_size, MACH_MSG_TRAILER_MINIMUM_SIZE);

    ++requests_;

    ReplyMessage* reply = reinterpret_cast<ReplyMessage*>(out);
    reply->Head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
    reply->Head.msgh_size = sizeof(*reply);
    reply->Head.msgh_remote_port = request->header.msgh_remote_port;
    reply->Head.msgh_local_port = MACH_PORT_NULL;
    reply->Head.msgh_id = kReplyMessageID;
    reply->NDR = NDR_record;
    reply->RetCode = options_.server_mig_retcode;
    reply->number = replies_++;

    return true;
  }

  std::set<mach_msg_id_t> MachMessageServerRequestIDs() override {
    static constexpr mach_msg_id_t request_ids[] = {kRequestMessageID};
    return std::set<mach_msg_id_t>(&request_ids[0],
                                   &request_ids[std::size(request_ids)]);
  }

  mach_msg_size_t MachMessageServerRequestSize() override {
    return sizeof(RequestMessage);
  }

  mach_msg_size_t MachMessageServerReplySize() override {
    return sizeof(ReplyMessage);
  }

 private:
  struct RequestMessage : public mach_msg_base_t {
    // If body.msgh_descriptor_count is 0, port_descriptor will still be
    // present, but it will be zeroed out. It wouldn’t normally be present in a
    // message froma MIG-generated interface, but it’s harmless and simpler to
    // leave it here and just treat it as more data.
    mach_msg_port_descriptor_t port_descriptor;

    NDR_record_t ndr;
    uint32_t number;
  };

  // LargeRequestMessage is larger enough than a regular RequestMessage to
  // ensure that whatever buffer was allocated to receive a RequestMessage is
  // not large enough to receive a LargeRequestMessage.
  struct LargeRequestMessage : public RequestMessage {
    uint8_t data[4 * PAGE_MAX_SIZE];
  };

  struct ReplyMessage : public mig_reply_error_t {
    uint32_t number;
  };

  // MachMultiprocess:

  void MachMultiprocessParent() override {
    mach_port_t local_port = LocalPort();

    kern_return_t kr;
    if (options_.child_send_all_requests_before_receiving_any_replies) {
      // On OS X 10.10, the queue limit of a new Mach port seems to be 2 by
      // default, which is below the value of MACH_PORT_QLIMIT_DEFAULT. Set the
      // port’s queue limit explicitly here.
      mach_port_limits limits = {};
      limits.mpl_qlimit = MACH_PORT_QLIMIT_DEFAULT;
      kr = mach_port_set_attributes(mach_task_self(),
                                    local_port,
                                    MACH_PORT_LIMITS_INFO,
                                    reinterpret_cast<mach_port_info_t>(&limits),
                                    MACH_PORT_LIMITS_INFO_COUNT);
      ASSERT_EQ(kr, KERN_SUCCESS)
          << MachErrorMessage(kr, "mach_port_set_attributes");
    }

    if (options_.child_wait_for_parent_pipe_early) {
      // Tell the child to begin sending messages.
      char c = '\0';
      CheckedWriteFile(WritePipeHandle(), &c, 1);
    }

    if (options_.parent_wait_for_child_pipe) {
      // Wait until the child is done sending what it’s going to send.
      char c;
      CheckedReadFileExactly(ReadPipeHandle(), &c, 1);
      EXPECT_EQ(c, '\0');
    }

    ASSERT_EQ((kr = MachMessageServer::Run(this,
                                           local_port,
                                           options_.server_options,
                                           options_.server_persistent,
                                           options_.server_receive_large,
                                           options_.server_timeout_ms)),
              options_.expect_server_result)
        << MachErrorMessage(kr, "MachMessageServer");

    if (options_.client_send_complex) {
      EXPECT_NE(parent_complex_message_port_, kMachPortNull);
      mach_port_type_t type;

      if (!options_.expect_server_destroyed_complex) {
        // MachMessageServer should not have destroyed the resources sent in the
        // complex request message.
        kr = mach_port_type(
            mach_task_self(), parent_complex_message_port_, &type);
        EXPECT_EQ(kr, KERN_SUCCESS) << MachErrorMessage(kr, "mach_port_type");
        EXPECT_EQ(type, MACH_PORT_TYPE_SEND);

        // Destroy the resources here.
        kr = mach_port_deallocate(mach_task_self(),
                                  parent_complex_message_port_);
        EXPECT_EQ(kr, KERN_SUCCESS)
            << MachErrorMessage(kr, "mach_port_deallocate");
      }

      // The kernel won’t have reused the same name for another Mach port in
      // this task so soon. It’s possible that something else in this task could
      // have reused the name, but it’s unlikely for that to have happened in
      // this test environment.
      kr =
          mach_port_type(mach_task_self(), parent_complex_message_port_, &type);
      EXPECT_EQ(kr, KERN_INVALID_NAME)
          << MachErrorMessage(kr, "mach_port_type");
    }

    if (options_.child_wait_for_parent_pipe_late) {
      // Let the child know it’s safe to exit.
      char c = '\0';
      CheckedWriteFile(WritePipeHandle(), &c, 1);
    }
  }

  void MachMultiprocessChild() override {
    if (options_.child_wait_for_parent_pipe_early) {
      // Wait until the parent is done setting things up on its end.
      char c;
      CheckedReadFileExactly(ReadPipeHandle(), &c, 1);
      EXPECT_EQ(c, '\0');
    }

    for (size_t index = 0;
         index < options_.client_send_request_count;
         ++index) {
      if (options_.child_send_all_requests_before_receiving_any_replies) {
        // For this test, all of the messages need to go into the queue before
        // the parent is allowed to start processing them. Don’t attempt to
        // process replies before all of the requests are sent, because the
        // server won’t have sent any replies until all of the requests are in
        // its queue.
        ASSERT_NO_FATAL_FAILURE(ChildSendRequest());
      } else {
        ASSERT_NO_FATAL_FAILURE(ChildSendRequestAndWaitForReply());
      }
    }

    if (options_.parent_wait_for_child_pipe &&
        options_.child_send_all_requests_before_receiving_any_replies) {
      // Now that all of the requests have been sent, let the parent know that
      // it’s safe to begin processing them, and then wait for the replies.
      ASSERT_NO_FATAL_FAILURE(ChildNotifyParentViaPipe());

      for (size_t index = 0;
           index < options_.client_send_request_count;
           ++index) {
        ASSERT_NO_FATAL_FAILURE(ChildWaitForReply());
      }
    }

    if (options_.child_wait_for_parent_pipe_late) {
      char c;
      CheckedReadFileExactly(ReadPipeHandle(), &c, 1);
      ASSERT_EQ(c, '\0');
    }
  }

  // In the child process, sends a request message to the server.
  void ChildSendRequest() {
    // local_receive_port_owner will the receive right that is created in this
    // scope and intended to be destroyed when leaving this scope, after it has
    // been carried in a Mach message.
    base::apple::ScopedMachReceiveRight local_receive_port_owner;

    // A LargeRequestMessage is always allocated, but the message that will be
    // sent will be a normal RequestMessage due to the msgh_size field
    // indicating the size of the smaller base structure unless
    // options_.client_send_large is true.
    LargeRequestMessage request = {};

    request.header.msgh_bits =
        MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND) |
        (options_.client_send_complex ? MACH_MSGH_BITS_COMPLEX : 0);
    request.header.msgh_size = options_.client_send_large ?
        sizeof(LargeRequestMessage) : sizeof(RequestMessage);
    request.header.msgh_remote_port = RemotePort();
    kern_return_t kr;
    switch (options_.client_reply_port_type) {
      case Options::kReplyPortNormal:
        request.header.msgh_local_port = LocalPort();
        break;
      case Options::kReplyPortNull:
        request.header.msgh_local_port = MACH_PORT_NULL;
        break;
      case Options::kReplyPortDead: {
        // Use a newly-allocated receive right that will be destroyed when this
        // method returns. A send right will be made from this receive right and
        // carried in the request message to the server. By the time the server
        // looks at the right, it will have become a dead name.
        local_receive_port_owner.reset(NewMachPort(MACH_PORT_RIGHT_RECEIVE));
        ASSERT_TRUE(local_receive_port_owner.is_valid());
        request.header.msgh_local_port = local_receive_port_owner.get();
        break;
      }
    }
    request.header.msgh_id = kRequestMessageID;
    if (options_.client_send_complex) {
      // Allocate a new receive right in this process and make a send right that
      // will appear in the parent process. This is used to test that the server
      // properly handles ownership of resources received in complex messages.
      request.body.msgh_descriptor_count = 1;
      child_complex_message_port_.reset(NewMachPort(MACH_PORT_RIGHT_RECEIVE));
      ASSERT_TRUE(child_complex_message_port_.is_valid());
      request.port_descriptor.name = child_complex_message_port_.get();
      request.port_descriptor.disposition = MACH_MSG_TYPE_MAKE_SEND;
      request.port_descriptor.type = MACH_MSG_PORT_DESCRIPTOR;
    } else {
      request.body.msgh_descriptor_count = 0;
      request.port_descriptor.name = MACH_PORT_NULL;
      request.port_descriptor.disposition = 0;
      request.port_descriptor.type = 0;
    }
    request.ndr = NDR_record;
    request.number = requests_++;

    if (options_.client_send_large) {
      memset(request.data, '!', sizeof(request.data));
    }

    kr = mach_msg(&request.header,
                  MACH_SEND_MSG | MACH_SEND_TIMEOUT,
                  request.header.msgh_size,
                  0,
                  MACH_PORT_NULL,
                  MACH_MSG_TIMEOUT_NONE,
                  MACH_PORT_NULL);
    ASSERT_EQ(kr, MACH_MSG_SUCCESS) << MachErrorMessage(kr, "mach_msg");
  }

  // In the child process, waits for a reply message from the server.
  void ChildWaitForReply() {
    if (!options_.client_expect_reply) {
      // The client shouldn’t expect a reply when it didn’t send a good reply
      // port with its request, or when testing the server behaving in a way
      // that doesn’t send replies.
      return;
    }

    struct ReceiveReplyMessage : public ReplyMessage {
      mach_msg_trailer_t trailer;
    };

    ReceiveReplyMessage reply = {};
    kern_return_t kr = mach_msg(&reply.Head,
                                MACH_RCV_MSG,
                                0,
                                sizeof(reply),
                                LocalPort(),
                                MACH_MSG_TIMEOUT_NONE,
                                MACH_PORT_NULL);
    ASSERT_EQ(kr, MACH_MSG_SUCCESS) << MachErrorMessage(kr, "mach_msg");

    ASSERT_EQ(reply.Head.msgh_bits,
              implicit_cast<mach_msg_bits_t>(
                  MACH_MSGH_BITS(0, MACH_MSG_TYPE_MOVE_SEND)));
    ASSERT_EQ(reply.Head.msgh_size, sizeof(ReplyMessage));
    ASSERT_EQ(reply.Head.msgh_remote_port, kMachPortNull);
    ASSERT_EQ(reply.Head.msgh_local_port, LocalPort());
    ASSERT_EQ(reply.Head.msgh_id, kReplyMessageID);
    ASSERT_EQ(memcmp(&reply.NDR, &NDR_record, sizeof(NDR_record)), 0);
    ASSERT_EQ(reply.RetCode, options_.server_mig_retcode);
    ASSERT_EQ(reply.number, replies_);
    ASSERT_EQ(
        reply.trailer.msgh_trailer_type,
        implicit_cast<mach_msg_trailer_type_t>(MACH_MSG_TRAILER_FORMAT_0));
    ASSERT_EQ(reply.trailer.msgh_trailer_size, MACH_MSG_TRAILER_MINIMUM_SIZE);

    ++replies_;
  }

  // For test types where the child needs to notify the server in the parent
  // that the child is ready, this method will send a byte via the POSIX pipe.
  // The parent will be waiting in a read() on this pipe, and will proceed to
  // running MachMessageServer() once it’s received.
  void ChildNotifyParentViaPipe() {
    char c = '\0';
    CheckedWriteFile(WritePipeHandle(), &c, 1);
  }

  // In the child process, sends a request message to the server and then
  // receives a reply message.
  void ChildSendRequestAndWaitForReply() {
    ASSERT_NO_FATAL_FAILURE(ChildSendRequest());

    if (options_.parent_wait_for_child_pipe &&
        !options_.child_send_all_requests_before_receiving_any_replies) {
      // The parent is waiting to read a byte to indicate that the message has
      // been placed in the queue.
      ASSERT_NO_FATAL_FAILURE(ChildNotifyParentViaPipe());
    }

    ASSERT_NO_FATAL_FAILURE(ChildWaitForReply());
  }

  const Options& options_;

  // A receive right allocated in the child process. A send right will be
  // created from this right and sent to the parent parent process in the
  // request message.
  base::apple::ScopedMachReceiveRight child_complex_message_port_;

  // The send right received in the parent process. This right is stored in a
  // member variable to test that resources carried in complex messages are
  // properly destroyed in the server when expected.
  mach_port_t parent_complex_message_port_;

  static uint32_t requests_;
  static uint32_t replies_;

  static constexpr mach_msg_id_t kRequestMessageID = 16237;
  static constexpr mach_msg_id_t kReplyMessageID = kRequestMessageID + 100;
};

uint32_t TestMachMessageServer::requests_;
uint32_t TestMachMessageServer::replies_;
constexpr mach_msg_id_t TestMachMessageServer::kRequestMessageID;
constexpr mach_msg_id_t TestMachMessageServer::kReplyMessageID;

TEST(MachMessageServer, Basic) {
  // The client sends one message to the server, which will wait indefinitely in
  // blocking mode for it.
  TestMachMessageServer::Options options;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, NonblockingNoMessage) {
  // The server waits in nonblocking mode and the client sends nothing, so the
  // server should return immediately without processing any message.
  TestMachMessageServer::Options options;
  options.expect_server_interface_method_called = false;
  options.server_timeout_ms = kMachMessageTimeoutNonblocking;
  options.expect_server_result = MACH_RCV_TIMED_OUT;
  options.expect_server_transaction_count = 0;
  options.client_send_request_count = 0;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, TimeoutNoMessage) {
  // The server waits in blocking mode for one message, but with a timeout. The
  // client sends no message, so the server returns after the timeout.
  TestMachMessageServer::Options options;
  options.expect_server_interface_method_called = false;
  options.server_timeout_ms = 10;
  options.expect_server_result = MACH_RCV_TIMED_OUT;
  options.expect_server_transaction_count = 0;
  options.client_send_request_count = 0;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, Nonblocking) {
  // The client sends one message to the server and then signals the server that
  // it’s safe to start waiting for it in nonblocking mode. The message is in
  // the server’s queue, so it’s able to receive it when it begins listening in
  // nonblocking mode.
  TestMachMessageServer::Options options;
  options.parent_wait_for_child_pipe = true;
  options.server_timeout_ms = kMachMessageTimeoutNonblocking;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, Timeout) {
  // The client sends one message to the server, which will wait in blocking
  // mode for it up to a specific timeout.
  TestMachMessageServer::Options options;
  options.server_timeout_ms = 10;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, PersistentTenMessages) {
  // The server waits for as many messages as it can receive in blocking mode
  // with a timeout. The client sends several messages, and the server processes
  // them all.
  TestMachMessageServer::Options options;
  options.server_persistent = MachMessageServer::kPersistent;
  options.server_timeout_ms = 10;
  options.expect_server_result = MACH_RCV_TIMED_OUT;
  options.expect_server_transaction_count = 10;
  options.client_send_request_count = 10;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, PersistentNonblockingFourMessages) {
  // The client sends several messages to the server and then signals the server
  // that it’s safe to start waiting for them in nonblocking mode. The server
  // then listens for them in nonblocking persistent mode, and receives all of
  // them because they’ve been queued up. The client doesn’t wait for the
  // replies until after it’s put all of its requests into the server’s queue.
  //
  // This test is sensitive to the length of the IPC queue limit. Mach ports
  // normally have a queue length limit of MACH_PORT_QLIMIT_DEFAULT (which is
  // MACH_PORT_QLIMIT_BASIC, or 5). The number of messages sent for this test
  // must be below this, because the server does not begin dequeueing request
  // messages until the client has finished sending them.
  //
  // The queue limit on new ports has been seen to be below
  // MACH_PORT_QLIMIT_DEFAULT, so it will explicitly be set by
  // mach_port_set_attributes() for this test. This needs to happen before the
  // child is allowed to begin sending messages, so
  // child_wait_for_parent_pipe_early is used to make the child wait until the
  // parent is ready.
  constexpr size_t kTransactionCount = 4;
  static_assert(kTransactionCount <= MACH_PORT_QLIMIT_DEFAULT,
                "must not exceed queue limit");

  TestMachMessageServer::Options options;
  options.parent_wait_for_child_pipe = true;
  options.server_persistent = MachMessageServer::kPersistent;
  options.server_timeout_ms = kMachMessageTimeoutNonblocking;
  options.expect_server_result = MACH_RCV_TIMED_OUT;
  options.expect_server_transaction_count = kTransactionCount;
  options.child_wait_for_parent_pipe_early = true;
  options.client_send_request_count = kTransactionCount;
  options.child_send_all_requests_before_receiving_any_replies = true;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, ReturnCodeInvalidArgument) {
  // This tests that the mig_reply_error_t::RetCode field is properly returned
  // to the client.
  TestMachMessageServer::Options options;
  options.server_mig_retcode = KERN_INVALID_ARGUMENT;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, ReturnCodeNoReply) {
  // This tests that when mig_reply_error_t::RetCode is set to MIG_NO_REPLY, no
  // response is sent to the client.
  TestMachMessageServer::Options options;
  options.server_mig_retcode = MIG_NO_REPLY;
  options.client_expect_reply = false;
  options.child_wait_for_parent_pipe_late = true;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, ReplyPortNull) {
  // The client sets its reply port to MACH_PORT_NULL. The server should see
  // this and avoid sending a message to the null port. No reply message is
  // sent and the server returns success.
  TestMachMessageServer::Options options;
  options.client_reply_port_type =
      TestMachMessageServer::Options::kReplyPortNull;
  options.client_expect_reply = false;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, ReplyPortDead) {
  // The client allocates a new port and uses it as the reply port in its
  // request message, and then deallocates its receive right to that port. It
  // then signals the server to process the request message. The server’s view
  // of the port is that it is a dead name. The server function will return
  // MACH_SEND_INVALID_DEST because it’s not possible to send a message to a
  // dead name.
  TestMachMessageServer::Options options;
  options.parent_wait_for_child_pipe = true;
  options.expect_server_result = MACH_SEND_INVALID_DEST;
  options.client_reply_port_type =
      TestMachMessageServer::Options::kReplyPortDead;
  options.client_expect_reply = false;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, Complex) {
  // The client allocates a new receive right and sends a complex request
  // message to the server with a send right made out of this receive right. The
  // server receives this message and is instructed to destroy the send right
  // when it is done handling the request-reply transaction. The former send
  // right is verified to be invalid after the server runs. This test ensures
  // that resources transferred to a server process temporarily aren’t leaked.
  TestMachMessageServer::Options options;
  options.client_send_complex = true;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, ComplexNotDestroyed) {
  // As in MachMessageServer.Complex, but the server is instructed not to
  // destroy the send right. After the server runs, the send right is verified
  // to continue to exist in the server task. The client process is then
  // signalled by pipe that it’s safe to exit so that the send right in the
  // server task doesn’t prematurely become a dead name. This test ensures that
  // rights that are expected to be retained in the server task are properly
  // retained.
  TestMachMessageServer::Options options;
  options.server_destroy_complex = false;
  options.expect_server_destroyed_complex = false;
  options.client_send_complex = true;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, ComplexDestroyedInvalidArgument) {
  // As in MachMessageServer.ComplexNotDestroyed, but the server does not return
  // a successful code via MIG. The server is expected to destroy resources in
  // this case, because server_destroy_complex = false is only honored when a
  // MIG request is handled successfully or with no reply.
  TestMachMessageServer::Options options;
  options.server_mig_retcode = KERN_INVALID_TASK;
  options.server_destroy_complex = false;
  options.client_send_complex = true;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, ComplexNotDestroyedNoReply) {
  // As in MachMessageServer.ComplexNotDestroyed, but the server does not send
  // a reply message and is expected to retain the send right in the server
  // task.
  TestMachMessageServer::Options options;
  options.server_mig_retcode = MIG_NO_REPLY;
  options.server_destroy_complex = false;
  options.expect_server_destroyed_complex = false;
  options.client_send_complex = true;
  options.client_expect_reply = false;
  options.child_wait_for_parent_pipe_late = true;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, ReceiveLargeError) {
  // The client sends a request to the server that is larger than the server is
  // expecting. server_receive_large is kReceiveLargeError, so the request is
  // destroyed and the server returns a MACH_RCV_TOO_LARGE error. The client
  // does not receive a reply.
  TestMachMessageServer::Options options;
  options.expect_server_result = MACH_RCV_TOO_LARGE;
  options.expect_server_transaction_count = 0;
  options.client_send_large = true;
  options.client_expect_reply = false;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, ReceiveLargeRetry) {
  // The client sends a request to the server that is larger than the server is
  // initially expecting. server_receive_large is kReceiveLargeResize, so a new
  // buffer is allocated to receive the message. The server receives the large
  // request message, processes it, and returns a reply to the client.
  TestMachMessageServer::Options options;
  options.server_receive_large = MachMessageServer::kReceiveLargeResize;
  options.client_send_large = true;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

TEST(MachMessageServer, ReceiveLargeIgnore) {
  // The client sends a request to the server that is larger than the server is
  // expecting. server_receive_large is kReceiveLargeIgnore, so the request is
  // destroyed but the server does not consider this an error. The server is
  // running in blocking mode with a timeout, and continues to wait for a
  // message until it times out. The client does not receive a reply.
  TestMachMessageServer::Options options;
  options.server_receive_large = MachMessageServer::kReceiveLargeIgnore;
  options.server_timeout_ms = 10;
  options.expect_server_result = MACH_RCV_TIMED_OUT;
  options.expect_server_transaction_count = 0;
  options.client_send_large = true;
  options.client_expect_reply = false;
  TestMachMessageServer test_mach_message_server(options);
  test_mach_message_server.Test();
}

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