// 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.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) {
  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) {
  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
