// 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/mach_message_server.h"

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

#include <set>

#include "base/mac/scoped_mach_port.h"
#include "base/macros.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) {
  }

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

    Run();

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

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

    // 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(implicit_cast<mach_msg_trailer_type_t>(MACH_MSG_TRAILER_FORMAT_0),
              trailer->msgh_trailer_type);
    EXPECT_EQ(MACH_MSG_TRAILER_MINIMUM_SIZE, trailer->msgh_trailer_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 {
    const mach_msg_id_t request_ids[] = {kRequestMessageID};
    return std::set<mach_msg_id_t>(&request_ids[0],
                                   &request_ids[arraysize(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_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(KERN_SUCCESS, kr)
          << 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;
      CheckedReadFile(ReadPipeHandle(), &c, 1);
      EXPECT_EQ('\0', c);
    }

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

    if (options_.client_send_complex) {
      EXPECT_NE(kMachPortNull, parent_complex_message_port_);
      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(KERN_SUCCESS, kr) << MachErrorMessage(kr, "mach_port_type");
        EXPECT_EQ(MACH_PORT_TYPE_SEND, type);

        // Destroy the resources here.
        kr = mach_port_deallocate(mach_task_self(),
                                  parent_complex_message_port_);
        EXPECT_EQ(KERN_SUCCESS, kr)
            << 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(KERN_INVALID_NAME, kr)
          << 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;
      CheckedReadFile(ReadPipeHandle(), &c, 1);
      EXPECT_EQ('\0', c);
    }

    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;
      CheckedReadFile(ReadPipeHandle(), &c, 1);
      ASSERT_EQ('\0', c);
    }
  }

  // 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::mac::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(MACH_MSG_SUCCESS, kr) << 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(MACH_MSG_SUCCESS, kr) << MachErrorMessage(kr, "mach_msg");

    ASSERT_EQ(implicit_cast<mach_msg_bits_t>(
        MACH_MSGH_BITS(0, MACH_MSG_TYPE_MOVE_SEND)), reply.Head.msgh_bits);
    ASSERT_EQ(sizeof(ReplyMessage), reply.Head.msgh_size);
    ASSERT_EQ(kMachPortNull, reply.Head.msgh_remote_port);
    ASSERT_EQ(LocalPort(), reply.Head.msgh_local_port);
    ASSERT_EQ(kReplyMessageID, reply.Head.msgh_id);
    ASSERT_EQ(0, memcmp(&reply.NDR, &NDR_record, sizeof(NDR_record)));
    ASSERT_EQ(options_.server_mig_retcode, reply.RetCode);
    ASSERT_EQ(replies_, reply.number);
    ASSERT_EQ(implicit_cast<mach_msg_trailer_type_t>(MACH_MSG_TRAILER_FORMAT_0),
              reply.trailer.msgh_trailer_type);
    ASSERT_EQ(MACH_MSG_TRAILER_MINIMUM_SIZE, reply.trailer.msgh_trailer_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::mac::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 const mach_msg_id_t kRequestMessageID = 16237;
  static const mach_msg_id_t kReplyMessageID = kRequestMessageID + 100;

  DISALLOW_COPY_AND_ASSIGN(TestMachMessageServer);
};

uint32_t TestMachMessageServer::requests_;
uint32_t TestMachMessageServer::replies_;
const mach_msg_id_t TestMachMessageServer::kRequestMessageID;
const 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.
  const 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
