// 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/zx/exception.h>
#include <stddef.h>
#include <stdint.h>
#include <zircon/syscalls/port.h>

#include <utility>

#include <test-utils/test-utils.h>
#include <zxtest/zxtest.h>

#include "debugger.h"
#include "inferior-control.h"
#include "inferior.h"
#include "utils.h"

namespace {

struct suspend_on_start_test_state_t {
  int started_threads = 0;
};

void suspend_on_start_test_handler(inferior_data_t* data, const zx_port_packet_t* packet,
                                   void* handler_arg) {
  auto* test_state = reinterpret_cast<suspend_on_start_test_state_t*>(handler_arg);

  // This test is supposed to only get an exception and nothing else.
  zx_info_handle_basic_t basic_info;
  zx_status_t status = zx_object_get_info(data->exception_channel, ZX_INFO_HANDLE_BASIC,
                                          &basic_info, sizeof(basic_info), nullptr, nullptr);
  ASSERT_EQ(status, ZX_OK);
  ASSERT_EQ(basic_info.koid, packet->key);

  zx::exception exception;
  zx_exception_info_t info;
  uint32_t num_bytes = sizeof(info);
  uint32_t num_handles = 1;
  status = zx_channel_read(data->exception_channel, 0, &info, exception.reset_and_get_address(),
                           num_bytes, num_handles, nullptr, nullptr);
  ASSERT_EQ(status, ZX_OK);

  switch (info.type) {
    case ZX_EXCP_THREAD_STARTING:
      printf("thread %lu starting\n", info.tid);
      // We only want to resume the first thread.
      test_state->started_threads++;
      break;
    case ZX_EXCP_THREAD_EXITING:
      printf("thread %lu exiting\n", info.tid);
      ASSERT_NO_FATAL_FAILURE(handle_thread_exiting(data->inferior, &info, std::move(exception)));
      break;
    default:
      printf("Unexpected exception %s (%u) on thread %lu\n", tu_exception_to_string(info.type),
             info.type, info.tid);
      break;
  }
}

}  // namespace

TEST(SuspendOnStartTests, SuspendOnStartTest) {
  springboard_t* sb;
  zx_handle_t inferior, channel;
  ASSERT_NO_FATAL_FAILURE(setup_inferior(kTestSuspendOnStart, &sb, &inferior, &channel));

  // Attach to the inferior now because we want to see thread starting
  // exceptions.
  zx_handle_t port = ZX_HANDLE_INVALID;
  EXPECT_EQ(zx_port_create(0, &port), ZX_OK);
  size_t max_threads = 2;
  inferior_data_t* inferior_data = attach_inferior(inferior, port, max_threads);

  suspend_on_start_test_state_t test_state = {};
  thrd_t wait_inf_thread =
      start_wait_inf_thread(inferior_data, suspend_on_start_test_handler, &test_state);
  EXPECT_NE(port, ZX_HANDLE_INVALID);

  ASSERT_NO_FATAL_FAILURE(start_inferior(sb));

  // The remaining testing happens at this point as threads start.
  // This testing is done in |suspend_on_start_test_handler()|.

  ASSERT_NO_FATAL_FAILURE(shutdown_inferior(channel, inferior));

  // Stop the waiter thread before closing the port that it's waiting on.
  join_wait_inf_thread(wait_inf_thread);

  detach_inferior(inferior_data, true);

  zx_handle_close(port);
  zx_handle_close(channel);
  zx_handle_close(inferior);
}
