// Copyright 2018 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.

#ifndef _ALL_SOURCE
#define _ALL_SOURCE // Enables thrd_create_with_name in <threads.h>.
#endif

#include <stddef.h>
#include <string>
#include <threads.h>
#include <zircon/syscalls/object.h>
#include <zircon/threads.h>
#include <zx/event.h>
#include <zx/process.h>
#include <zx/time.h>

#include "garnet/lib/debugger_utils/jobs.h"
#include "garnet/lib/debugger_utils/threads.h"
#include "garnet/lib/debugger_utils/util.h"
#include "garnet/public/lib/fxl/logging.h"
#include "gtest/gtest.h"

namespace debugger_utils {
namespace {

// Threads should eventually suspend and resume. Leave it to the watchdog
// to handle problems.
constexpr zx::duration kThreadSuspendTimeout = zx::duration::infinite();
constexpr zx::duration kThreadRunningTimeout = zx::duration::infinite();

constexpr size_t kNumTestThreads = 10u;

int ThreadFunction(void* arg) {
  auto keep_running = reinterpret_cast<std::atomic_bool*>(arg);
  while (*keep_running) {
    zx::nanosleep(zx::deadline_after(zx::msec(100)));
  }
  return 0;
}

void ShutdownThreads(const std::vector<thrd_t>& threads,
                     std::atomic_bool* keep_running) {
  *keep_running = false;
  for (auto& thread : threads) {
    int result = thrd_join(thread, NULL);
    FXL_DCHECK(result == thrd_success);
  }
}

bool CreateThreads(size_t num_threads, std::vector<thrd_t>* threads,
                   std::atomic_bool* keep_running) {
  for (size_t i = 0; i < num_threads; ++i) {
    char name[sizeof("thread") + 10];
    snprintf(name, sizeof(name), "thread%zu", i);
    thrd_t thread;
    if (thrd_create_with_name(&thread, ThreadFunction, keep_running, name) !=
        thrd_success) {
      goto Fail;
    }
    threads->push_back(thread);
  }

  return true;

 Fail:
  ShutdownThreads(*threads, keep_running);
  return false;
}

zx_status_t GetThreadState(const zx::thread& thread, uint32_t* state) {
  zx_info_thread_t info;
  auto status = thread.get_info(ZX_INFO_THREAD, &info, sizeof(info),
                                nullptr, nullptr);
  if (status != ZX_OK) {
    return status;
  }
  *state = info.state;
  return ZX_OK;
}

void CheckThreadSuspended(const zx::thread& thread, const char* msg) {
  uint32_t state;
  EXPECT_EQ(ZX_OK, GetThreadState(thread, &state)) << msg;
  EXPECT_EQ(ZX_THREAD_STATE_SUSPENDED, state) << msg;
}

void CheckThreadRunning(const zx::thread& thread, const char* msg) {
  uint32_t state;
  EXPECT_EQ(ZX_OK, GetThreadState(thread, &state)) << msg;
  // Our threads are either running or sleeping.
  EXPECT_TRUE(state == ZX_THREAD_STATE_RUNNING ||
              state == ZX_THREAD_STATE_BLOCKED_SLEEPING) << msg;
}

void WaitThreadsRunning(const std::vector<zx::thread>& threads,
                        const char* msg) {
  for (const auto& thread : threads) {
    EXPECT_EQ(ZX_OK, thread.wait_one(ZX_THREAD_RUNNING | ZX_THREAD_TERMINATED,
                                     zx::deadline_after(kThreadRunningTimeout),
                                     nullptr)) << msg;
    CheckThreadRunning(thread, msg);
  }
}

TEST(Threads, WithThreadSuspended) {
  std::atomic_bool keep_running{true};
  std::vector<thrd_t> threads;
  std::vector<zx::thread> zx_threads;

  ASSERT_TRUE(CreateThreads(1u, &threads, &keep_running));

  zx_threads.push_back(zx::thread(thrd_get_zx_handle(threads[0])));
  WaitThreadsRunning(zx_threads, "pre-suspend");

  EXPECT_EQ(ZX_OK, WithThreadSuspended(zx_threads[0], kThreadSuspendTimeout,
                                       [] (const zx::thread& thread) -> zx_status_t {
    CheckThreadSuspended(thread, "inside WithThreadSuspended");
    return ZX_OK;
  }));

  // When a thread's suspend token is closed it does not necessarily
  // return to the RUNNING state immediately,
  WaitThreadsRunning(zx_threads, "post-suspend");

  // Release the handle as it will be closed elsewhere.
  EXPECT_NE(ZX_HANDLE_INVALID, zx_threads[0].release());

  ShutdownThreads(threads, &keep_running);
}

TEST(Threads, WithAllThreadsSuspended) {
  std::atomic_bool keep_running{true};
  std::vector<thrd_t> threads;
  std::vector<zx::thread> zx_threads;

  ASSERT_TRUE(CreateThreads(kNumTestThreads, &threads, &keep_running));

  for (const auto& thread : threads) {
    zx_threads.push_back(zx::thread(thrd_get_zx_handle(thread)));
  }
  WaitThreadsRunning(zx_threads, "pre-suspend");

  EXPECT_EQ(ZX_OK, WithAllThreadsSuspended(
      zx_threads, kThreadSuspendTimeout,
      [&zx_threads] (const zx::thread& thread) -> zx_status_t {
    for (const auto& t : zx_threads) {
      CheckThreadSuspended(t, "inside WithAllThreadsSuspended");
    }
    return ZX_OK;
  }));

  // When a thread's suspend token is closed it does not necessarily
  // return to the RUNNING state immediately.
  WaitThreadsRunning(zx_threads, "post-suspend");

  // Release the handles as they will be closed elsewhere.
  for (auto& thread : zx_threads) {
    EXPECT_NE(ZX_HANDLE_INVALID, thread.release());
  }

  ShutdownThreads(threads, &keep_running);
}

}  // namespace
}  // namespace debugger_utils
