// Copyright 2020 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "samples/emitc_modules/add_module.h"

#include "iree/base/api.h"
#include "iree/testing/gtest.h"
#include "iree/testing/status_matchers.h"
#include "iree/vm/api.h"

namespace iree {
namespace {

class VMAddModuleTest : public ::testing::Test {
 protected:
  virtual void SetUp() {
    IREE_CHECK_OK(iree_vm_instance_create(iree_allocator_system(), &instance_));

    iree_vm_module_t* add_module = nullptr;
    IREE_CHECK_OK(
        add_module_create(instance_, iree_allocator_system(), &add_module));

    std::vector<iree_vm_module_t*> modules = {add_module};
    IREE_CHECK_OK(iree_vm_context_create_with_modules(
        instance_, IREE_VM_CONTEXT_FLAG_NONE, modules.size(), modules.data(),
        iree_allocator_system(), &context_));

    iree_vm_module_release(add_module);
  }

  virtual void TearDown() {
    iree_vm_context_release(context_);
    iree_vm_instance_release(instance_);
  }

  StatusOr<int32_t> RunFunction(iree_string_view_t function_name, int32_t arg) {
    // Lookup the entry function. This can be cached in an application if
    // multiple calls will be made.
    iree_vm_function_t function;
    IREE_RETURN_IF_ERROR(
        iree_vm_context_resolve_function(context_, function_name, &function),
        "unable to resolve entry point");

    // Setup I/O lists and pass in the argument. The result list will be
    // populated upon return.
    vm::ref<iree_vm_list_t> input_list;
    IREE_RETURN_IF_ERROR(iree_vm_list_create(
        /*element_type=*/nullptr, 1, iree_allocator_system(), &input_list));
    auto arg_value = iree_vm_value_make_i32(arg);
    IREE_RETURN_IF_ERROR(iree_vm_list_push_value(input_list.get(), &arg_value));
    vm::ref<iree_vm_list_t> output_list;
    IREE_RETURN_IF_ERROR(iree_vm_list_create(
        /*element_type=*/nullptr, 1, iree_allocator_system(), &output_list));

    // Invoke the entry function to do our work. Runs synchronously.
    IREE_RETURN_IF_ERROR(
        iree_vm_invoke(context_, function, IREE_VM_INVOCATION_FLAG_NONE,
                       /*policy=*/nullptr, input_list.get(), output_list.get(),
                       iree_allocator_system()));

    // Load the output result.
    iree_vm_value_t ret_value;
    IREE_RETURN_IF_ERROR(
        iree_vm_list_get_value(output_list.get(), 0, &ret_value));
    return ret_value.i32;
  }

  StatusOr<int32_t> RunFunction(iree_string_view_t function_name, int32_t arg0,
                                int32_t arg1) {
    // Lookup the entry function. This can be cached in an application if
    // multiple calls will be made.
    iree_vm_function_t function;
    IREE_RETURN_IF_ERROR(
        iree_vm_context_resolve_function(context_, function_name, &function),
        "unable to resolve entry point");

    // Setup I/O lists and pass in the argument. The result list will be
    // populated upon return.
    vm::ref<iree_vm_list_t> input_list;
    IREE_RETURN_IF_ERROR(iree_vm_list_create(
        /*element_type=*/nullptr, 1, iree_allocator_system(), &input_list));
    auto arg0_value = iree_vm_value_make_i32(arg0);
    auto arg1_value = iree_vm_value_make_i32(arg1);
    IREE_RETURN_IF_ERROR(
        iree_vm_list_push_value(input_list.get(), &arg0_value));
    IREE_RETURN_IF_ERROR(
        iree_vm_list_push_value(input_list.get(), &arg1_value));
    vm::ref<iree_vm_list_t> output_list;
    IREE_RETURN_IF_ERROR(iree_vm_list_create(
        /*element_type=*/nullptr, 1, iree_allocator_system(), &output_list));

    // Invoke the entry function to do our work. Runs synchronously.
    IREE_RETURN_IF_ERROR(
        iree_vm_invoke(context_, function, IREE_VM_INVOCATION_FLAG_NONE,
                       /*policy=*/nullptr, input_list.get(), output_list.get(),
                       iree_allocator_system()));

    // Load the output result.
    iree_vm_value_t ret_value;
    IREE_RETURN_IF_ERROR(
        iree_vm_list_get_value(output_list.get(), 0, &ret_value));
    return ret_value.i32;
  }

 private:
  iree_vm_instance_t* instance_ = nullptr;
  iree_vm_context_t* context_ = nullptr;
};

TEST_F(VMAddModuleTest, AddTest) {
  IREE_ASSERT_OK_AND_ASSIGN(
      int32_t v,
      RunFunction(iree_make_cstring_view("add_module.add_and_double"), 17, 42));
  ASSERT_EQ(v, 118);
}

TEST_F(VMAddModuleTest, AddCallTest) {
  IREE_ASSERT_OK_AND_ASSIGN(
      int32_t v,
      RunFunction(iree_make_cstring_view("add_module.test_call"), 17));
  ASSERT_EQ(v, 136);
}

}  // namespace
}  // namespace iree
