// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <lib/fit/function.h>
#include <lib/zx/clock.h>
#include <lib/zx/event.h>
#include <lib/zx/job.h>
#include <lib/zx/msi.h>
#include <lib/zx/process.h>
#include <lib/zx/thread.h>
#include <lib/zx/time.h>
#include <lib/zx/vmar.h>
#include <threads.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/debug.h>
#include <zircon/syscalls/exception.h>
#include <zircon/syscalls/object.h>
#include <zircon/types.h>

#include <algorithm>
#include <atomic>
#include <cassert>
#include <climits>
#include <vector>

#include <mini-process/mini-process.h>
#include <zxtest/zxtest.h>

namespace {

#ifdef __aarch64__
constexpr auto kThreadRegister = &zx_thread_state_general_regs_t::tpidr;
#elif defined(__x86_64__)
constexpr auto kThreadRegister = &zx_thread_state_general_regs_t::fs_base;
#endif

const zx_time_t kTimeoutNs = ZX_MSEC(250);

TEST(ProcessTest, LongNameSucceeds) {
  // Creating a process with a super long name should succeed.
  static const char long_name[] =
      "0123456789012345678901234567890123456789"
      "0123456789012345678901234567890123456789";
  ASSERT_GT(strlen(long_name), (size_t)ZX_MAX_NAME_LEN - 1, "too short to truncate");

  zx_handle_t proc;
  zx_handle_t vmar;
  ASSERT_OK(zx_process_create(zx_job_default(), long_name, sizeof(long_name), 0, &proc, &vmar));
  static char proc_name[ZX_MAX_NAME_LEN];
  ASSERT_OK(zx_object_get_property(proc, ZX_PROP_NAME, proc_name, ZX_MAX_NAME_LEN));
  ASSERT_EQ(strncmp(proc_name, long_name, ZX_MAX_NAME_LEN - 1), 0);
  ASSERT_OK(zx_handle_close(vmar));
  ASSERT_OK(zx_handle_close(proc));
}

TEST(ProcessTest, EmptyNameSucceeds) {
  // Creating a process with "" name, 0 name_len should succeed.
  zx_handle_t proc;
  zx_handle_t vmar;
  ASSERT_OK(zx_process_create(zx_job_default(), "", 0, 0, &proc, &vmar));
  static char proc_name[ZX_MAX_NAME_LEN];
  ASSERT_OK(zx_object_get_property(proc, ZX_PROP_NAME, proc_name, ZX_MAX_NAME_LEN));
  ASSERT_EQ(strcmp(proc_name, ""), 0);
  ASSERT_OK(zx_handle_close(vmar));
  ASSERT_OK(zx_handle_close(proc));
}

TEST(ProcessTest, GetRuntimeNoPermission) {
  zx::process proc;
  zx::vmar vmar;
  ASSERT_OK(zx::process::create(*zx::job::default_job(), "", 0, 0, &proc, &vmar));

  zx_info_handle_basic basic;
  ASSERT_OK(proc.get_info(ZX_INFO_HANDLE_BASIC, &basic, sizeof(basic), nullptr, nullptr));

  zx::process proc_dup;
  ASSERT_OK(proc.duplicate(basic.rights & ~ZX_RIGHT_INSPECT, &proc_dup));
  zx_info_task_runtime_t info;
  ASSERT_OK(proc.get_info(ZX_INFO_TASK_RUNTIME, &info, sizeof(info), nullptr, nullptr));
  ASSERT_EQ(proc_dup.get_info(ZX_INFO_TASK_RUNTIME, &info, sizeof(info), nullptr, nullptr),
            ZX_ERR_ACCESS_DENIED);
}

TEST(ProcessTest, MiniProcessSanity) {
  zx_handle_t proc;
  zx_handle_t thread;
  zx_handle_t vmar;

  ASSERT_OK(zx_process_create(zx_job_default(), "mini-p", 3u, 0, &proc, &vmar));
  ASSERT_OK(zx_thread_create(proc, "mini-p", 2u, 0u, &thread));

  zx_handle_t event;
  ASSERT_OK(zx_event_create(0u, &event));

  zx_handle_t cmd_channel;
  EXPECT_OK(start_mini_process_etc(proc, thread, vmar, event, true, &cmd_channel));

  EXPECT_OK(mini_process_cmd(cmd_channel, MINIP_CMD_ECHO_MSG, nullptr));

  zx_handle_t oev;
  EXPECT_OK(mini_process_cmd(cmd_channel, MINIP_CMD_CREATE_EVENT, &oev));

  EXPECT_EQ(mini_process_cmd(cmd_channel, MINIP_CMD_EXIT_NORMAL, nullptr), ZX_ERR_PEER_CLOSED);

  zx_handle_close(thread);
  zx_handle_close(proc);
  zx_handle_close(vmar);
}

TEST(ProcessTest, ProcessStartNoHandle) {
  zx_handle_t proc;
  zx_handle_t thread;
  zx_handle_t vmar;

  constexpr const char kTestName[] = "test-no-handles";
  ASSERT_OK(zx_process_create(zx_job_default(), kTestName, sizeof(kTestName) - 1, 0, &proc, &vmar));
  ASSERT_OK(zx_thread_create(proc, kTestName, sizeof(kTestName) - 1, 0u, &thread));

  // The process will get no handles, but it can still make syscalls.
  // The vDSO's e_entry points to zx_process_exit.  So the process will
  // enter at `zx_process_exit(ZX_HANDLE_INVALID);`.
  uintptr_t entry;
  EXPECT_OK(mini_process_load_vdso(proc, vmar, nullptr, &entry));

  // The vDSO ABI needs a stack, though zx_process_exit actually might not.
  uintptr_t stack_base, sp;
  EXPECT_OK(mini_process_load_stack(vmar, false, &stack_base, &sp));
  zx_handle_close(vmar);

  EXPECT_OK(zx_process_start(proc, thread, entry, sp, ZX_HANDLE_INVALID, 0));
  zx_handle_close(thread);

  zx_signals_t signals;
  EXPECT_OK(zx_object_wait_one(proc, ZX_TASK_TERMINATED, zx_deadline_after(ZX_SEC(1)), &signals));
  EXPECT_EQ(signals, ZX_TASK_TERMINATED);

  {
    zx_info_process_t info{};
    EXPECT_OK(zx_object_get_info(proc, ZX_INFO_PROCESS, &info, sizeof(info), nullptr, nullptr));
    EXPECT_EQ(info.return_code, int64_t{ZX_HANDLE_INVALID});
  }

  zx_handle_close(proc);
}

#if defined(__x86_64__)

#include <cpuid.h>

// This is based on code from kernel/ which isn't usable by code in system/.
enum { X86_CPUID_ADDR_WIDTH = 0x80000008 };

static uint32_t x86_linear_address_width() {
  uint32_t eax, ebx, ecx, edx;
  __cpuid(X86_CPUID_ADDR_WIDTH, eax, ebx, ecx, edx);
  return (eax >> 8) & 0xff;
}

#endif

TEST(ProcessTest, ProcessStartNonUserspaceEntry) {
  auto test_process_start = [&](uintptr_t entry, zx_status_t expected) {
    zx_handle_t proc;
    zx_handle_t thread;
    zx_handle_t vmar;

    constexpr const char kTestName[] = "test-noncanonical-entry";
    ASSERT_OK(
        zx_process_create(zx_job_default(), kTestName, sizeof(kTestName) - 1, 0, &proc, &vmar));
    zx_handle_close(vmar);
    ASSERT_OK(zx_thread_create(proc, kTestName, sizeof(kTestName) - 1, 0u, &thread));

    char stack[1024] __ALIGNED(16);  // a small stack for the process.
    uintptr_t sp = reinterpret_cast<uintptr_t>(&stack[1024]);

    EXPECT_EQ(expected, zx_process_start(proc, thread, entry, sp, ZX_HANDLE_INVALID, 0));
    zx_handle_close(thread);
    zx_handle_close(proc);
  };

  // This represents an inaccessible address on both aarch64 (because bit 55 == 0
  // indicates an accessible user address) and x86_64 (because the upper 16 bits
  // are not all zero).
  uintptr_t non_user_pc = 0x1UL << 55;
  uintptr_t kernel_pc = 0xffffff8000000000UL;

  test_process_start(non_user_pc, ZX_ERR_INVALID_ARGS);
  test_process_start(kernel_pc, ZX_ERR_INVALID_ARGS);

#if defined(__x86_64__)
  uintptr_t non_canonical_pc = ((uintptr_t)1) << (x86_linear_address_width() - 1);
  test_process_start(non_canonical_pc, ZX_ERR_INVALID_ARGS);
#endif  // defined(__x86_64__)
}

TEST(ProcessTest, ProcessStartFail) {
  zx_handle_t event1, event2;
  zx_handle_t process;
  zx_handle_t thread;

  ASSERT_OK(zx_event_create(0u, &event1));
  ASSERT_OK(zx_event_create(0u, &event2));

  ASSERT_OK(start_mini_process(zx_job_default(), event1, &process, &thread));

  zx_handle_t other_thread;
  ASSERT_OK(zx_thread_create(process, "test", 4u, 0, &other_thread));

  // Test that calling process_start() again for an existing process fails in a
  // reasonable way. Also test that the transferred object is closed.
  EXPECT_EQ(zx_process_start(process, other_thread, 0, 0, event2, 0), ZX_ERR_BAD_STATE);

  zx_handle_close(process);
  zx_handle_close(thread);
  zx_handle_close(other_thread);
}

TEST(ProcessTest, ProcessNotKilledViaThreadClose) {
  zx_handle_t event;
  ASSERT_OK(zx_event_create(0u, &event));

  zx_handle_t process;
  zx_handle_t thread;
  ASSERT_OK(start_mini_process(zx_job_default(), event, &process, &thread));

  EXPECT_OK(zx_handle_close(thread));

  // The timeout below does not have to be large because the processing happens
  // synchronously if indeed |thread| is the last handle.
  zx_signals_t signals = 0;
  EXPECT_EQ(
      zx_object_wait_one(process, ZX_TASK_TERMINATED, zx_deadline_after(ZX_MSEC(1)), &signals),
      ZX_ERR_TIMED_OUT);
  EXPECT_NE(signals, ZX_TASK_TERMINATED);

  EXPECT_OK(zx_handle_close(process));
}

TEST(ProcessTest, ProcessNotKilledViaProcessClose) {
  zx_handle_t event;
  ASSERT_OK(zx_event_create(0u, &event));

  zx_handle_t process;
  zx_handle_t thread;
  ASSERT_OK(start_mini_process(zx_job_default(), event, &process, &thread));

  EXPECT_OK(zx_handle_close(process));

  // The timeout below does not have to be large because the processing happens
  // synchronously if indeed |process| is the last handle.
  zx_signals_t signals;
  EXPECT_EQ(zx_object_wait_one(thread, ZX_TASK_TERMINATED, zx_deadline_after(ZX_MSEC(1)), &signals),
            ZX_ERR_TIMED_OUT);

  EXPECT_OK(zx_handle_close(thread));
}

zx_status_t dup_send_handle(zx_handle_t channel, zx_handle_t handle) {
  zx_handle_t dup;
  zx_status_t st = zx_handle_duplicate(handle, ZX_RIGHT_SAME_RIGHTS, &dup);
  if (st < 0)
    return st;
  return zx_channel_write(channel, 0u, nullptr, 0u, &dup, 1u);
}

TEST(ProcessTest, KillChannelHandleCycle) {
  zx_handle_t chan[2] = {ZX_HANDLE_INVALID, ZX_HANDLE_INVALID};
  ASSERT_OK(zx_channel_create(0u, &chan[0], &chan[1]));

  zx_handle_t proc1, proc2;
  zx_handle_t vmar1, vmar2;

  zx_handle_t job_child;
  ASSERT_OK(zx_job_create(zx_job_default(), 0u, &job_child));

  ASSERT_OK(zx_process_create(job_child, "ttp1", 4u, 0u, &proc1, &vmar1));
  ASSERT_OK(zx_process_create(job_child, "ttp2", 4u, 0u, &proc2, &vmar2));

  zx_handle_t thread1, thread2;

  ASSERT_OK(zx_thread_create(proc1, "th1", 3u, 0u, &thread1));
  ASSERT_OK(zx_thread_create(proc2, "th2", 3u, 0u, &thread2));

  // Now we stuff duplicated process and thread handles into each side of the channel.
  EXPECT_OK(dup_send_handle(chan[0], proc2));
  EXPECT_OK(dup_send_handle(chan[0], thread2));

  EXPECT_OK(dup_send_handle(chan[1], proc1));
  EXPECT_OK(dup_send_handle(chan[1], thread1));

  // The process start with each one side of the channel. We don't have access to the
  // channel anymore.

  zx_handle_t minip_chn[2];

  EXPECT_OK(start_mini_process_etc(proc1, thread1, vmar1, chan[0], true, &minip_chn[0]));
  EXPECT_OK(start_mini_process_etc(proc2, thread2, vmar2, chan[1], true, &minip_chn[1]));

  EXPECT_OK(zx_handle_close(vmar2));
  EXPECT_OK(zx_handle_close(vmar1));

  EXPECT_OK(zx_handle_close(proc1));
  EXPECT_OK(zx_handle_close(proc2));

  // Make (relatively) certain the processes are alive.

  zx_signals_t signals;
  EXPECT_EQ(
      zx_object_wait_one(thread1, ZX_TASK_TERMINATED, zx_deadline_after(kTimeoutNs), &signals),
      ZX_ERR_TIMED_OUT);

  EXPECT_EQ(
      zx_object_wait_one(thread2, ZX_TASK_TERMINATED, zx_deadline_after(kTimeoutNs), &signals),
      ZX_ERR_TIMED_OUT);

  // At this point the two processes have each other thread/process handles.
  EXPECT_OK(zx_handle_close(thread1));

  EXPECT_EQ(
      zx_object_wait_one(thread2, ZX_TASK_TERMINATED, zx_deadline_after(kTimeoutNs), &signals),
      ZX_ERR_TIMED_OUT);

  // The only way out of this situation is to use the job handle.
  EXPECT_OK(zx_task_kill(job_child));

  EXPECT_OK(zx_object_wait_one(thread2, ZX_TASK_TERMINATED, ZX_TIME_INFINITE, &signals));
  signals &= ZX_TASK_TERMINATED;
  EXPECT_EQ(signals, ZX_TASK_TERMINATED);

  EXPECT_OK(zx_handle_close(thread2));
  EXPECT_OK(zx_handle_close(job_child));
}

// Tests that |zx_info_process_t| fields reflect the current state of a process.
TEST(ProcessTest, InfoReflectsProcessState) {
  // Create a process with one thread.
  zx_handle_t event;
  ASSERT_OK(zx_event_create(0u, &event));

  zx_handle_t job_child;
  ASSERT_OK(zx_job_create(zx_job_default(), 0u, &job_child));

  zx_handle_t proc;
  zx_handle_t vmar;
  ASSERT_OK(zx_process_create(job_child, "ttp", 4u, 0u, &proc, &vmar));
  EXPECT_OK(zx_handle_close(job_child));

  zx_handle_t thread;
  ASSERT_OK(zx_thread_create(proc, "th", 3u, 0u, &thread));

  {
    zx_info_process_t info;
    ASSERT_OK(zx_object_get_info(proc, ZX_INFO_PROCESS, &info, sizeof(info), NULL, NULL));
    EXPECT_FALSE(info.flags & ZX_INFO_PROCESS_FLAG_STARTED, "process should not appear as started");
    EXPECT_FALSE(info.flags & ZX_INFO_PROCESS_FLAG_EXITED, "process should not appear as exited");
    EXPECT_EQ(info.return_code, 0, "return code is zero");
  }

  const zx_time_t before_start = zx_clock_get_monotonic();

  zx_handle_t minip_chn;
  // Start the process and make (relatively) certain it's alive.
  ASSERT_OK(start_mini_process_etc(proc, thread, vmar, event, true, &minip_chn));

  const zx_time_t after_start = zx_clock_get_monotonic();

  zx_signals_t signals;
  ASSERT_EQ(zx_object_wait_one(proc, ZX_TASK_TERMINATED, zx_deadline_after(kTimeoutNs), &signals),
            ZX_ERR_TIMED_OUT);

  {
    zx_info_process_t info;
    ASSERT_OK(zx_object_get_info(proc, ZX_INFO_PROCESS, &info, sizeof(info), NULL, NULL));
    // `info.start_time` is only valid if the STARTED flag is set.
    ASSERT_TRUE(info.flags & ZX_INFO_PROCESS_FLAG_STARTED, "process should appear as started");
    EXPECT_FALSE(info.flags & ZX_INFO_PROCESS_FLAG_EXITED, "process should not appear as exited");
    EXPECT_GE(info.start_time, before_start);
    EXPECT_LE(info.start_time, after_start);
  }

  // Kill the process and wait for it to terminate.
  ASSERT_OK(zx_task_kill(proc));
  ASSERT_OK(zx_object_wait_one(proc, ZX_TASK_TERMINATED, ZX_TIME_INFINITE, &signals));
  ASSERT_EQ(signals, ZX_TASK_TERMINATED);

  {
    zx_info_process_t info;
    ASSERT_OK(zx_object_get_info(proc, ZX_INFO_PROCESS, &info, sizeof(info), NULL, NULL));
    // `info.start_time` is only valid if the STARTED flag is set.
    ASSERT_TRUE(info.flags & ZX_INFO_PROCESS_FLAG_STARTED, "process should appear as started");
    EXPECT_TRUE(info.flags & ZX_INFO_PROCESS_FLAG_EXITED, "process should appear as exited");
    EXPECT_EQ(info.return_code, ZX_TASK_RETCODE_SYSCALL_KILL, "process retcode invalid");
    EXPECT_GE(info.start_time, before_start);
    EXPECT_LE(info.start_time, after_start);
  }
}

// Helper class to encapsulate starting a process with up to kNumThreads no-op child threads.
class TestProcess {
 public:
  // Creates the process handle, must be called first before any other function.
  void CreateProcess() {
    constexpr const char* kProcessName = "test_process";
    EXPECT_OK(zx_process_create(zx_job_default(), kProcessName, strlen(kProcessName), 0, &process_,
                                &vmar_));
  }

  // Creates a child thread but does not start it.
  void CreateThread() {
    char name[32];
    size_t name_length = snprintf(name, sizeof(name), "test_thread_%lu", threads_.size());

    zx_handle_t thread;
    ASSERT_OK(zx_thread_create(process_, name, name_length, 0, &thread));
    threads_.push_back(thread);
  }

  // Starts the process and all child threads.
  void StartProcess() { return StartProcessWithControl(nullptr); }

  // Starts a process with a control channel that can be used to send commands.
  // Also starts all child threads.
  void StartProcessWithControl(zx_handle_t* out_control_channel) {
    ASSERT_GT(threads_.size(), 0);

    // The first thread must start the process.
    // We don't use this event but starting a new process requires passing it a handle.
    zx_handle_t event = ZX_HANDLE_INVALID;
    ASSERT_OK(zx_event_create(0u, &event));
    ASSERT_OK(
        start_mini_process_etc(process_, threads_[0], vmar_, event, true, out_control_channel));

    for (size_t i = 1; i < threads_.size(); ++i) {
      ASSERT_OK(start_mini_process_thread(threads_[i], vmar_));
    }
  }

  // Waits for a signal on the requested thread and returns true if the result
  // matches |expected|.
  //
  // If |expected| is ZX_ERR_TIMED_OUT this waits for a finite amount of time,
  // otherwise it waits forever.
  bool WaitForThreadSignal(int index, zx_signals_t signal, zx_status_t expected) {
    zx_time_t timeout = ZX_TIME_INFINITE;
    if (expected == ZX_ERR_TIMED_OUT)
      timeout = zx_deadline_after(kTimeoutNs);

    return zx_object_wait_one(threads_[index], signal, timeout, nullptr) == expected;
  }

  // Do this explicitly rather than in the destructor to catch any errors.
  void StopProcess() {
    EXPECT_OK(zx_task_kill(process_));
    EXPECT_OK(zx_handle_close(process_));
    EXPECT_OK(zx_handle_close(vmar_));
    if (!threads_.empty()) {
      EXPECT_OK(zx_handle_close_many(threads_.data(), threads_.size()));
    }
  }

  zx_handle_t process() const { return process_; }
  zx_handle_t thread(int index) const { return threads_[index]; }
  zx::channel& control_channel() { return control_channel_; }

 private:
  zx_handle_t process_ = ZX_HANDLE_INVALID;
  zx_handle_t vmar_ = ZX_HANDLE_INVALID;
  zx::channel control_channel_;

  std::vector<zx_handle_t> threads_;
};

TEST(ProcessTest, Suspend) {
  TestProcess test_process;
  ASSERT_NO_FAILURES(test_process.CreateProcess());
  ASSERT_NO_FAILURES(test_process.CreateThread());
  ASSERT_NO_FAILURES(test_process.StartProcess());

  zx_handle_t suspend_token;
  ASSERT_OK(zx_task_suspend(test_process.process(), &suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_SUSPENDED, ZX_OK));

  ASSERT_OK(zx_handle_close(suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_RUNNING, ZX_OK));

  ASSERT_NO_FAILURES(test_process.StopProcess());
}

TEST(ProcessTest, SuspendSelf) {
  zx_handle_t suspend_token;
  EXPECT_EQ(zx_task_suspend(zx_process_self(), &suspend_token), ZX_ERR_NOT_SUPPORTED);
}

TEST(ProcessTest, SuspendMultipleThreads) {
  TestProcess test_process;
  ASSERT_NO_FAILURES(test_process.CreateProcess());
  ASSERT_NO_FAILURES(test_process.CreateThread());
  ASSERT_NO_FAILURES(test_process.CreateThread());
  ASSERT_NO_FAILURES(test_process.CreateThread());
  ASSERT_NO_FAILURES(test_process.StartProcess());

  zx_handle_t suspend_token;
  ASSERT_OK(zx_task_suspend(test_process.process(), &suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_SUSPENDED, ZX_OK));
  ASSERT_TRUE(test_process.WaitForThreadSignal(1, ZX_THREAD_SUSPENDED, ZX_OK));
  ASSERT_TRUE(test_process.WaitForThreadSignal(2, ZX_THREAD_SUSPENDED, ZX_OK));

  ASSERT_OK(zx_handle_close(suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_RUNNING, ZX_OK));
  ASSERT_TRUE(test_process.WaitForThreadSignal(1, ZX_THREAD_RUNNING, ZX_OK));
  ASSERT_TRUE(test_process.WaitForThreadSignal(2, ZX_THREAD_RUNNING, ZX_OK));

  ASSERT_NO_FAILURES(test_process.StopProcess());
}

TEST(ProcessTest, SuspendBeforeCreatingThreads) {
  TestProcess test_process;
  ASSERT_NO_FAILURES(test_process.CreateProcess());

  zx_handle_t suspend_token;
  ASSERT_OK(zx_task_suspend(test_process.process(), &suspend_token));

  ASSERT_NO_FAILURES(test_process.CreateThread());
  ASSERT_NO_FAILURES(test_process.StartProcess());
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_SUSPENDED, ZX_OK));

  ASSERT_OK(zx_handle_close(suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_RUNNING, ZX_OK));

  ASSERT_NO_FAILURES(test_process.StopProcess());
}

TEST(ProcessTest, SuspendBeforeStartingThreads) {
  TestProcess test_process;
  ASSERT_NO_FAILURES(test_process.CreateProcess());
  ASSERT_NO_FAILURES(test_process.CreateThread());

  zx_handle_t suspend_token;
  ASSERT_OK(zx_task_suspend(test_process.process(), &suspend_token));

  ASSERT_NO_FAILURES(test_process.StartProcess());
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_SUSPENDED, ZX_OK));

  ASSERT_OK(zx_handle_close(suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_RUNNING, ZX_OK));

  ASSERT_NO_FAILURES(test_process.StopProcess());
}

TEST(ProcessTest, SuspendProcessThenThread) {
  TestProcess test_process;
  ASSERT_NO_FAILURES(test_process.CreateProcess());
  ASSERT_NO_FAILURES(test_process.CreateThread());
  ASSERT_NO_FAILURES(test_process.StartProcess());

  zx_handle_t process_suspend_token;
  ASSERT_OK(zx_task_suspend(test_process.process(), &process_suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_SUSPENDED, ZX_OK));

  zx_handle_t thread_suspend_token;
  ASSERT_OK(zx_task_suspend(test_process.thread(0), &thread_suspend_token));

  // When we release the process token, the thread should remain suspended.
  ASSERT_OK(zx_handle_close(process_suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_RUNNING, ZX_ERR_TIMED_OUT));

  // Now close the thread token and it should resume.
  ASSERT_OK(zx_handle_close(thread_suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_RUNNING, ZX_OK));

  ASSERT_NO_FAILURES(test_process.StopProcess());
}

TEST(ProcessTest, SuspendThreadThenProcess) {
  TestProcess test_process;
  ASSERT_NO_FAILURES(test_process.CreateProcess());
  ASSERT_NO_FAILURES(test_process.CreateThread());
  ASSERT_NO_FAILURES(test_process.StartProcess());

  zx_handle_t thread_suspend_token;
  ASSERT_OK(zx_task_suspend(test_process.thread(0), &thread_suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_SUSPENDED, ZX_OK));

  zx_handle_t process_suspend_token;
  ASSERT_OK(zx_task_suspend(test_process.process(), &process_suspend_token));

  ASSERT_OK(zx_handle_close(process_suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_RUNNING, ZX_ERR_TIMED_OUT));

  ASSERT_OK(zx_handle_close(thread_suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_RUNNING, ZX_OK));

  ASSERT_NO_FAILURES(test_process.StopProcess());
}

TEST(ProcessTest, SuspendThreadAndProcessBeforeStartingProcess) {
  TestProcess test_process;

  // Create and immediately suspend the process and thread.
  ASSERT_NO_FAILURES(test_process.CreateProcess());
  zx_handle_t process_suspend_token;
  ASSERT_OK(zx_task_suspend(test_process.process(), &process_suspend_token));

  ASSERT_NO_FAILURES(test_process.CreateThread());
  zx_handle_t thread_suspend_token;
  ASSERT_OK(zx_task_suspend(test_process.thread(0), &thread_suspend_token));

  ASSERT_NO_FAILURES(test_process.StartProcess());
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_SUSPENDED, ZX_OK));

  // Resume the process, thread should stay suspended.
  ASSERT_OK(zx_handle_close(process_suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_RUNNING, ZX_ERR_TIMED_OUT));

  ASSERT_OK(zx_handle_close(thread_suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_RUNNING, ZX_OK));

  ASSERT_NO_FAILURES(test_process.StopProcess());
}

TEST(ProcessTest, SuspendTwice) {
  TestProcess test_process;
  ASSERT_NO_FAILURES(test_process.CreateProcess());
  ASSERT_NO_FAILURES(test_process.CreateThread());
  ASSERT_NO_FAILURES(test_process.StartProcess());

  zx_handle_t suspend_tokens[2];
  ASSERT_OK(zx_task_suspend(test_process.process(), &suspend_tokens[0]));
  ASSERT_OK(zx_task_suspend(test_process.process(), &suspend_tokens[1]));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_SUSPENDED, ZX_OK));

  ASSERT_OK(zx_handle_close(suspend_tokens[0]));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_RUNNING, ZX_ERR_TIMED_OUT));

  ASSERT_OK(zx_handle_close(suspend_tokens[1]));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_RUNNING, ZX_OK));

  ASSERT_NO_FAILURES(test_process.StopProcess());
}

TEST(ProcessTest, SuspendTwiceBeforeCreatingThreads) {
  TestProcess test_process;
  ASSERT_NO_FAILURES(test_process.CreateProcess());

  zx_handle_t suspend_tokens[2];
  ASSERT_OK(zx_task_suspend(test_process.process(), &suspend_tokens[0]));
  ASSERT_OK(zx_task_suspend(test_process.process(), &suspend_tokens[1]));

  ASSERT_NO_FAILURES(test_process.CreateThread());
  ASSERT_NO_FAILURES(test_process.StartProcess());
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_SUSPENDED, ZX_OK));

  ASSERT_OK(zx_handle_close(suspend_tokens[0]));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_RUNNING, ZX_ERR_TIMED_OUT));

  ASSERT_OK(zx_handle_close(suspend_tokens[1]));
  ASSERT_TRUE(test_process.WaitForThreadSignal(0, ZX_THREAD_RUNNING, ZX_OK));

  ASSERT_NO_FAILURES(test_process.StopProcess());
}

// This test isn't super reliable since it has to try to suspend and resume while a thread is in
// the small window while it's dying but before it's dead, but there doesn't seem to be a way
// to deterministically hit that window so unfortunately this is the best we can do.
//
// In the expected case this test will always succeed, but if there is an underlying bug it
// will occasionally fail, so if this test begins to show flakiness it likely represents a real
// bug.
TEST(ProcessTest, SuspendWithDyingThread) {
  TestProcess test_process;
  zx::channel control_channel;
  ASSERT_NO_FAILURES(test_process.CreateProcess());
  ASSERT_NO_FAILURES(test_process.CreateThread());
  ASSERT_NO_FAILURES(test_process.CreateThread());
  ASSERT_NO_FAILURES(test_process.CreateThread());
  ASSERT_NO_FAILURES(test_process.StartProcessWithControl(control_channel.reset_and_get_address()));

  // Tell the main process thread to exit. Hopefully we can catch it in the DYING state.
  ASSERT_OK(mini_process_cmd_send(control_channel.get(), MINIP_CMD_THREAD_EXIT));

  // Now suspend the process and make sure it still works on the live threads.
  // Don't check thread 0 because that's the one that's exiting.
  zx_handle_t suspend_token;
  ASSERT_OK(zx_task_suspend(test_process.process(), &suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(1, ZX_THREAD_SUSPENDED, ZX_OK));
  ASSERT_TRUE(test_process.WaitForThreadSignal(2, ZX_THREAD_SUSPENDED, ZX_OK));

  ASSERT_OK(zx_handle_close(suspend_token));
  ASSERT_TRUE(test_process.WaitForThreadSignal(1, ZX_THREAD_RUNNING, ZX_OK));
  ASSERT_TRUE(test_process.WaitForThreadSignal(2, ZX_THREAD_RUNNING, ZX_OK));

  ASSERT_NO_FAILURES(test_process.StopProcess());
}

template <typename InfoT>
static void TestProcessGetInfoRuntime(const uint32_t topic) {
  TestProcess test_process;
  ASSERT_NO_FAILURES(test_process.CreateProcess());
  ASSERT_NO_FAILURES(test_process.CreateThread());

  // Get info before the threads start running.
  InfoT info;
  size_t actual = 0;
  size_t avail = 0;
  ASSERT_OK(
      zx_object_get_info(test_process.process(), topic, &info, sizeof(info), &actual, &avail));
  ASSERT_EQ(info.cpu_time, 0);
  ASSERT_EQ(info.queue_time, 0);
  EXPECT_EQ(actual, 1);
  EXPECT_EQ(avail, 1);

  ASSERT_NO_FAILURES(test_process.StartProcess());

  test_process.WaitForThreadSignal(0, ZX_THREAD_RUNNING, ZX_OK);

  // We are occasionally fast enough reading the thread info to see it before it gets scheduled.
  // Loop until we see the values we are looking for.
  while (info.cpu_time == 0 || info.queue_time == 0) {
    ASSERT_OK(
        zx_object_get_info(test_process.process(), topic, &info, sizeof(info), nullptr, nullptr));
  }

  EXPECT_GT(info.cpu_time, 0);
  EXPECT_GT(info.queue_time, 0);

  ASSERT_OK(zx_task_kill(test_process.process()));
  ASSERT_OK(
      zx_object_wait_one(test_process.process(), ZX_TASK_TERMINATED, ZX_TIME_INFINITE, nullptr));

  // Read info after process death, ensure it does not change.
  ASSERT_OK(
      zx_object_get_info(test_process.process(), topic, &info, sizeof(info), nullptr, nullptr));
  EXPECT_GT(info.cpu_time, 0);
  EXPECT_GT(info.queue_time, 0);

  zx_info_task_runtime_t info2;
  ASSERT_OK(
      zx_object_get_info(test_process.process(), topic, &info2, sizeof(info2), nullptr, nullptr));
  EXPECT_EQ(info.cpu_time, info2.cpu_time);
  EXPECT_EQ(info.queue_time, info2.queue_time);

  ASSERT_NO_FAILURES(test_process.StopProcess());
}

TEST(ProcessTest, GetInfoRuntime) {
  TestProcessGetInfoRuntime<zx_info_task_runtime_t>(ZX_INFO_TASK_RUNTIME);
}

TEST(ProcessTest, GetInfoRuntimeV1) {
  TestProcessGetInfoRuntime<zx_info_task_runtime_v1_t>(ZX_INFO_TASK_RUNTIME_V1);
}

// A stress test designed to create a race where one thread is creating a process while another
// thread is killing its parent job.
TEST(ProcessTest, CreateAndKillJobRaceStress) {
  constexpr zx_duration_t kTestDuration = ZX_SEC(1);
  srand(4);

  struct args_t {
    std::atomic<bool>* keep_running;
    std::atomic<zx_handle_t>* job;
  };

  // Repeatedly create and kill a job.
  auto killer_thread = [](void* arg) -> int {
    auto [job, keep_running] = *reinterpret_cast<args_t*>(arg);
    while (keep_running->load()) {
      zx_handle_t handle = ZX_HANDLE_INVALID;
      zx_status_t status = zx_job_create(zx_job_default(), 0, &handle);
      if (status != ZX_OK) {
        return status;
      }
      job->store(handle);

      // Give the creator threads an opportunity to get the handle before killing the job.
      zx_nanosleep(ZX_MSEC(10));

      status = zx_task_kill(handle);
      zx_handle_close(handle);
      if (status != ZX_OK) {
        return status;
      }
      handle = ZX_HANDLE_INVALID;
      job->store(handle);
    }
    return ZX_OK;
  };

  // Repeatedly create a process.
  auto creator_thread = [](void* arg) -> int {
    auto [job, keep_running] = *reinterpret_cast<args_t*>(arg);
    constexpr const char kName[] = "create-and-kill";
    while (keep_running->load()) {
      zx_handle_t handle = job->load();
      if (handle == ZX_HANDLE_INVALID) {
        continue;
      }

      zx_handle_t proc = ZX_HANDLE_INVALID;
      zx_handle_t vmar = ZX_HANDLE_INVALID;
      zx_status_t status =
          zx_process_create(handle, "create-and-kill", sizeof(kName) - 1, 0, &proc, &vmar);

      // We're racing with the killer_thread so it's entirely possible for zx_process_create
      // to fail with ZX_ERR_BAD_HANDLE or ZX_ERR_BAD_STATE. Just ignore those.
      if (status != ZX_OK && status != ZX_ERR_BAD_HANDLE && status != ZX_ERR_BAD_STATE) {
        return status;
      }
      zx_handle_close(proc);
      proc = ZX_HANDLE_INVALID;
      zx_handle_close(vmar);
      vmar = ZX_HANDLE_INVALID;
    }

    return ZX_OK;
  };

  std::atomic<bool> keep_running(true);
  std::atomic<zx_handle_t> job(ZX_HANDLE_INVALID);
  args_t args{&keep_running, &job};

  thrd_t killer;
  ASSERT_EQ(thrd_create(&killer, killer_thread, &args), thrd_success);

  constexpr unsigned kNumCreators = 4;
  thrd_t creators[kNumCreators];
  for (auto& t : creators) {
    ASSERT_EQ(thrd_create(&t, creator_thread, &args), thrd_success);
  }

  zx_nanosleep(zx_deadline_after(kTestDuration));

  keep_running.store(false);
  for (auto& t : creators) {
    int res;
    ASSERT_EQ(thrd_join(t, &res), thrd_success);
    ASSERT_OK(res);
  }

  int res;
  ASSERT_EQ(thrd_join(killer, &res), thrd_success);
  ASSERT_OK(res);

  zx_handle_close(args.job->load());
}

TEST(ProcessTest, ProcessStartWriteThreadState) {
  zx_handle_t proc;
  zx_handle_t vmar;
  ASSERT_OK(zx_process_create(zx_job_default(), "ttp", 3u, 0, &proc, &vmar));

  zx_handle_t thread;
  ASSERT_OK(zx_thread_create(proc, "th", 2u, 0u, &thread));

  // Suspend the thread before it starts.
  zx_handle_t token;
  ASSERT_OK(zx_task_suspend(thread, &token));

  zx_handle_t event;
  ASSERT_OK(zx_event_create(0u, &event));

  zx_handle_t minip_chn;
  ASSERT_OK(start_mini_process_etc(proc, thread, vmar, event, false, &minip_chn));

  // Get a known word into memory to point the thread pointer at.  It would
  // be simpler and sufficient for the purpose of this test just to check
  // the value of the thread register itself for a known bit pattern.  But
  // on older x86 hardware there is no unprivileged way to read the register
  // directly (rdfsbase) and it can only be used in a memory access.
  const uintptr_t kCheckValue = MINIP_THREAD_POINTER_CHECK_VALUE;
  zx_handle_t vmo;
  ASSERT_OK(zx_vmo_create(zx_system_get_page_size(), 0, &vmo));
  ASSERT_OK(zx_vmo_write(vmo, &kCheckValue, 0, sizeof(kCheckValue)));
  uintptr_t addr;
  ASSERT_OK(zx_vmar_map(vmar, ZX_VM_PERM_READ, 0, vmo, 0, zx_system_get_page_size(), &addr));
  EXPECT_OK(zx_handle_close(vmo));

  // Wait for the new thread to reach quiescent suspended state.
  zx_signals_t signals;
  EXPECT_OK(zx_object_wait_one(thread, ZX_THREAD_SUSPENDED, ZX_TIME_INFINITE, &signals));
  EXPECT_TRUE(signals & ZX_THREAD_SUSPENDED);

  // Fetch the initial register state.
  zx_thread_state_general_regs_t regs;
  ASSERT_OK(zx_thread_read_state(thread, ZX_THREAD_STATE_GENERAL_REGS, &regs, sizeof(regs)));
  EXPECT_EQ(regs.*kThreadRegister, 0);

  // Write it back with the thread register pointed at our memory.
  regs.*kThreadRegister = addr;
  ASSERT_OK(zx_thread_write_state(thread, ZX_THREAD_STATE_GENERAL_REGS, &regs, sizeof(regs)));

  // Now let the thread run again.
  EXPECT_OK(zx_handle_close(token));

  // Complete the startup handshake that had to be delayed while the thread
  // was suspended.
  EXPECT_OK(mini_process_wait_for_ack(minip_chn));

  // Now have it read from its thread pointer and check the value.
  EXPECT_OK(mini_process_cmd(minip_chn, MINIP_CMD_CHECK_THREAD_POINTER, nullptr));

  // All done!
  EXPECT_EQ(mini_process_cmd(minip_chn, MINIP_CMD_EXIT_NORMAL, nullptr), ZX_ERR_PEER_CLOSED);

  EXPECT_OK(zx_handle_close(proc));
  EXPECT_OK(zx_handle_close(vmar));
  EXPECT_OK(zx_handle_close(thread));
}

// This checks for lock ordering violations between the acquiring the process dispatcher lock and
// the process handle table lock.
//
// Given that the 'standard' lock ordering is handle table and then dispatcher, this is really
// testing that ZX_INFO_PROCESS_VMOS doesn't acquire in the other order.
//
// object_wait_async and port_cancel are used as syscalls that will allow us to hold the handle
// table lock whilst operating on a process in a way that requires grabbing the dispatcher lock.
// This represents the 'correct' ordering.
TEST(ProcessTest, ProcessWaitAsyncCancelSelf) {
  // Start up a thread in a mini-process that is given a copy of the process handle and will
  // create a port and infinitely loop doing process.wait_async(port) + port.cancel(process)
  zx::process process;
  zx::vmar vmar;

  constexpr const char kProcessName[] = "test_process";
  ASSERT_OK(zx::process::create(*zx::job::default_job(), kProcessName, sizeof(kProcessName), 0,
                                &process, &vmar));

  zx::thread thread;

  constexpr const char kThreadName[] = "test_thread";
  ASSERT_OK(zx::thread::create(process, kThreadName, sizeof(kThreadName), 0, &thread));

  zx::channel cntrl_channel;
  zx::process process_dup;
  ASSERT_OK(process.duplicate(ZX_RIGHT_SAME_RIGHTS, &process_dup));
  ASSERT_OK(start_mini_process_etc(process.get(), thread.get(), vmar.get(), process_dup.release(),
                                   true, cntrl_channel.reset_and_get_address()));

  ASSERT_OK(mini_process_cmd_send(cntrl_channel.get(), MINIP_CMD_WAIT_ASYNC_CANCEL));

  // Call get_info several times on the process. We're trying to trigger a race that will cause a
  // kernel deadlock. In testing with the deadlock present 10000 iterations would reliably trigger
  // and does not take very long to run.
  zx_info_vmo_t vmo;
  size_t actual;
  size_t available;
  for (int i = 0; i < 10000; i++) {
    ASSERT_OK(process.get_info(ZX_INFO_PROCESS_VMOS, &vmo, sizeof(vmo), &actual, &available));
  }
  // We need to explicitly kill the process tree as we gave the mini-process a handle to itself,
  // so it is able to keep itself alive when we close our copies of the handles otherwise.
  ASSERT_OK(process.kill());
  zx_signals_t pending;
  ASSERT_OK(process.wait_one(ZX_TASK_TERMINATED, zx::time::infinite(), &pending));
}

TEST(ProcessTest, ForbidDestroyRootVmar) {
  zx::process process;
  zx::vmar vmar;

  constexpr const char kProcessName[] = "test_process";
  ASSERT_OK(zx::process::create(*zx::job::default_job(), kProcessName, sizeof(kProcessName), 0,
                                &process, &vmar));

  // Attempt to destroy the vmar. We accept this call either succeeding or not being supported, as
  // long as our future get_info call doesn't cause a kernel panic.
  zx_status_t result = vmar.destroy();
  ASSERT_TRUE(result == ZX_OK || result == ZX_ERR_NOT_SUPPORTED);

  // Query the address space.
  zx_info_maps_t map;
  size_t actual, avail;
  ASSERT_OK(process.get_info(ZX_INFO_PROCESS_MAPS, &map, sizeof(map), &actual, &avail));
}

TEST(ProcessTest, ProcessHwTraceContextIdProperty) {
  // Handle whether or not the needed syscall is enabled.
  // It is only enabled with the "kernel.enable-debugging-syscalls=true"
  // kernel command line argument. Unsupported architectures act as-if the
  // syscall is disabled.
  bool debugging_syscalls_enabled = false;

#ifdef __x86_64__
  {
    zx_status_t status;
    char too_small;
    status = zx_object_get_property(zx_process_self(), ZX_PROP_PROCESS_HW_TRACE_CONTEXT_ID,
                                    &too_small, sizeof(too_small));
    if (status != ZX_ERR_NOT_SUPPORTED) {
      EXPECT_EQ(status, ZX_ERR_BUFFER_TOO_SMALL, "unexpected status: %d", status);
      // If we didn't get ZX_ERR_NOT_SUPPORTED, then the needed support is present and enabled.
      debugging_syscalls_enabled = true;
    }
  }
#endif

  auto supported_read_prop_test = [](const char* test_name) {
    zx_status_t status;
    uintptr_t prop_aspace = 0;
    status = zx_object_get_property(zx_process_self(), ZX_PROP_PROCESS_HW_TRACE_CONTEXT_ID,
                                    &prop_aspace, sizeof(prop_aspace));
    EXPECT_EQ(status, ZX_OK, "%s: zx_object_get_property failed: %d", test_name, status);
    // We can't verify the value, but we can at least check it's reasonable.
    EXPECT_NE(prop_aspace, 0, "%s", test_name);
    EXPECT_EQ(prop_aspace & (zx_system_get_page_size() - 1), 0, "%s", test_name);
  };
  auto unsupported_read_prop_test = [](const char* test_name) {
    zx_status_t status;
    uintptr_t prop_aspace;
    status = zx_object_get_property(zx_process_self(), ZX_PROP_PROCESS_HW_TRACE_CONTEXT_ID,
                                    &prop_aspace, sizeof(prop_aspace));
    EXPECT_EQ(status, ZX_ERR_NOT_SUPPORTED, "%s: unexpected status: %d", test_name, status);
  };

  fit::function<void(const char*)> read_prop_test;
  printf("Note: debugging syscalls are %s\n", debugging_syscalls_enabled ? "enabled" : "disabled");
  if (debugging_syscalls_enabled) {
    read_prop_test = std::move(supported_read_prop_test);
  } else {
    read_prop_test = std::move(unsupported_read_prop_test);
  }

  // Verify obtaining the context ID works through the stages of process
  // creation/death.
  static const char name[] = "context-id-test";
  {
    zx::process proc;
    zx::vmar vmar;

    ASSERT_OK(
        zx::process::create(*zx::job::default_job(), name, sizeof(name) - 1, 0, &proc, &vmar));
    read_prop_test("process created");

    zx::thread thread;
    ASSERT_OK(zx::thread::create(proc, name, sizeof(name) - 1, 0u, &thread));
    zx::event event;
    ASSERT_OK(zx::event::create(0u, &event));
    zx::channel cmd_channel;
    ASSERT_OK(start_mini_process_etc(proc.get(), thread.get(), vmar.get(), event.get(), true,
                                     cmd_channel.reset_and_get_address()));
    ASSERT_OK(mini_process_cmd(cmd_channel.get(), MINIP_CMD_ECHO_MSG, nullptr));
    read_prop_test("process live");

    ASSERT_EQ(mini_process_cmd(cmd_channel.get(), MINIP_CMD_EXIT_NORMAL, nullptr),
              ZX_ERR_PEER_CLOSED);
    zx_signals_t signals;
    ASSERT_OK(proc.wait_one(ZX_TASK_TERMINATED, zx::time::infinite(), &signals));
    ASSERT_EQ(signals, ZX_TASK_TERMINATED);
    read_prop_test("process dead");
  }

  // The property is read-only.
  {
    uintptr_t prop_to_set = 0;
    zx_status_t status = zx_object_set_property(
        zx_process_self(), ZX_PROP_PROCESS_HW_TRACE_CONTEXT_ID, &prop_to_set, sizeof(prop_to_set));
    EXPECT_EQ(status, ZX_ERR_INVALID_ARGS, "unexpected status: %d", status);
  }
}

TEST(ProcessTest, InfoProcessNoProcessHandles) {
  // Create process with a thread
  zx::process process;
  zx::thread thread;
  zx::vmar vmar;

  zx::unowned<zx::job> job = zx::job::default_job();

  ASSERT_OK(zx::process::create(*job, "mini-p", 3u, 0, &process, &vmar));
  ASSERT_OK(zx::thread::create(process, "mini-p", 2u, 0u, &thread));

  zx::event event;
  ASSERT_OK(zx::event::create(0u, &event));

  zx_handle_t cmd_channel;
  EXPECT_OK(start_mini_process_etc(process.get(), thread.get(), vmar.get(), event.get(), true,
                                   &cmd_channel));

  // Get our KOID.
  zx_info_handle_basic_t handle_info = {};
  size_t actual = 0;
  size_t avail = 0;
  ASSERT_OK(
      process.get_info(ZX_INFO_HANDLE_BASIC, &handle_info, sizeof(handle_info), &actual, &avail));
  EXPECT_EQ(actual, 1);
  EXPECT_EQ(avail, 1);
  const zx_koid_t process_koid = handle_info.koid;

  // Check that our handle count is one.
  zx_info_handle_count_t handle_count = {};
  ASSERT_OK(
      process.get_info(ZX_INFO_HANDLE_COUNT, &handle_count, sizeof(handle_count), &actual, &avail));
  EXPECT_EQ(actual, 1);
  EXPECT_EQ(avail, 1);
  EXPECT_EQ(handle_count.handle_count, 1);

  // Close the handle, the runnable thread will keep the process alive.
  process.reset();

  // Query the job and make sure the process is still listed.
  std::vector<zx_koid_t> children;
  do {
    ASSERT_OK(job->get_info(ZX_INFO_JOB_PROCESSES, children.data(),
                            sizeof(zx_koid_t) * children.size(), &actual, &avail));
    children.resize(avail);
  } while (avail > actual);

  EXPECT_TRUE(std::any_of(children.begin(), children.end(),
                          [process_koid](zx_koid_t koid) { return koid == process_koid; }));

  // Now retrieve the handle.
  zx::process original_process;
  EXPECT_OK(job->get_child(process_koid, ZX_RIGHT_SAME_RIGHTS, &original_process));

  // Cleanup
  EXPECT_EQ(mini_process_cmd(cmd_channel, MINIP_CMD_EXIT_NORMAL, nullptr), ZX_ERR_PEER_CLOSED);
}

}  // namespace
