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

#include <limits.h>
#include <new>
#include <cstddef>
#include <memory>

#include <fbl/algorithm.h>
#include <lib/fidl/coding.h>
#include <lib/fidl/internal.h>
#include <lib/zx/event.h>
#include <lib/zx/eventpair.h>
#include <unittest/unittest.h>
#include <zircon/syscalls.h>

#include "fidl/extra_messages.h"
#include "fidl_coded_types.h"
#include "fidl_structs.h"

namespace fidl {
namespace {

// test utility functions

bool IsPeerValid(const zx::unowned_eventpair& handle) {
    zx_signals_t observed_signals = {};
    switch (handle->wait_one(ZX_EVENTPAIR_PEER_CLOSED,
                             zx::deadline_after(zx::msec(1)),
                             &observed_signals)) {
        case ZX_ERR_TIMED_OUT:
            // timeout implies peer-closed was not observed
            return true;
        case ZX_OK:
            return (observed_signals & ZX_EVENTPAIR_PEER_CLOSED) == 0;
        default:
            return false;
    }
}

bool IsPeerValid(zx_handle_t handle) {
    return IsPeerValid(zx::unowned_eventpair(handle));
}

bool EncodeErrorTest() {
    BEGIN_TEST;

    // If there is only one handle in the message, fidl_encode should not close beyond one handles.
    // Specifically, |event_handle| should remain intact.

    zx_handle_t event_handle;
    ASSERT_EQ(zx_event_create(0, &event_handle), ZX_OK);
    zx_handle_t handles[2] = {
        ZX_HANDLE_INVALID,
        event_handle,
    };

    constexpr uint32_t kMessageSize = sizeof(nonnullable_handle_message_layout);
    std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(kMessageSize);
    nonnullable_handle_message_layout& message =
        *reinterpret_cast<nonnullable_handle_message_layout*>(buffer.get());
    message.inline_struct.handle = ZX_HANDLE_INVALID;

    const char* error = nullptr;
    uint32_t actual_handles;
    auto status = fidl_encode(&nonnullable_handle_message_type, &message, kMessageSize, handles,
                              fbl::count_of(handles), &actual_handles, &error);

    ASSERT_EQ(status, ZX_ERR_INVALID_ARGS);
    ASSERT_NONNULL(error);
    ASSERT_EQ(handles[0], ZX_HANDLE_INVALID);
    ASSERT_EQ(handles[1], event_handle);

    ASSERT_EQ(zx_handle_close(event_handle), ZX_OK);

    END_TEST;
}

bool EncodeWithNullHandlesTest() {
    BEGIN_TEST;

    // When the |handles| parameter to fidl_encode is nullptr, it should still close all handles
    // inside the message.
    for (uint32_t num_handles : {0u, 1u}) {
        zx::eventpair eventpair_a;
        zx::eventpair eventpair_b;
        ASSERT_EQ(zx::eventpair::create(0, &eventpair_a, &eventpair_b), ZX_OK);

        constexpr uint32_t kMessageSize = sizeof(nonnullable_handle_message_layout);
        std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(kMessageSize);
        nonnullable_handle_message_layout& message =
            *reinterpret_cast<nonnullable_handle_message_layout*>(buffer.get());
        message.inline_struct.handle = eventpair_a.release();

        const char* error = nullptr;
        uint32_t actual_handles;
        auto status = fidl_encode(&nonnullable_handle_message_type, &message, kMessageSize, nullptr,
                                  num_handles, &actual_handles, &error);

        ASSERT_EQ(status, ZX_ERR_INVALID_ARGS);
        ASSERT_NONNULL(error);
        ASSERT_FALSE(IsPeerValid(zx::unowned_eventpair(eventpair_b)));
    }

    END_TEST;
}

bool EncodeWithNullOutActualHandlesTest() {
    BEGIN_TEST;

    // When the |out_actual_handles| parameter to fidl_encode is nullptr, it should still close
    // all handles inside the message.

    zx::eventpair eventpair_a;
    zx::eventpair eventpair_b;
    ASSERT_EQ(zx::eventpair::create(0, &eventpair_a, &eventpair_b), ZX_OK);
    zx_handle_t handles[1] = {};

    constexpr uint32_t kMessageSize = sizeof(nonnullable_handle_message_layout);
    std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(kMessageSize);
    nonnullable_handle_message_layout& message =
        *reinterpret_cast<nonnullable_handle_message_layout*>(buffer.get());
    message.inline_struct.handle = eventpair_a.release();

    const char* error = nullptr;
    auto status = fidl_encode(&nonnullable_handle_message_type, &message, kMessageSize, handles,
                              fbl::count_of(handles), nullptr, &error);

    ASSERT_EQ(status, ZX_ERR_INVALID_ARGS);
    ASSERT_NONNULL(error);
    ASSERT_FALSE(IsPeerValid(zx::unowned_eventpair(eventpair_b)));

    END_TEST;
}

bool DecodeErrorTest() {
    BEGIN_TEST;

    // If an unknown envelope causes the handles contained within to be closed, and later on
    // an error was encountered, the handles in the unknown envelope should not be closed again.
    zx::eventpair eventpair_a;
    zx::eventpair eventpair_b;
    ASSERT_EQ(zx::eventpair::create(0, &eventpair_a, &eventpair_b), ZX_OK);

    // It should close all handles in case of failure. Add an extra handle at the end of the
    // handle array to detect this.
    zx::eventpair eventpair_x;
    zx::eventpair eventpair_y;
    ASSERT_EQ(zx::eventpair::create(0, &eventpair_x, &eventpair_y), ZX_OK);

    // Assemble an encoded TableOfStructWithHandle, with first field correctly populated,
    // but second field missing non-nullable handles.
    constexpr uint32_t buf_size = 512;
    uint8_t buffer[buf_size] = {};
    TableOfStructLayout* msg = reinterpret_cast<TableOfStructLayout*>(&buffer[0]);
    msg->envelope_vector.set_data(reinterpret_cast<fidl_envelope_t*>(FIDL_ALLOC_PRESENT));
    msg->envelope_vector.set_count(2);
    msg->envelopes.a = fidl_envelope_t {
        .num_bytes = sizeof(OrdinalOneStructWithHandle),
        .num_handles = 1,
        .presence = FIDL_ALLOC_PRESENT
    };
    msg->envelopes.b = fidl_envelope_t {
        .num_bytes = sizeof(OrdinalTwoStructWithManyHandles),
        .num_handles = 0,
        .presence = FIDL_ALLOC_PRESENT
    };
    msg->a = OrdinalOneStructWithHandle {
        .h = FIDL_HANDLE_PRESENT,
        .foo = 42
    };
    msg->b = OrdinalTwoStructWithManyHandles {
        .h1 = ZX_HANDLE_INVALID,
        .h2 = ZX_HANDLE_INVALID,
        .hs = {}
    };

    ASSERT_TRUE(IsPeerValid(zx::unowned_eventpair(eventpair_a)));

    const char* out_error = nullptr;
    zx_handle_t handles[] = { eventpair_b.release(), eventpair_y.release() };
    auto status = fidl_decode(&fidl_test_coding_SmallerTableOfStructWithHandleTable,
                              buffer, buf_size,
                              handles, fbl::count_of(handles), &out_error);
    ASSERT_EQ(status, ZX_ERR_INVALID_ARGS);
    ASSERT_NONNULL(out_error);

    // The peer was closed by the decoder
    ASSERT_FALSE(IsPeerValid(zx::unowned_eventpair(eventpair_a)));
    ASSERT_FALSE(IsPeerValid(zx::unowned_eventpair(eventpair_x)));

    END_TEST;
}

BEGIN_TEST_CASE(on_error_close_handle)
RUN_TEST(EncodeErrorTest)
RUN_TEST(EncodeWithNullHandlesTest)
RUN_TEST(EncodeWithNullOutActualHandlesTest)
RUN_TEST(DecodeErrorTest)
END_TEST_CASE(on_error_close_handle)

} // namespace
} // namespace fidl
