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

#include <mach/mach.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>

#include "base/check.h"
#include "base/mac/mach_logging.h"
#include "base/mac/scoped_mach_port.h"
#include "base/notreached.h"
#include "build/build_config.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/exc_server_variants.h"
#include "util/mach/exception_types.h"
#include "util/mach/mach_extensions.h"
#include "util/mach/mach_message.h"
#include "util/mach/mach_message_server.h"
#include "util/misc/scoped_forbid_return.h"
#include "util/synchronization/semaphore.h"

namespace crashpad {
namespace test {
namespace {

// Calls GetExceptionPorts() on its |exception_ports| argument to look up the
// EXC_MASK_CRASH handler. If |expect_port| is not MACH_PORT_NULL, it expects to
// find a handler for this mask whose port matches |expect_port| and whose
// behavior matches |expect_behavior| exactly. In this case, if
// |expect_behavior| is a state-carrying behavior, the looked-up thread state
// flavor is expected to be MACHINE_THREAD_STATE, otherwise, it is expected to
// be THREAD_STATE_NONE. If |expect_port| is MACH_PORT_NULL, no handler for
// EXC_MASK_CRASH is expected to be found.
//
// A second GetExceptionPorts() lookup is also performed on a wider exception
// mask, EXC_MASK_ALL | EXC_MASK_CRASH. The EXC_MASK_CRASH handler’s existence
// and properties from this second lookup are validated in the same way.
//
// This function uses Google Test EXPECT_* and ASSERT_* macros to perform its
// validation.
void TestGetExceptionPorts(const ExceptionPorts& exception_ports,
                           mach_port_t expect_port,
                           exception_behavior_t expect_behavior) {
  constexpr exception_mask_t kExceptionMask = EXC_MASK_CRASH;

  thread_state_flavor_t expect_flavor = (expect_behavior == EXCEPTION_DEFAULT)
                                            ? THREAD_STATE_NONE
                                            : MACHINE_THREAD_STATE;

  ExceptionPorts::ExceptionHandlerVector crash_handler;
  ASSERT_TRUE(
      exception_ports.GetExceptionPorts(kExceptionMask, &crash_handler));

  if (expect_port != MACH_PORT_NULL) {
    ASSERT_EQ(crash_handler.size(), 1u);

    EXPECT_EQ(crash_handler[0].mask, kExceptionMask);
    EXPECT_EQ(crash_handler[0].port, expect_port);
    EXPECT_EQ(crash_handler[0].behavior, expect_behavior);
    EXPECT_EQ(crash_handler[0].flavor, expect_flavor);
  } else {
    EXPECT_TRUE(crash_handler.empty());
  }

  ExceptionPorts::ExceptionHandlerVector handlers;
  ASSERT_TRUE(exception_ports.GetExceptionPorts(ExcMaskValid(), &handlers));

  EXPECT_GE(handlers.size(), crash_handler.size());
  bool found = false;
  for (const ExceptionPorts::ExceptionHandler& handler : handlers) {
    if ((handler.mask & kExceptionMask) != 0) {
      EXPECT_FALSE(found);
      found = true;
      EXPECT_EQ(handler.port, expect_port);
      EXPECT_EQ(handler.behavior, expect_behavior);
      EXPECT_EQ(handler.flavor, expect_flavor);
    }
  }

  if (expect_port != MACH_PORT_NULL) {
    EXPECT_TRUE(found);
  } else {
    EXPECT_FALSE(found);
  }
}

class TestExceptionPorts : public MachMultiprocess,
                           public UniversalMachExcServer::Interface {
 public:
  // Whether to call SetExceptionPort or SwapExceptionPorts.
  enum SetOrSwap {
    kSetExceptionPort = 0,
    kSwapExceptionPorts,
  };

  // Which entities to set exception ports for.
  enum SetOn {
    kSetOnTaskOnly = 0,
    kSetOnTaskAndThreads,
  };

  // Where to call ExceptionPorts::SetExceptionPort() from.
  enum SetType {
    // Call it from the child process on itself.
    kSetInProcess = 0,

    // Call it from the parent process on the child.
    kSetOutOfProcess,
  };

  // Which thread in the child process is expected to crash.
  enum WhoCrashes {
    kNobodyCrashes = 0,
    kMainThreadCrashes,
    kOtherThreadCrashes,
  };

  TestExceptionPorts(SetOrSwap set_or_swap,
                     SetOn set_on,
                     SetType set_type,
                     WhoCrashes who_crashes)
      : MachMultiprocess(),
        UniversalMachExcServer::Interface(),
        set_or_swap_(set_or_swap),
        set_on_(set_on),
        set_type_(set_type),
        who_crashes_(who_crashes),
        handled_(false) {
    if (who_crashes_ != kNobodyCrashes) {
      SetExpectedChildTerminationBuiltinTrap();
    }
  }

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

  SetOrSwap set_or_swap() const { return set_or_swap_; }
  SetOn set_on() const { return set_on_; }
  SetType set_type() const { return set_type_; }
  WhoCrashes who_crashes() const { return who_crashes_; }

  // UniversalMachExcServer::Interface:

  virtual kern_return_t CatchMachException(
      exception_behavior_t behavior,
      exception_handler_t exception_port,
      thread_t thread,
      task_t task,
      exception_type_t exception,
      const mach_exception_data_type_t* code,
      mach_msg_type_number_t code_count,
      thread_state_flavor_t* flavor,
      ConstThreadState old_state,
      mach_msg_type_number_t old_state_count,
      thread_state_t new_state,
      mach_msg_type_number_t* new_state_count,
      const mach_msg_trailer_t* trailer,
      bool* destroy_complex_request) override {
    *destroy_complex_request = true;

    EXPECT_FALSE(handled_);
    handled_ = true;

    // To be able to distinguish between which handler was actually triggered,
    // the different handlers are registered with different behavior values.
    exception_behavior_t expect_behavior;
    if (set_on_ == kSetOnTaskOnly) {
      expect_behavior = EXCEPTION_DEFAULT;
    } else if (who_crashes_ == kMainThreadCrashes) {
      expect_behavior = EXCEPTION_STATE;
    } else if (who_crashes_ == kOtherThreadCrashes) {
      expect_behavior = EXCEPTION_STATE_IDENTITY;
    } else {
      NOTREACHED();
      expect_behavior = 0;
    }

    EXPECT_EQ(behavior, expect_behavior);

    EXPECT_EQ(exception_port, LocalPort());

    EXPECT_EQ(exception, EXC_CRASH);
    EXPECT_EQ(code_count, 2u);

    // The exception and code_count checks above would ideally use ASSERT_EQ so
    // that the next conditional would not be necessary, but ASSERT_* requires a
    // function returning type void, and the interface dictates otherwise here.
    if (exception == EXC_CRASH && code_count >= 1) {
      int signal;
      ExcCrashRecoverOriginalException(code[0], nullptr, &signal);

#if defined(ARCH_CPU_X86_FAMILY)
      constexpr int kBuiltinTrapSignal = SIGILL;
#elif defined(ARCH_CPU_ARM64)
      constexpr int kBuiltinTrapSignal = SIGTRAP;
#else
#error Port
#endif
      EXPECT_EQ(signal, kBuiltinTrapSignal);
    }

    EXPECT_EQ(AuditPIDFromMachMessageTrailer(trailer), 0);

    ExcServerCopyState(
        behavior, old_state, old_state_count, new_state, new_state_count);
    return ExcServerSuccessfulReturnValue(exception, behavior, false);
  }

 private:
  class Child {
   public:
    explicit Child(TestExceptionPorts* test_exception_ports)
        : test_exception_ports_(test_exception_ports),
          thread_(),
          init_semaphore_(0),
          crash_semaphore_(0) {}

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

    ~Child() {}

    void Run() {
      ExceptionPorts self_task_ports(ExceptionPorts::kTargetTypeTask,
                                     TASK_NULL);
      ExceptionPorts self_thread_ports(ExceptionPorts::kTargetTypeThread,
                                       THREAD_NULL);

      mach_port_t remote_port = test_exception_ports_->RemotePort();

      // Set the task’s and this thread’s exception ports, if appropriate.
      if (test_exception_ports_->set_type() == kSetInProcess) {
        switch (test_exception_ports_->set_or_swap()) {
          case kSetExceptionPort: {
            ASSERT_TRUE(self_task_ports.SetExceptionPort(EXC_MASK_CRASH,
                                                         remote_port,
                                                         EXCEPTION_DEFAULT,
                                                         THREAD_STATE_NONE));

            if (test_exception_ports_->set_on() == kSetOnTaskAndThreads) {
              ASSERT_TRUE(
                  self_thread_ports.SetExceptionPort(EXC_MASK_CRASH,
                                                     remote_port,
                                                     EXCEPTION_STATE,
                                                     MACHINE_THREAD_STATE));
            }

            break;
          }

          case kSwapExceptionPorts: {
            ExceptionPorts::ExceptionHandlerVector old_handlers;
            ASSERT_TRUE(self_task_ports.SwapExceptionPorts(EXC_MASK_CRASH,
                                                           remote_port,
                                                           EXCEPTION_DEFAULT,
                                                           THREAD_STATE_NONE,
                                                           &old_handlers));

            if (test_exception_ports_->set_on() == kSetOnTaskAndThreads) {
              ASSERT_TRUE(
                  self_thread_ports.SwapExceptionPorts(EXC_MASK_CRASH,
                                                       remote_port,
                                                       EXCEPTION_STATE,
                                                       MACHINE_THREAD_STATE,
                                                       &old_handlers));
            }

            break;
          }

          default: {
            NOTREACHED();
          }
        }
      }

      int rv_int = pthread_create(&thread_, nullptr, ThreadMainThunk, this);
      ASSERT_EQ(rv_int, 0);

      // Wait for the new thread to be ready.
      init_semaphore_.Wait();

      // Tell the parent process that everything is set up.
      char c = '\0';
      CheckedWriteFile(test_exception_ports_->WritePipeHandle(), &c, 1);

      // Wait for the parent process to say that its end is set up.
      CheckedReadFileExactly(test_exception_ports_->ReadPipeHandle(), &c, 1);
      EXPECT_EQ(c, '\0');

      // Regardless of where ExceptionPorts::SetExceptionPort() ran,
      // ExceptionPorts::GetExceptionPorts() can always be tested in-process.
      {
        SCOPED_TRACE("task");
        TestGetExceptionPorts(self_task_ports, remote_port, EXCEPTION_DEFAULT);
      }

      {
        SCOPED_TRACE("main_thread");
        mach_port_t thread_handler =
            (test_exception_ports_->set_on() == kSetOnTaskAndThreads)
                ? remote_port
                : MACH_PORT_NULL;
        TestGetExceptionPorts(
            self_thread_ports, thread_handler, EXCEPTION_STATE);
      }

      // Let the other thread know it’s safe to proceed.
      crash_semaphore_.Signal();

      // If this thread is the one that crashes, do it.
      if (test_exception_ports_->who_crashes() == kMainThreadCrashes) {
        Crash();
      }

      // Reap the other thread.
      rv_int = pthread_join(thread_, nullptr);
      ASSERT_EQ(rv_int, 0);
    }

   private:
    // Calls ThreadMain().
    static void* ThreadMainThunk(void* argument) {
      Child* self = reinterpret_cast<Child*>(argument);
      return self->ThreadMain();
    }

    // Runs the “other” thread.
    void* ThreadMain() {
      ExceptionPorts self_thread_ports(ExceptionPorts::kTargetTypeThread,
                                       THREAD_NULL);
      mach_port_t remote_port = test_exception_ports_->RemotePort();

      // Set this thread’s exception handler, if appropriate.
      if (test_exception_ports_->set_type() == kSetInProcess &&
          test_exception_ports_->set_on() == kSetOnTaskAndThreads) {
        switch (test_exception_ports_->set_or_swap()) {
          case kSetExceptionPort: {
            CHECK(self_thread_ports.SetExceptionPort(EXC_MASK_CRASH,
                                                     remote_port,
                                                     EXCEPTION_STATE_IDENTITY,
                                                     MACHINE_THREAD_STATE));
            break;
          }
          case kSwapExceptionPorts: {
            ExceptionPorts::ExceptionHandlerVector old_handlers;
            CHECK(self_thread_ports.SwapExceptionPorts(EXC_MASK_CRASH,
                                                       remote_port,
                                                       EXCEPTION_STATE_IDENTITY,
                                                       MACHINE_THREAD_STATE,
                                                       &old_handlers));
            break;
          }
          default: {
            NOTREACHED();
          }
        }
      }

      // Let the main thread know that this thread is ready.
      init_semaphore_.Signal();

      // Wait for the main thread to signal that it’s safe to proceed.
      crash_semaphore_.Wait();

      // Regardless of where ExceptionPorts::SetExceptionPort() ran,
      // ExceptionPorts::GetExceptionPorts() can always be tested in-process.
      {
        SCOPED_TRACE("other_thread");
        mach_port_t thread_handler =
            (test_exception_ports_->set_on() == kSetOnTaskAndThreads)
                ? remote_port
                : MACH_PORT_NULL;
        TestGetExceptionPorts(
            self_thread_ports, thread_handler, EXCEPTION_STATE_IDENTITY);
      }

      // If this thread is the one that crashes, do it.
      if (test_exception_ports_->who_crashes() == kOtherThreadCrashes) {
        Crash();
      }

      return nullptr;
    }

    static void Crash() {
      __builtin_trap();
    }

    // The parent object.
    TestExceptionPorts* test_exception_ports_;  // weak

    // The “other” thread.
    pthread_t thread_;

    // The main thread waits on this for the other thread to start up and
    // perform its own initialization.
    Semaphore init_semaphore_;

    // The child thread waits on this for the parent thread to indicate that the
    // child can test its exception ports and possibly crash, as appropriate.
    Semaphore crash_semaphore_;
  };

  // MachMultiprocess:

  void MachMultiprocessParent() override {
    // Wait for the child process to be ready. It needs to have all of its
    // threads set up before proceeding if in kSetOutOfProcess mode.
    char c;
    CheckedReadFileExactly(ReadPipeHandle(), &c, 1);
    EXPECT_EQ(c, '\0');

    mach_port_t local_port = LocalPort();

    // Get an ExceptionPorts object for the task and each of its threads.
    ExceptionPorts task_ports(ExceptionPorts::kTargetTypeTask, ChildTask());
    EXPECT_STREQ("task", task_ports.TargetTypeName());

    // Hopefully the threads returned by task_threads() are in order, with the
    // main thread first and the other thread second. This is currently always
    // the case, although nothing guarantees that it will remain so.
    thread_act_array_t threads;
    mach_msg_type_number_t thread_count = 0;
    kern_return_t kr = task_threads(ChildTask(), &threads, &thread_count);
    ASSERT_EQ(kr, KERN_SUCCESS) << MachErrorMessage(kr, "task_threads");

    ScopedForbidReturn threads_need_owners;
    ASSERT_EQ(thread_count, 2u);
    base::mac::ScopedMachSendRight main_thread(threads[0]);
    base::mac::ScopedMachSendRight other_thread(threads[1]);
    threads_need_owners.Disarm();

    ExceptionPorts main_thread_ports(ExceptionPorts::kTargetTypeThread,
                                     main_thread.get());
    ExceptionPorts other_thread_ports(ExceptionPorts::kTargetTypeThread,
                                      other_thread.get());
    EXPECT_STREQ("thread", main_thread_ports.TargetTypeName());
    EXPECT_STREQ("thread", other_thread_ports.TargetTypeName());

    if (set_type_ == kSetOutOfProcess) {
      // Test ExceptionPorts::SetExceptionPort() being called from
      // out-of-process.
      //
      // local_port is only a receive right, but a send right is needed for
      // ExceptionPorts::SetExceptionPort(). Make a send right, which can be
      // deallocated once the calls to ExceptionPorts::SetExceptionPort() are
      // done.
      kr = mach_port_insert_right(
          mach_task_self(), local_port, local_port, MACH_MSG_TYPE_MAKE_SEND);
      ASSERT_EQ(kr, KERN_SUCCESS)
          << MachErrorMessage(kr, "mach_port_insert_right");
      base::mac::ScopedMachSendRight send_owner(local_port);

      switch (set_or_swap_) {
        case kSetExceptionPort: {
          ASSERT_TRUE(task_ports.SetExceptionPort(EXC_MASK_CRASH,
                                                  local_port,
                                                  EXCEPTION_DEFAULT,
                                                  THREAD_STATE_NONE));

          if (set_on_ == kSetOnTaskAndThreads) {
            ASSERT_TRUE(
                main_thread_ports.SetExceptionPort(EXC_MASK_CRASH,
                                                   local_port,
                                                   EXCEPTION_STATE,
                                                   MACHINE_THREAD_STATE));

            ASSERT_TRUE(
                other_thread_ports.SetExceptionPort(EXC_MASK_CRASH,
                                                    local_port,
                                                    EXCEPTION_STATE_IDENTITY,
                                                    MACHINE_THREAD_STATE));
          }
          break;
        }

        case kSwapExceptionPorts: {
          ExceptionPorts::ExceptionHandlerVector old_handlers;

          ASSERT_TRUE(task_ports.SwapExceptionPorts(EXC_MASK_CRASH,
                                                    local_port,
                                                    EXCEPTION_DEFAULT,
                                                    THREAD_STATE_NONE,
                                                    &old_handlers));

          if (set_on_ == kSetOnTaskAndThreads) {
            ASSERT_TRUE(
                main_thread_ports.SwapExceptionPorts(EXC_MASK_CRASH,
                                                     local_port,
                                                     EXCEPTION_STATE,
                                                     MACHINE_THREAD_STATE,
                                                     &old_handlers));

            ASSERT_TRUE(
                other_thread_ports.SwapExceptionPorts(EXC_MASK_CRASH,
                                                      local_port,
                                                      EXCEPTION_STATE_IDENTITY,
                                                      MACHINE_THREAD_STATE,
                                                      &old_handlers));
          }
          break;
        }

        default: {
          NOTREACHED();
        }
      }
    }

    // Regardless of where ExceptionPorts::SetExceptionPort() ran,
    // ExceptionPorts::GetExceptionPorts() can always be tested out-of-process.
    {
      SCOPED_TRACE("task");
      TestGetExceptionPorts(task_ports, local_port, EXCEPTION_DEFAULT);
    }

    mach_port_t thread_handler =
        (set_on_ == kSetOnTaskAndThreads) ? local_port : MACH_PORT_NULL;

    {
      SCOPED_TRACE("main_thread");
      TestGetExceptionPorts(main_thread_ports, thread_handler, EXCEPTION_STATE);
    }

    {
      SCOPED_TRACE("other_thread");
      TestGetExceptionPorts(
          other_thread_ports, thread_handler, EXCEPTION_STATE_IDENTITY);
    }

    // Let the child process know that everything in the parent process is set
    // up.
    c = '\0';
    CheckedWriteFile(WritePipeHandle(), &c, 1);

    if (who_crashes_ != kNobodyCrashes) {
      UniversalMachExcServer universal_mach_exc_server(this);

      constexpr mach_msg_timeout_t kTimeoutMs = 50;
      kern_return_t kr =
          MachMessageServer::Run(&universal_mach_exc_server,
                                 local_port,
                                 kMachMessageReceiveAuditTrailer,
                                 MachMessageServer::kOneShot,
                                 MachMessageServer::kReceiveLargeError,
                                 kTimeoutMs);
      EXPECT_EQ(kr, KERN_SUCCESS)
          << MachErrorMessage(kr, "MachMessageServer::Run");

      EXPECT_TRUE(handled_);
    }

    // Wait for the child process to exit or terminate, as indicated by it
    // closing its pipe. This keeps LocalPort() alive in the child as
    // RemotePort(), for the child’s use in its TestGetExceptionPorts().
    CheckedReadFileAtEOF(ReadPipeHandle());
  }

  void MachMultiprocessChild() override {
    Child child(this);
    child.Run();
  }

  SetOrSwap set_or_swap_;
  SetOn set_on_;
  SetType set_type_;
  WhoCrashes who_crashes_;

  // true if an exception message was handled.
  bool handled_;
};

TEST(ExceptionPorts, TaskExceptionPorts_SetInProcess_NoCrash) {
  TestExceptionPorts test_exception_ports(TestExceptionPorts::kSetExceptionPort,
                                          TestExceptionPorts::kSetOnTaskOnly,
                                          TestExceptionPorts::kSetInProcess,
                                          TestExceptionPorts::kNobodyCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskExceptionPorts_SetInProcess_MainThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSetExceptionPort,
      TestExceptionPorts::kSetOnTaskOnly,
      TestExceptionPorts::kSetInProcess,
      TestExceptionPorts::kMainThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskExceptionPorts_SetInProcess_OtherThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSetExceptionPort,
      TestExceptionPorts::kSetOnTaskOnly,
      TestExceptionPorts::kSetInProcess,
      TestExceptionPorts::kOtherThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskAndThreadExceptionPorts_SetInProcess_NoCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSetExceptionPort,
      TestExceptionPorts::kSetOnTaskAndThreads,
      TestExceptionPorts::kSetInProcess,
      TestExceptionPorts::kNobodyCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskAndThreadExceptionPorts_SetInProcess_MainThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSetExceptionPort,
      TestExceptionPorts::kSetOnTaskAndThreads,
      TestExceptionPorts::kSetInProcess,
      TestExceptionPorts::kMainThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts,
     TaskAndThreadExceptionPorts_SetInProcess_OtherThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSetExceptionPort,
      TestExceptionPorts::kSetOnTaskAndThreads,
      TestExceptionPorts::kSetInProcess,
      TestExceptionPorts::kOtherThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskExceptionPorts_SetOutOfProcess_NoCrash) {
  TestExceptionPorts test_exception_ports(TestExceptionPorts::kSetExceptionPort,
                                          TestExceptionPorts::kSetOnTaskOnly,
                                          TestExceptionPorts::kSetOutOfProcess,
                                          TestExceptionPorts::kNobodyCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskExceptionPorts_SetOutOfProcess_MainThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSetExceptionPort,
      TestExceptionPorts::kSetOnTaskOnly,
      TestExceptionPorts::kSetOutOfProcess,
      TestExceptionPorts::kMainThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskExceptionPorts_SetOutOfProcess_OtherThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSetExceptionPort,
      TestExceptionPorts::kSetOnTaskOnly,
      TestExceptionPorts::kSetOutOfProcess,
      TestExceptionPorts::kOtherThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskAndThreadExceptionPorts_SetOutOfProcess_NoCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSetExceptionPort,
      TestExceptionPorts::kSetOnTaskAndThreads,
      TestExceptionPorts::kSetOutOfProcess,
      TestExceptionPorts::kNobodyCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts,
     TaskAndThreadExceptionPorts_SetOutOfProcess_MainThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSetExceptionPort,
      TestExceptionPorts::kSetOnTaskAndThreads,
      TestExceptionPorts::kSetOutOfProcess,
      TestExceptionPorts::kMainThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts,
     TaskAndThreadExceptionPorts_SetOutOfProcess_OtherThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSetExceptionPort,
      TestExceptionPorts::kSetOnTaskAndThreads,
      TestExceptionPorts::kSetOutOfProcess,
      TestExceptionPorts::kOtherThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskExceptionPorts_SwapInProcess_NoCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSwapExceptionPorts,
      TestExceptionPorts::kSetOnTaskOnly,
      TestExceptionPorts::kSetInProcess,
      TestExceptionPorts::kNobodyCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskExceptionPorts_SwapInProcess_MainThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSwapExceptionPorts,
      TestExceptionPorts::kSetOnTaskOnly,
      TestExceptionPorts::kSetInProcess,
      TestExceptionPorts::kMainThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskExceptionPorts_SwapInProcess_OtherThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSwapExceptionPorts,
      TestExceptionPorts::kSetOnTaskOnly,
      TestExceptionPorts::kSetInProcess,
      TestExceptionPorts::kOtherThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskAndThreadExceptionPorts_SwapInProcess_NoCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSwapExceptionPorts,
      TestExceptionPorts::kSetOnTaskAndThreads,
      TestExceptionPorts::kSetInProcess,
      TestExceptionPorts::kNobodyCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts,
     TaskAndThreadExceptionPorts_SwapInProcess_MainThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSwapExceptionPorts,
      TestExceptionPorts::kSetOnTaskAndThreads,
      TestExceptionPorts::kSetInProcess,
      TestExceptionPorts::kMainThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts,
     TaskAndThreadExceptionPorts_SwapInProcess_OtherThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSwapExceptionPorts,
      TestExceptionPorts::kSetOnTaskAndThreads,
      TestExceptionPorts::kSetInProcess,
      TestExceptionPorts::kOtherThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskExceptionPorts_SwapOutOfProcess_NoCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSwapExceptionPorts,
      TestExceptionPorts::kSetOnTaskOnly,
      TestExceptionPorts::kSetOutOfProcess,
      TestExceptionPorts::kNobodyCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskExceptionPorts_SwapOutOfProcess_MainThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSwapExceptionPorts,
      TestExceptionPorts::kSetOnTaskOnly,
      TestExceptionPorts::kSetOutOfProcess,
      TestExceptionPorts::kMainThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskExceptionPorts_SwapOutOfProcess_OtherThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSwapExceptionPorts,
      TestExceptionPorts::kSetOnTaskOnly,
      TestExceptionPorts::kSetOutOfProcess,
      TestExceptionPorts::kOtherThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, TaskAndThreadExceptionPorts_SwapOutOfProcess_NoCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSwapExceptionPorts,
      TestExceptionPorts::kSetOnTaskAndThreads,
      TestExceptionPorts::kSetOutOfProcess,
      TestExceptionPorts::kNobodyCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts,
     TaskAndThreadExceptionPorts_SwapOutOfProcess_MainThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSwapExceptionPorts,
      TestExceptionPorts::kSetOnTaskAndThreads,
      TestExceptionPorts::kSetOutOfProcess,
      TestExceptionPorts::kMainThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts,
     TaskAndThreadExceptionPorts_SwapOutOfProcess_OtherThreadCrash) {
  TestExceptionPorts test_exception_ports(
      TestExceptionPorts::kSwapExceptionPorts,
      TestExceptionPorts::kSetOnTaskAndThreads,
      TestExceptionPorts::kSetOutOfProcess,
      TestExceptionPorts::kOtherThreadCrashes);
  test_exception_ports.Run();
}

TEST(ExceptionPorts, HostExceptionPorts) {
  // ExceptionPorts isn’t expected to work as non-root. Just do a quick test to
  // make sure that TargetTypeName() returns the right string, and that the
  // underlying host_get_exception_ports() function appears to be called by
  // looking for a KERN_INVALID_ARGUMENT return value. Or, on the off chance
  // that the test is being run as root, just look for KERN_SUCCESS.
  // host_set_exception_ports() is not tested, because if the test were running
  // as root and the call succeeded, it would have global effects.

  const bool expect_success = geteuid() == 0;

  base::mac::ScopedMachSendRight host(mach_host_self());
  ExceptionPorts explicit_host_ports(ExceptionPorts::kTargetTypeHost,
                                     host.get());
  EXPECT_STREQ("host", explicit_host_ports.TargetTypeName());

  ExceptionPorts::ExceptionHandlerVector explicit_handlers;
  bool rv =
      explicit_host_ports.GetExceptionPorts(ExcMaskValid(), &explicit_handlers);
  EXPECT_EQ(rv, expect_success);

  ExceptionPorts implicit_host_ports(ExceptionPorts::kTargetTypeHost,
                                     HOST_NULL);
  EXPECT_STREQ("host", implicit_host_ports.TargetTypeName());

  ExceptionPorts::ExceptionHandlerVector implicit_handlers;
  rv =
      implicit_host_ports.GetExceptionPorts(ExcMaskValid(), &implicit_handlers);
  EXPECT_EQ(rv, expect_success);

  EXPECT_EQ(implicit_handlers.size(), explicit_handlers.size());
}

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