// 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 <stdlib.h>
#include <string.h>
#include <launchpad/launchpad.h>
#include <launchpad/vmo.h>
#include <lib/zircon-internal/crashlogger.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/port.h>
#include <zircon/status.h>
#include <runtime/thread.h>
#include <test-utils/test-utils.h>
#include <unittest/unittest.h>

#define TU_FAIL_ERRCODE 10

void* tu_malloc(size_t size)
{
    void* result = malloc(size);
    if (result == NULL) {
        // TODO(dje): printf may try to malloc too ...
        unittest_printf_critical("out of memory trying to malloc(%zu)\n", size);
        exit(TU_FAIL_ERRCODE);
    }
    return result;
}

void* tu_calloc(size_t nmemb, size_t size)
{
    void* result = calloc(nmemb, size);
    if (result == NULL) {
        // TODO(dje): printf may try to malloc too ...
        unittest_printf_critical("out of memory trying to calloc(%zu, %zu)\n", nmemb, size);
        exit(TU_FAIL_ERRCODE);
    }
    return result;
}

char* tu_strdup(const char* s)
{
    size_t len = strlen(s) + 1;
    char* r = tu_malloc(len);
    strcpy(r, s);
    return r;
}

char* tu_asprintf(const char* fmt, ...)
{
    va_list args;
    char* result;
    va_start(args, fmt);
    if (vasprintf(&result, fmt, args) < 0) {
        unittest_printf_critical("out of memory trying to asprintf(%s)\n", fmt);
        exit(TU_FAIL_ERRCODE);
    }
    va_end(args);
    return result;
}

void tu_fatal(const char *what, zx_status_t status)
{
    const char* reason = zx_status_get_string(status);
    unittest_printf_critical("\nFATAL: %s failed, rc %d (%s)\n", what, status, reason);

    // Request a backtrace to assist debugging.
    unittest_printf_critical("FATAL: backtrace follows:\n");
    unittest_printf_critical("       (using sw breakpoint request to crashlogger)\n");
    zx_crashlogger_request_backtrace();

    unittest_printf_critical("FATAL: exiting process\n");
    exit(TU_FAIL_ERRCODE);
}

void tu_handle_close(zx_handle_t handle)
{
    zx_status_t status = zx_handle_close(handle);
    // TODO(dje): It's still an open question as to whether errors other than ZX_ERR_BAD_HANDLE are "advisory".
    if (status < 0) {
        tu_fatal(__func__, status);
    }
}

zx_handle_t tu_handle_duplicate(zx_handle_t handle)
{
    zx_handle_t copy = ZX_HANDLE_INVALID;
    zx_status_t status =
        zx_handle_duplicate(handle, ZX_RIGHT_SAME_RIGHTS, &copy);
    if (status < 0)
        tu_fatal(__func__, status);
    return copy;
}

// N.B. This creates a C11 thread.
// See, e.g., musl/include/threads.h.

void tu_thread_create_c11(thrd_t* t, thrd_start_t entry, void* arg,
                          const char* name)
{
    int ret = thrd_create_with_name(t, entry, arg, name);
    if (ret != thrd_success) {
        // tu_fatal takes zx_status_t values.
        // The translation doesn't have to be perfect.
        switch (ret) {
        case thrd_nomem:
            tu_fatal(__func__, ZX_ERR_NO_MEMORY);
        default:
            tu_fatal(__func__, ZX_ERR_BAD_STATE);
        }
        __UNREACHABLE;
    }
}

zx_status_t tu_wait(uint32_t num_objects,
                    const zx_handle_t* handles,
                    const zx_signals_t* signals,
                    zx_signals_t* pending)
{
    zx_wait_item_t items[num_objects];
    for (uint32_t n = 0; n < num_objects; n++) {
        items[n].handle = handles[n];
        items[n].waitfor = signals[n];
    }
    zx_status_t status = zx_object_wait_many(items, num_objects, ZX_TIME_INFINITE);
    for (uint32_t n = 0; n < num_objects; n++) {
        pending[n] = items[n].pending;
    }
    return status;
}

void tu_channel_create(zx_handle_t* handle0, zx_handle_t* handle1) {
    zx_handle_t handles[2];
    zx_status_t status = zx_channel_create(0, &handles[0], &handles[1]);
    if (status < 0)
        tu_fatal(__func__, status);
    *handle0 = handles[0];
    *handle1 = handles[1];
}

void tu_channel_write(zx_handle_t handle, uint32_t flags, const void* bytes, uint32_t num_bytes,
                      const zx_handle_t* handles, uint32_t num_handles) {
    zx_status_t status = zx_channel_write(handle, flags, bytes, num_bytes, handles, num_handles);
    if (status < 0)
        tu_fatal(__func__, status);
}

void tu_channel_read(zx_handle_t handle, uint32_t flags, void* bytes, uint32_t* num_bytes,
                     zx_handle_t* handles, uint32_t* num_handles) {
    zx_status_t status = zx_channel_read(handle, flags, bytes, handles,
                                         num_bytes ? *num_bytes : 0, num_handles ? *num_handles : 0,
                                         num_bytes, num_handles);
    if (status < 0)
        tu_fatal(__func__, status);
}

bool tu_channel_wait_readable(zx_handle_t channel)
{
    zx_signals_t signals = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
    zx_signals_t pending;
    zx_status_t result = tu_wait(1, &channel, &signals, &pending);
    if (result != ZX_OK)
        tu_fatal(__func__, result);
    if ((pending & ZX_CHANNEL_READABLE) == 0) {
        unittest_printf("%s: peer closed\n", __func__);
        return false;
    }
    return true;
}

zx_handle_t tu_launch(zx_handle_t job, const char* name,
                      int argc, const char* const* argv,
                      const char* const* envp,
                      size_t num_handles, zx_handle_t* handles,
                      uint32_t* handle_ids)
{
    launchpad_t* lp;
    launchpad_create(job, name, &lp);
    launchpad_load_from_file(lp, argv[0]);
    launchpad_set_args(lp, argc, argv);
    launchpad_set_environ(lp, envp);
    launchpad_add_handles(lp, num_handles, handles, handle_ids);

    zx_status_t status;
    zx_handle_t child;
    status = launchpad_go(lp, &child, NULL);

    if (status < 0)
        tu_fatal("tu_launch", status);
    return child;
}

launchpad_t* tu_launch_fdio_init(zx_handle_t job, const char* name,
                                 int argc, const char* const* argv,
                                 const char* const* envp,
                                 size_t hnds_count, zx_handle_t* handles,
                                 uint32_t* ids)
{
    // This is the first part of launchpad_launch_fdio_etc.
    // It does everything except start the process running.
    launchpad_t* lp;

    const char* filename = argv[0];
    if (name == NULL)
        name = filename;

    launchpad_create(job, name, &lp);
    launchpad_load_from_file(lp, filename);
    launchpad_set_args(lp, argc, argv);
    launchpad_set_environ(lp, envp);
    launchpad_clone(lp, LP_CLONE_FDIO_ALL);
    launchpad_add_handles(lp, hnds_count, handles, ids);

   return lp;
}

zx_handle_t tu_launch_fdio_fini(launchpad_t* lp)
{
    zx_handle_t proc;
    zx_status_t status;
    if ((status = launchpad_go(lp, &proc, NULL)) < 0)
        tu_fatal("tu_launch_fdio_fini", status);
    return proc;
}

void tu_process_wait_signaled(zx_handle_t process)
{
    zx_signals_t signals = ZX_PROCESS_TERMINATED;
    zx_signals_t pending;
    zx_status_t result = tu_wait(1, &process, &signals, &pending);
    if (result != ZX_OK)
        tu_fatal(__func__, result);
    if ((pending & ZX_PROCESS_TERMINATED) == 0) {
        unittest_printf_critical("%s: unexpected return from tu_wait\n", __func__);
        exit(TU_FAIL_ERRCODE);
    }
}

bool tu_process_has_exited(zx_handle_t process)
{
    zx_info_process_t info;
    zx_status_t status;
    if ((status = zx_object_get_info(process, ZX_INFO_PROCESS, &info,
                                     sizeof(info), NULL, NULL)) < 0)
        tu_fatal("get process info", status);
    return info.exited;
}

int tu_process_get_return_code(zx_handle_t process)
{
    zx_info_process_t info;
    zx_status_t status;
    if ((status = zx_object_get_info(process, ZX_INFO_PROCESS, &info,
                                     sizeof(info), NULL, NULL)) < 0)
        tu_fatal("get process info", status);
    if (!info.exited) {
        unittest_printf_critical(
                "attempt to read return code of non-exited process");
        exit(TU_FAIL_ERRCODE);
    }
    return info.return_code;
}

int tu_process_wait_exit(zx_handle_t process)
{
    tu_process_wait_signaled(process);
    return tu_process_get_return_code(process);
}

zx_handle_t tu_process_get_thread(zx_handle_t process, zx_koid_t tid)
{
    zx_handle_t thread;
    zx_status_t status = zx_object_get_child(process, tid, ZX_RIGHT_SAME_RIGHTS, &thread);
    if (status == ZX_ERR_NOT_FOUND)
        return ZX_HANDLE_INVALID;
    if (status < 0)
        tu_fatal(__func__, status);
    return thread;
}

size_t tu_process_get_threads(zx_handle_t process, zx_koid_t* threads, size_t max_threads)
{
    size_t num_threads;
    size_t buf_size = max_threads * sizeof(threads[0]);
    zx_status_t status = zx_object_get_info(process, ZX_INFO_PROCESS_THREADS,
                                            threads, buf_size, &num_threads, NULL);
    if (status < 0)
        tu_fatal(__func__, status);
    return num_threads;
}

zx_handle_t tu_job_create(zx_handle_t job)
{
    zx_handle_t child_job;
    zx_status_t status = zx_job_create(job, 0, &child_job);
    if (status < 0)
        tu_fatal(__func__, status);
    return child_job;
}

zx_handle_t tu_io_port_create(void)
{
    zx_handle_t handle;
    zx_status_t status = zx_port_create(0, &handle);
    if (status < 0)
        tu_fatal(__func__, status);
    return handle;
}

void tu_set_exception_port(zx_handle_t handle, zx_handle_t eport, uint64_t key, uint32_t options)
{
    if (handle == 0)
        handle = zx_process_self();
    zx_status_t status = zx_task_bind_exception_port(handle, eport, key, options);
    if (status < 0)
        tu_fatal(__func__, status);
}

void tu_object_wait_async(zx_handle_t handle, zx_handle_t port, zx_signals_t signals)
{
    uint64_t key = tu_get_koid(handle);
    uint32_t options = ZX_WAIT_ASYNC_REPEATING;
    zx_status_t status = zx_object_wait_async(handle, port, key, signals, options);
    if (status < 0)
        tu_fatal(__func__, status);
}

void tu_handle_get_basic_info(zx_handle_t handle, zx_info_handle_basic_t* info)
{
    zx_status_t status = zx_object_get_info(handle, ZX_INFO_HANDLE_BASIC,
                                            info, sizeof(*info), NULL, NULL);
    if (status < 0)
        tu_fatal(__func__, status);
}

zx_koid_t tu_get_koid(zx_handle_t handle)
{
    zx_info_handle_basic_t info;
    tu_handle_get_basic_info(handle, &info);
    return info.koid;
}

zx_koid_t tu_get_related_koid(zx_handle_t handle)
{
    zx_info_handle_basic_t info;
    tu_handle_get_basic_info(handle, &info);
    return info.related_koid;
}

zx_handle_t tu_get_thread(zx_handle_t proc, zx_koid_t tid)
{
    zx_handle_t thread;
    zx_status_t status = zx_object_get_child(proc, tid, ZX_RIGHT_SAME_RIGHTS, &thread);
    if (status != ZX_OK)
        tu_fatal(__func__, status);
    return thread;
}

zx_info_thread_t tu_thread_get_info(zx_handle_t thread)
{
    zx_info_thread_t info;
    zx_status_t status = zx_object_get_info(thread, ZX_INFO_THREAD, &info, sizeof(info), NULL, NULL);
    if (status < 0)
        tu_fatal("zx_object_get_info(ZX_INFO_THREAD)", status);
    return info;
}

uint32_t tu_thread_get_state(zx_handle_t thread)
{
    zx_info_thread_t info = tu_thread_get_info(thread);
    return info.state;
}

bool tu_thread_is_dying_or_dead(zx_handle_t thread)
{
    zx_info_thread_t info = tu_thread_get_info(thread);
    return (info.state == ZX_THREAD_STATE_DYING ||
            info.state == ZX_THREAD_STATE_DEAD);
}

void tu_task_kill(zx_handle_t task)
{
    zx_status_t status = zx_task_kill(task);
    if (status < 0)
        tu_fatal("zx_task_kill", status);
}

int tu_run_program(const char *progname, int argc, const char** argv)
{
    launchpad_t* lp;

    unittest_printf("%s: running %s\n", __func__, progname);

    launchpad_create(ZX_HANDLE_INVALID, progname, &lp);
    launchpad_clone(lp, LP_CLONE_ALL);
    launchpad_load_from_file(lp, argv[0]);
    launchpad_set_args(lp, argc, argv);
    zx_status_t status;
    zx_handle_t child;
    if ((status = launchpad_go(lp, &child, NULL)) < 0) {
        tu_fatal(__func__, status);
    }

    int rc = tu_process_wait_exit(child);
    tu_handle_close(child);
    unittest_printf("%s: child returned %d\n", __func__, rc);
    return rc;
}

int tu_run_command(const char* progname, const char* cmd)
{
    const char* argv[] = {
        "/boot/bin/sh",
        "-c",
        cmd
    };

    return tu_run_program(progname, countof(argv), argv);
}
