// 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 <lib/test-exceptions/exception-catcher.h>
#include <lib/zx/object.h>
#include <lib/zx/time.h>
#include <stdio.h>
#include <zircon/syscalls/debug.h>

#include <utility>

namespace test_exceptions {

namespace {

template <typename T>
zx_status_t GetKoid(const zx::object<T>& object, zx_koid_t* koid) {
  zx_info_handle_basic_t info;
  zx_status_t status = object.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
  if (status != ZX_OK) {
    *koid = ZX_KOID_INVALID;
    return status;
  }
  *koid = info.koid;
  return ZX_OK;
}

// Returns true if |info| matches the given koids, with ZX_KOID_INVALID
// matching anything.
bool ExceptionMatches(const zx_exception_info_t& info, zx_koid_t pid, zx_koid_t tid) {
  return (pid == ZX_KOID_INVALID || pid == info.pid) && (tid == ZX_KOID_INVALID || tid == info.tid);
}

}  // namespace

__EXPORT
ExceptionCatcher::~ExceptionCatcher() {
  zx_status_t status = Stop();
  ZX_ASSERT_MSG(status == ZX_OK, "ExceptionCatcher::Stop() failed (%s)",
                zx_status_get_string(status));
}

__EXPORT
zx_status_t ExceptionCatcher::Stop() {
  // Move these to local vars so they always get cleared when we return.
  zx::channel exception_channel = std::move(exception_channel_);
  auto active_exceptions = std::move(active_exceptions_);

  bool exceptions_in_channel = false;
  if (exception_channel) {
    zx_status_t status = exception_channel.wait_one(ZX_CHANNEL_READABLE, zx::time(0), nullptr);
    if (status == ZX_OK) {
      exceptions_in_channel = true;
    } else if (status != ZX_ERR_TIMED_OUT) {
      return status;
    }
  }

  return (active_exceptions.empty() && !exceptions_in_channel) ? ZX_OK : ZX_ERR_CANCELED;
}

__EXPORT
zx::result<zx::exception> ExceptionCatcher::ExpectException() {
  return ExpectException(ZX_KOID_INVALID, ZX_KOID_INVALID);
}

__EXPORT
zx::result<zx::exception> ExceptionCatcher::ExpectException(const zx::thread& thread) {
  zx_koid_t tid;
  zx_status_t status = GetKoid(thread, &tid);
  if (status != ZX_OK) {
    return zx::error(status);
  }
  return ExpectException(ZX_KOID_INVALID, tid);
}

__EXPORT
zx::result<zx::exception> ExceptionCatcher::ExpectException(const zx::process& process) {
  zx_koid_t pid;
  zx_status_t status = GetKoid(process, &pid);
  if (status != ZX_OK) {
    return zx::error(status);
  }
  return ExpectException(pid, ZX_KOID_INVALID);
}

zx::result<zx::exception> ExceptionCatcher::ExpectException(zx_koid_t pid, zx_koid_t tid) {
  // First check if we've already seen this exception on a previous call.
  for (auto iter = active_exceptions_.begin(); iter != active_exceptions_.end(); ++iter) {
    if (ExceptionMatches(iter->info, pid, tid)) {
      auto exception = zx::ok(std::move(iter->exception));
      active_exceptions_.erase(iter);
      return std::move(exception);
    }
  }

  while (1) {
    zx_signals_t signals = 0;
    zx_status_t status = exception_channel_.wait_one(ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED,
                                                     zx::time::infinite(), &signals);
    if (status != ZX_OK) {
      return zx::error(status);
    }
    if (!(signals & ZX_CHANNEL_READABLE)) {
      return zx::error(ZX_ERR_PEER_CLOSED);
    }

    zx_exception_info_t info;
    zx::exception exception;
    status = exception_channel_.read(0, &info, exception.reset_and_get_address(), sizeof(info), 1,
                                     nullptr, nullptr);
    if (status != ZX_OK) {
      return zx::error(status);
    }

    if (ExceptionMatches(info, pid, tid)) {
      return zx::ok(std::move(exception));
    }
    active_exceptions_.push_back(ActiveException{info, std::move(exception)});
  }
}

}  // namespace test_exceptions
