// Copyright 2019 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 <assert.h>
#include <lib/zx/channel.h>
#include <lib/zx/event.h>
#include <lib/zx/handle.h>
#include <lib/zx/job.h>
#include <lib/zx/process.h>
#include <lib/zx/thread.h>
#include <lib/zx/vmar.h>
#include <zircon/syscalls/policy.h>

#include <iterator>

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

// This file contains tests that verify the behavior of the default exception handler, that is, the
// in-kernel exception handler that's used when no usermode exception handler is installed.
//
// To ensure these tests verify the unhandle exception path, they should be run on a system that has
// no usermode exception handlers.  Standalone core-tests provides such an environment.  See also
// |VerifyNoExceptionHandler|.

namespace {

// Test helper that runs a mini-process in |job| that will execute the command specified by
// |minip_cmd|.  Be sure to call with ASSERT_NO_FAILURES.
//
// See mini-process.h for valid |minip_cmd| values.
//
// Upon success, sets |exit_code| to the process's exit code.  See the ZX_TASK_RETCODE_* constants
// in syscalls/object.h.
void RunMiniProcessTestHelper(const zx::job& job, uint32_t minip_cmd, int64_t* exit_code) {
  zx::vmar vmar;
  zx::process proc;
  static constexpr char kName[] = "unhandled-exception-test";
  ASSERT_OK(zx::process::create(job, kName, sizeof(kName) - 1, 0u, &proc, &vmar));

  zx::thread thread;
  ASSERT_OK(zx::thread::create(proc, kName, sizeof(kName) - 1, 0, &thread));

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

  zx::channel control;
  ASSERT_OK(start_mini_process_etc(proc.get(), thread.release(), vmar.get(), event.release(), true,
                                   control.reset_and_get_address()));
  zx::handle handle;
  ASSERT_STATUS(mini_process_cmd(control.get(), minip_cmd, handle.reset_and_get_address()),
                ZX_ERR_PEER_CLOSED);

  ASSERT_OK(proc.wait_one(ZX_TASK_TERMINATED, zx::time::infinite(), nullptr));

  zx_info_process_t proc_info;
  ASSERT_OK(proc.get_info(ZX_INFO_PROCESS, &proc_info, sizeof(proc_info), nullptr, nullptr));
  ASSERT_TRUE(proc_info.flags & ZX_INFO_PROCESS_FLAG_EXITED);

  *exit_code = proc_info.return_code;
}

// Verfies that the default job has no exception handler.
//
// TODO(maniscalco): We're only checking the default job.  It's entirely possible one of its
// ancestors has an exception channel.  Unfortunately, there is no good way to verify that none in
// the tree have an exception handler.
void VerifyNoExceptionHandler() {
  zx::unowned_job job(zx::job::default_job());
  ASSERT_TRUE(job->is_valid());

  // If we can't install an exception channel, then there must be one already installed.
  zx::channel exception_channel;
  ASSERT_OK(job->create_exception_channel(0, &exception_channel));
}

// Verify that an unhandled exception terminates the process.
TEST(DefaultExceptionHandlerTest, UnhandledHardwareException) {
  if (getenv("NO_CHILD_PROCESS")) {
    ZXTEST_SKIP(
        "Test requires creating a child process and this environment does not support it. "
        "Skipping");
  }
  ASSERT_NO_FAILURES(VerifyNoExceptionHandler());

  zx::job job;
  ASSERT_OK(zx::job::create(*zx::job::default_job(), 0u, &job));

  int64_t exit_code = 0;
  ASSERT_NO_FAILURES(RunMiniProcessTestHelper(job, MINIP_CMD_BUILTIN_TRAP, &exit_code));
  ASSERT_EQ(exit_code, ZX_TASK_RETCODE_EXCEPTION_KILL);
}

// Verify that an unhandled policy exception terminates the process.  Policy exceptions are special
// in that they are generated by the kernel itself rather than the hardware.
TEST(DefaultExceptionHandlerTest, UnhandledPolicyException) {
  if (getenv("NO_CHILD_PROCESS")) {
    ZXTEST_SKIP(
        "Test requires creating a child process and this environment does not support it. "
        "Skipping");
  }
  ASSERT_NO_FAILURES(VerifyNoExceptionHandler());

  zx::job job;
  ASSERT_OK(zx::job::create(*zx::job::default_job(), 0u, &job));

  // Create a job with policy that generates an excpetion when an object is created.
  zx_policy_basic_v2_t policy[] = {
      {ZX_POL_NEW_ANY, ZX_POL_ACTION_ALLOW_EXCEPTION, ZX_POL_OVERRIDE_DENY}};
  ASSERT_OK(job.set_policy(ZX_JOB_POL_ABSOLUTE, ZX_JOB_POL_BASIC_V2, policy,
                           static_cast<uint32_t>(std::size(policy))));

  // Tell the process to create an event.  See that it's killed because the exception is unhandled.
  int64_t exit_code = 0;
  ASSERT_NO_FAILURES(RunMiniProcessTestHelper(job, MINIP_CMD_CREATE_EVENT, &exit_code));
  ASSERT_EQ(exit_code, ZX_TASK_RETCODE_EXCEPTION_KILL);
}

}  // namespace
