// Copyright 2016 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 <errno.h>
#include <lib/fit/defer.h>
#include <lib/zx/thread.h>
#include <sched.h>
#include <threads.h>
#include <zircon/syscalls.h>
#include <zircon/threads.h>

#include <thread>

#include <zxtest/zxtest.h>

namespace {

TEST(C11ThreadTest, ThreadLocalErrno) {
  constexpr int kNumThreads = 4;
  thrd_t thread[kNumThreads];

  struct Args {
    int thread_number;
    int final_errno;
  } args[kNumThreads];

  auto ThreadLocalHelper = [](void* arg) -> int {
    auto args = static_cast<Args*>(arg);
    errno = args->thread_number;
    zx::nanosleep(zx::deadline_after(zx::msec(100)));
    args->final_errno = errno;

    return args->thread_number;
  };

  for (int i = 0; i < kNumThreads; ++i) {
    args[i].thread_number = i;
    ASSERT_EQ(thrd_success,
              thrd_create_with_name(&thread[i], ThreadLocalHelper, &args[i], "c11 thread test"));
  }
  for (int i = 0; i < kNumThreads; ++i) {
    int return_value = 99;
    ASSERT_EQ(thrd_join(thread[i], &return_value), thrd_success);
    ASSERT_EQ(return_value, i);
    ASSERT_EQ(args[i].final_errno, i);
  }
}

TEST(C11ThreadTest, NullNameThreadShouldSucceed) {
  auto NameHelper = [](void* arg) -> int { return 0; };

  constexpr auto kNullArg = nullptr;
  constexpr auto kNullName = nullptr;
  constexpr int* kIgnoreRet = nullptr;
  thrd_t thread;
  ASSERT_EQ(thrd_create_with_name(&thread, NameHelper, kNullArg, kNullName), thrd_success);
  ASSERT_EQ(thrd_join(thread, kIgnoreRet), thrd_success);
}

TEST(C11ThreadTest, CreateAndVerifyThreadHandle) {
  constexpr int kRandomRet = 5;

  auto ThreadHandleHelper = [](void* arg) -> int {
    std::atomic<bool>* keep_running = static_cast<std::atomic<bool>*>(arg);
    while (*keep_running) {
      zx::nanosleep(zx::time::infinite_past());
    }
    return kRandomRet;
  };

  thrd_t thread;
  std::atomic<bool> keep_running = true;
  ASSERT_EQ(thrd_create(&thread, ThreadHandleHelper, &keep_running), thrd_success);
  zx_handle_t handle = thrd_get_zx_handle(thread);
  ASSERT_NE(handle, ZX_HANDLE_INVALID, "got invalid thread handle");
  // Prove this is a valid handle by duplicating it.
  zx_handle_t dup_handle;
  ASSERT_OK(zx_handle_duplicate(handle, ZX_RIGHT_SAME_RIGHTS, &dup_handle));
  ASSERT_OK(zx_handle_close(dup_handle), "failed to close duplicate handle");
  keep_running = false;
  int return_value;
  ASSERT_EQ(thrd_join(thread, &return_value), thrd_success);
  ASSERT_EQ(return_value, kRandomRet, "Incorrect return from thread");
}

// Not really C11 threads, but <zircon/threads.h> declares it and no better
// place for the test really.
TEST(CppThreadTest, CreateAndVerifyThreadHandle) {
  std::atomic<bool> keep_running = true;
  std::thread thread([&keep_running]() {
    while (keep_running.load()) {
      zx::nanosleep(zx::time::infinite_past());
    }
  });
  auto cleanup = fit::defer([&keep_running, &thread]() {
    keep_running.store(false);
    thread.join();
  });

  zx::unowned_thread handle{native_thread_get_zx_handle(thread.native_handle())};
  ASSERT_TRUE(handle->is_valid(), "got invalid thread handle");

  // Prove this is a valid handle by duplicating it.
  zx::thread dup_handle;
  ASSERT_OK(handle->duplicate(ZX_RIGHT_SAME_RIGHTS, &dup_handle));
  ASSERT_TRUE(dup_handle.is_valid());
  dup_handle.reset();
  ASSERT_FALSE(dup_handle.is_valid());
}

TEST(C11ThreadTest, DetachedThreadKeepsRunning) {
  constexpr zx::duration kWaitEachIteration = zx::usec(10);

  struct Args {
    std::atomic<bool> keep_running;
    std::atomic<bool> thread_done;
    std::atomic<int> thread_iterations;
    const zx::duration kWaitEachIteration;
  } args = {true, false, 0, kWaitEachIteration};

  auto HandleHelper = [](void* arg) -> int {
    Args* args = static_cast<Args*>(arg);

    while (args->keep_running.load()) {
      zx::nanosleep(zx::deadline_after(args->kWaitEachIteration));
      args->thread_iterations.fetch_add(1);
    }
    args->thread_done.store(true);
    return 0;
  };

  thrd_t thread;
  ASSERT_EQ(thrd_create(&thread, HandleHelper, &args), thrd_success);

  ASSERT_EQ(thrd_detach(thread), thrd_success);

  // observe the thread is still operating
  int recorded_thread_iterations = args.thread_iterations.load();
  zx::duration time_waited;
  while (recorded_thread_iterations == args.thread_iterations.load()) {
    zx::nanosleep(zx::deadline_after(kWaitEachIteration));
    time_waited += kWaitEachIteration;
  }
  ASSERT_EQ(args.thread_done.load(), false);

  args.keep_running.store(false);

  time_waited = zx::duration();
  while (!args.thread_done.load()) {
    zx::nanosleep(zx::deadline_after(kWaitEachIteration));
    time_waited += kWaitEachIteration;
  }
  ASSERT_TRUE(args.thread_done.load());
}

TEST(C11ThreadTest, LongNameSucceeds) {
  auto LongNameHelper = [](void* arg) { return 0; };

  // Creating a thread with a super long name should succeed.
  constexpr char kLongName[] =
      "0123456789012345678901234567890123456789"
      "0123456789012345678901234567890123456789";
  ASSERT_GT(strlen(kLongName), static_cast<size_t>(ZX_MAX_NAME_LEN - 1), "too short to truncate");

  thrd_t thread;
  ASSERT_EQ(thrd_create_with_name(&thread, LongNameHelper, nullptr, kLongName), thrd_success);

  // Clean up.
  EXPECT_EQ(thrd_join(thread, nullptr), thrd_success);
}

TEST(C11ThreadTest, SelfDetachAndFree) {
  constexpr int kNumThreads = 1000;
  std::atomic<int> num_threads_completed = 0;

  struct Args {
    thrd_t* thread;
    std::atomic<int> detach_status;
    std::atomic<int>* num_threads_completed;
  } args[kNumThreads];

  auto DetachHelper = [](void* arg) -> int {
    Args* args = static_cast<Args*>(arg);
    args->detach_status.store(thrd_detach(*args->thread));
    delete args->thread;
    args->num_threads_completed->fetch_add(1);
    return 0;
  };

  for (size_t i = 0; i < kNumThreads; i++) {
    args[i].thread = new thrd_t;
    args[i].num_threads_completed = &num_threads_completed;
    ASSERT_EQ(thrd_create(args[i].thread, DetachHelper, &args[i]), thrd_success);
  }
  while (num_threads_completed.load() != kNumThreads) {
    sched_yield();
  }
  for (size_t i = 0; i < kNumThreads; i++) {
    ASSERT_EQ(args[i].detach_status.load(), thrd_success);
  }
}

}  // namespace
