// 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 <fidl/test/llcpp/basictypes/c/fidl.h>
#include <lib/async-loop/loop.h>
#include <lib/fidl-utils/bind.h>
#include <lib/fidl/llcpp/coding.h>
#include <lib/zx/channel.h>
#include <lib/zx/eventpair.h>
#include <lib/zx/time.h>
#include <memory>
#include <string.h>
#include <unittest/unittest.h>
#include <utility>
#include <zircon/fidl.h>
#include <zircon/syscalls.h>

// Interface under test
#include "generated/fidl_llcpp_basic.h"

// C server implementation
namespace internal_c {

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));
}

zx_status_t ConsumeSimpleStruct(void* ctx,
                                const fidl_test_llcpp_basictypes_SimpleStruct* arg,
                                fidl_txn_t* txn) {
    // Verify that all the handles are valid channels
    if (!IsPeerValid(arg->ep)) {
        return fidl_test_llcpp_basictypes_TestInterfaceConsumeSimpleStruct_reply(
            txn, ZX_ERR_INVALID_ARGS, -1);
    }
    for (auto& row : arg->arr) {
        for (auto& handle : row) {
            if (!IsPeerValid(handle)) {
                return fidl_test_llcpp_basictypes_TestInterfaceConsumeSimpleStruct_reply(
                    txn, ZX_ERR_INVALID_ARGS, -1);
            }
        }
    }
    // Close all the handles as part of consumption
    zx_handle_close(arg->ep);
    for (auto& row : arg->arr) {
        for (auto& handle : row) {
            zx_handle_close(handle);
        }
    }
    // Loop back field argument
    return fidl_test_llcpp_basictypes_TestInterfaceConsumeSimpleStruct_reply(
        txn, ZX_OK, arg->field);
}

zx_status_t ConsumeSimpleUnion(void* ctx,
                               const fidl_test_llcpp_basictypes_SimpleUnion* arg,
                               fidl_txn_t* txn) {
    if (arg->tag == fidl_test_llcpp_basictypes_SimpleUnionTag_field_a) {
        return fidl_test_llcpp_basictypes_TestInterfaceConsumeSimpleUnion_reply(
            txn, 0, arg->field_a);
    } else if (arg->tag == fidl_test_llcpp_basictypes_SimpleUnionTag_field_b) {
        return fidl_test_llcpp_basictypes_TestInterfaceConsumeSimpleUnion_reply(
            txn, 1, arg->field_b);
    } else {
        return fidl_test_llcpp_basictypes_TestInterfaceConsumeSimpleUnion_reply(
            txn, UINT32_MAX, -1);
    }
}

const fidl_test_llcpp_basictypes_TestInterface_ops_t kOps = {
    .ConsumeSimpleStruct = ConsumeSimpleStruct,
    .ConsumeSimpleUnion = ConsumeSimpleUnion,
};

zx_status_t ServerDispatch(void* ctx,
                           fidl_txn_t* txn,
                           fidl_msg_t* msg,
                           const fidl_test_llcpp_basictypes_TestInterface_ops_t* ops) {
    zx_status_t status = fidl_test_llcpp_basictypes_TestInterface_try_dispatch(ctx, txn, msg, ops);
    if (status == ZX_ERR_NOT_SUPPORTED) {
        zx_handle_close_many(msg->handles, msg->num_handles);
    }
    return status;
}

}

namespace {

bool SpinUpAsyncCServerHelper(zx::channel server, async_loop_t** out_loop) {
    BEGIN_HELPER;

    async_loop_t* loop = nullptr;
    ASSERT_EQ(ZX_OK, async_loop_create(&kAsyncLoopConfigNoAttachToThread, &loop), "");
    ASSERT_EQ(ZX_OK, async_loop_start_thread(loop, "basictypes-dispatcher", NULL), "");

    async_dispatcher_t* dispatcher = async_loop_get_dispatcher(loop);
    fidl_bind(dispatcher,
              server.release(),
              (fidl_dispatch_t*) internal_c::ServerDispatch,
              NULL,
              &internal_c::kOps);
    *out_loop = loop;

    END_HELPER;
}

void TearDownAsyncCServerHelper(async_loop_t* loop) {
    async_loop_destroy(loop);
}

bool RawChannelCallStructTest() {
    BEGIN_TEST;

    zx::channel client, server;
    ASSERT_EQ(zx::channel::create(0, &client, &server), ZX_OK);

    async_loop_t* loop = nullptr;
    ASSERT_TRUE(SpinUpAsyncCServerHelper(std::move(server), &loop));

    // manually call the server using generated message definitions
    FIDL_ALIGNDECL uint8_t storage[512] = {};
    fidl::BytePart bytes(&storage[0], sizeof(storage));
    // trivial linearization except to set message length
    bytes.set_actual(
        sizeof(fidl::test::llcpp::basictypes::TestInterface::ConsumeSimpleStructRequest));
    fidl::DecodedMessage<fidl::test::llcpp::basictypes::TestInterface::ConsumeSimpleStructRequest>
        request(std::move(bytes));
    request.message()->_hdr.ordinal =
        fidl_test_llcpp_basictypes_TestInterfaceConsumeSimpleStructOrdinal;
    request.message()->arg.field = 123;
    // make sure array shape is as expected (5 by 4)
    constexpr size_t kNumRow = 5;
    constexpr size_t kNumCol = 4;
    constexpr size_t kNumHandlesInArray = kNumRow * kNumCol;
    static_assert(decltype(request.message()->arg.arr)::size() == kNumRow);
    static_assert(
        std::remove_reference_t<decltype(request.message()->arg.arr[0])>::size() == kNumCol);
    // insert handles to be sent over
    zx::eventpair single_handle_payload;
    zx::eventpair single_handle_ourside;
    ASSERT_EQ(zx::eventpair::create(0, &single_handle_ourside, &single_handle_payload), ZX_OK);
    std::unique_ptr<zx::eventpair[]> handle_payload(new zx::eventpair[kNumHandlesInArray]);
    std::unique_ptr<zx::eventpair[]> handle_our_side(new zx::eventpair[kNumHandlesInArray]);
    for (size_t i = 0; i < kNumHandlesInArray; i++) {
        ASSERT_EQ(zx::eventpair::create(0, &handle_our_side[i], &handle_payload[i]), ZX_OK);
    }
    // fill the |ep| field
    request.message()->arg.ep = std::move(single_handle_payload);
    // fill the 2D handles array
    for (size_t i = 0; i < kNumRow; i++) {
        for (size_t j = 0; j < kNumCol; j++) {
            request.message()->arg.arr[i][j] = std::move(handle_payload[i * kNumCol + j]);
        }
    }
    auto encode_result = fidl::Encode(std::move(request));
    ASSERT_EQ(encode_result.status, ZX_OK);

    FIDL_ALIGNDECL uint8_t response_storage[512];
    fidl::BytePart response_bytes(&response_storage[0], sizeof(response_storage));
    auto response = fidl::Call(client, std::move(encode_result.message), std::move(response_bytes));

    ASSERT_EQ(response.status, ZX_OK);
    auto decode_result = fidl::Decode(std::move(response.message));
    ASSERT_EQ(decode_result.message.message()->field, 123);

    TearDownAsyncCServerHelper(loop);

    END_TEST;
}

bool RawChannelCallUnionTest() {
    BEGIN_TEST;

    zx::channel client, server;
    ASSERT_EQ(zx::channel::create(0, &client, &server), ZX_OK);

    async_loop_t* loop = nullptr;
    ASSERT_TRUE(SpinUpAsyncCServerHelper(std::move(server), &loop));

    // manually call the server using generated message definitions
    FIDL_ALIGNDECL uint8_t storage[512] = {};
    fidl::BytePart bytes(&storage[0], sizeof(storage));
    // trivial linearization except to set message length
    bytes.set_actual(
        sizeof(fidl::test::llcpp::basictypes::TestInterface::ConsumeSimpleUnionRequest));
    fidl::DecodedMessage<fidl::test::llcpp::basictypes::TestInterface::ConsumeSimpleUnionRequest>
        request(std::move(bytes));
    request.message()->_hdr.ordinal =
        fidl_test_llcpp_basictypes_TestInterfaceConsumeSimpleUnionOrdinal;
    request.message()->arg.mutable_field_b() = 456;

    auto encode_result = fidl::Encode(std::move(request));
    ASSERT_EQ(encode_result.status, ZX_OK);

    FIDL_ALIGNDECL uint8_t response_storage[512];
    fidl::BytePart response_bytes(&response_storage[0], sizeof(response_storage));
    auto response = fidl::Call(client, std::move(encode_result.message), std::move(response_bytes));

    ASSERT_EQ(response.status, ZX_OK);
    auto decode_result = fidl::Decode(std::move(response.message));
    ASSERT_EQ(decode_result.message.message()->index, 1);
    ASSERT_EQ(decode_result.message.message()->field, 456);

    TearDownAsyncCServerHelper(loop);

    END_TEST;
}

bool SyncCallStructTest() {
    BEGIN_TEST;

    zx::channel client, server;
    ASSERT_EQ(zx::channel::create(0, &client, &server), ZX_OK);

    async_loop_t* loop = nullptr;
    ASSERT_TRUE(SpinUpAsyncCServerHelper(std::move(server), &loop));

    // generated interface API
    fidl::test::llcpp::basictypes::TestInterface::SyncClient test(std::move(client));

    int32_t out_status;
    int32_t out_field;
    fidl::test::llcpp::basictypes::SimpleStruct simple_struct = {};
    simple_struct.field = 123;
    // make sure array shape is as expected (5 by 4)
    constexpr size_t kNumRow = 5;
    constexpr size_t kNumCol = 4;
    constexpr size_t kNumHandlesInArray = kNumRow * kNumCol;
    static_assert(decltype(simple_struct.arr)::size() == kNumRow);
    static_assert(
        std::remove_reference_t<decltype(simple_struct.arr[0])>::size() == kNumCol);
    // insert handles to be sent over
    zx::eventpair single_handle_payload;
    zx::eventpair single_handle_ourside;
    ASSERT_EQ(zx::eventpair::create(0, &single_handle_ourside, &single_handle_payload), ZX_OK);
    std::unique_ptr<zx::eventpair[]> handle_payload(new zx::eventpair[kNumHandlesInArray]);
    std::unique_ptr<zx::eventpair[]> handle_our_side(new zx::eventpair[kNumHandlesInArray]);
    for (size_t i = 0; i < kNumHandlesInArray; i++) {
        ASSERT_EQ(zx::eventpair::create(0, &handle_our_side[i], &handle_payload[i]), ZX_OK);
    }
    // fill the |ep| field
    simple_struct.ep = std::move(single_handle_payload);
    // fill the 2D handles array
    for (size_t i = 0; i < kNumRow; i++) {
        for (size_t j = 0; j < kNumCol; j++) {
            simple_struct.arr[i][j] = std::move(handle_payload[i * kNumCol + j]);
        }
    }
    // perform call
    zx_status_t status = test.ConsumeSimpleStruct(simple_struct, &out_status, &out_field);
    ASSERT_EQ(status, ZX_OK);
    ASSERT_EQ(out_status, ZX_OK);
    ASSERT_EQ(out_field, 123);

    TearDownAsyncCServerHelper(loop);

    END_TEST;
}

bool SyncCallerAllocateCallStructTest() {
    BEGIN_TEST;

    zx::channel client, server;
    ASSERT_EQ(zx::channel::create(0, &client, &server), ZX_OK);

    async_loop_t* loop = nullptr;
    ASSERT_TRUE(SpinUpAsyncCServerHelper(std::move(server), &loop));

    // generated interface API
    fidl::test::llcpp::basictypes::TestInterface::SyncClient test(std::move(client));

    int32_t out_status;
    int32_t out_field;
    fidl::test::llcpp::basictypes::SimpleStruct simple_struct = {};
    simple_struct.field = 123;
    // make sure array shape is as expected (5 by 4)
    constexpr size_t kNumRow = 5;
    constexpr size_t kNumCol = 4;
    constexpr size_t kNumHandlesInArray = kNumRow * kNumCol;
    static_assert(decltype(simple_struct.arr)::size() == kNumRow);
    static_assert(
        std::remove_reference_t<decltype(simple_struct.arr[0])>::size() == kNumCol);
    // insert handles to be sent over
    zx::eventpair single_handle_payload;
    zx::eventpair single_handle_ourside;
    ASSERT_EQ(zx::eventpair::create(0, &single_handle_ourside, &single_handle_payload), ZX_OK);
    std::unique_ptr<zx::eventpair[]> handle_payload(new zx::eventpair[kNumHandlesInArray]);
    std::unique_ptr<zx::eventpair[]> handle_our_side(new zx::eventpair[kNumHandlesInArray]);
    for (size_t i = 0; i < kNumHandlesInArray; i++) {
        ASSERT_EQ(zx::eventpair::create(0, &handle_our_side[i], &handle_payload[i]), ZX_OK);
    }
    // fill the |ep| field
    simple_struct.ep = std::move(single_handle_payload);
    // fill the 2D handles array
    for (size_t i = 0; i < kNumRow; i++) {
        for (size_t j = 0; j < kNumCol; j++) {
            simple_struct.arr[i][j] = std::move(handle_payload[i * kNumCol + j]);
        }
    }

    // perform call
    FIDL_ALIGNDECL uint8_t request_buf[512] = {};
    FIDL_ALIGNDECL uint8_t response_buf[512] = {};
    zx_status_t status = test.ConsumeSimpleStruct(fidl::BytePart(request_buf, sizeof(request_buf)),
                                                  fidl::BytePart(response_buf,
                                                                 sizeof(response_buf)),
                                                  simple_struct, &out_status, &out_field);
    ASSERT_EQ(status, ZX_OK);
    ASSERT_EQ(out_status, ZX_OK);
    ASSERT_EQ(out_field, 123);

    TearDownAsyncCServerHelper(loop);

    END_TEST;
}

bool SyncCallUnionTest() {
    BEGIN_TEST;

    zx::channel client, server;
    ASSERT_EQ(zx::channel::create(0, &client, &server), ZX_OK);

    async_loop_t* loop = nullptr;
    ASSERT_TRUE(SpinUpAsyncCServerHelper(std::move(server), &loop));

    // generated interface API
    fidl::test::llcpp::basictypes::TestInterface::SyncClient test(std::move(client));

    uint32_t out_index;
    int32_t out_field;
    fidl::test::llcpp::basictypes::SimpleUnion simple_union;
    simple_union.mutable_field_b() = 456;

    // perform call
    zx_status_t status = test.ConsumeSimpleUnion(simple_union, &out_index, &out_field);
    ASSERT_EQ(status, ZX_OK);
    ASSERT_EQ(out_index, 1);
    ASSERT_EQ(out_field, 456);

    TearDownAsyncCServerHelper(loop);

    END_TEST;
}

bool SyncCallerAllocateCallUnionTest() {
    BEGIN_TEST;

    zx::channel client, server;
    ASSERT_EQ(zx::channel::create(0, &client, &server), ZX_OK);

    async_loop_t* loop = nullptr;
    ASSERT_TRUE(SpinUpAsyncCServerHelper(std::move(server), &loop));

    // generated interface API
    fidl::test::llcpp::basictypes::TestInterface::SyncClient test(std::move(client));

    uint32_t out_index;
    int32_t out_field;
    fidl::test::llcpp::basictypes::SimpleUnion simple_union;
    simple_union.mutable_field_b() = 456;

    // perform call
    FIDL_ALIGNDECL uint8_t request_buf[512] = {};
    FIDL_ALIGNDECL uint8_t response_buf[512] = {};
    zx_status_t status = test.ConsumeSimpleUnion(fidl::BytePart(request_buf, sizeof(request_buf)),
                                                 fidl::BytePart(response_buf, sizeof(response_buf)),
                                                 simple_union, &out_index, &out_field);
    ASSERT_EQ(status, ZX_OK);
    ASSERT_EQ(out_index, 1);
    ASSERT_EQ(out_field, 456);

    TearDownAsyncCServerHelper(loop);

    END_TEST;
}

}

BEGIN_TEST_CASE(llcpp_basictypes_tests)
RUN_NAMED_TEST_SMALL("raw channel call (passing struct)", RawChannelCallStructTest)
RUN_NAMED_TEST_SMALL("raw channel call (passing union)", RawChannelCallUnionTest)
RUN_NAMED_TEST_SMALL("sync call via generated binding (passing struct)", SyncCallStructTest)
RUN_NAMED_TEST_SMALL("sync call via generated binding (passing union)", SyncCallUnionTest)
RUN_NAMED_TEST_SMALL("sync call via generated binding (passing struct, caller supplying buffer)",
                     SyncCallerAllocateCallStructTest)
RUN_NAMED_TEST_SMALL("sync call via generated binding (passing union, caller supplying buffer)",
                     SyncCallerAllocateCallUnionTest)
END_TEST_CASE(llcpp_basictypes_tests);
