diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index a9a7b8776c..40c9bb6aed 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -1,51 +1,52 @@ -# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required (VERSION 3.14) +cmake_minimum_required(VERSION 2.9) -project (wamr_unit_tests) +project(unit-test) -include (CTest) +SET(CMAKE_BUILD_TYPE Debug) -if (NOT DEFINED WAMR_BUILD_INTERP) - # Enable Interpreter by default - set (WAMR_BUILD_INTERP 1) -endif () +# add_definitions (-m32) +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") -if (NOT DEFINED WAMR_BUILD_PLATFORM) - string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) -endif () +if(WAMR_BUILD_TARGET STREQUAL "X86_32") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32") +endif() -set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) -include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) -add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE}) +# Prevent overriding the parent project's compiler/linker +# settings on Windows +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +# Fetch Google test include (FetchContent) FetchContent_Declare ( googletest URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip ) -# For Windows: Prevent overriding the parent project's compiler/linker settings -set (gtest_force_shared_crt ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable (googletest) -include (GoogleTest) - -add_library (wamr_gtest_main main.cpp) -target_link_libraries (wamr_gtest_main PUBLIC gtest vmlib) - -function (create_wamr_unit_test test_name) - set (sources ${ARGN}) - add_executable (${test_name} ${sources}) - target_link_libraries ( - ${test_name} - wamr_gtest_main - vmlib - ${LLVM_AVAILABLE_LIBS} - ) - gtest_discover_tests (${test_name}) - endfunction () - -if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1) - include (${IWASM_DIR}/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake) -endif () +SET(GOOGLETEST_INCLUDED 1) + +include(GoogleTest) +enable_testing() + +add_subdirectory(wasm-vm) +add_subdirectory(interpreter) +add_subdirectory(aot) +add_subdirectory(wasm-c-api) +add_subdirectory(libc-builtin) +add_subdirectory(shared-utils) +add_subdirectory(running-modes) +add_subdirectory(runtime-common) +add_subdirectory(custom-section) +add_subdirectory(compilation) +add_subdirectory(linear-memory-wasm) +add_subdirectory(linear-memory-aot) +add_subdirectory(aot-stack-frame) +add_subdirectory(linux-perf) +add_subdirectory(gc) +add_subdirectory(memory64) +add_subdirectory(tid-allocator) diff --git a/tests/unit/aot-stack-frame/CMakeLists.txt b/tests/unit/aot-stack-frame/CMakeLists.txt new file mode 100644 index 0000000000..9ff066f08c --- /dev/null +++ b/tests/unit/aot-stack-frame/CMakeLists.txt @@ -0,0 +1,55 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-aot-stack-frame) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_INTERP 0) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_SIMD 1) +set (WAMR_BUILD_REF_TYPES 1) +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_LIBC_BUILTIN 0) +set (WAMR_BUILD_MULTI_MODULE 0) +set (WAMR_DISABLE_HW_BOUND_CHECK 1) +set (WAMR_DISABLE_WRITE_GS_BASE 1) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1) +add_definitions (-DAOT_STACK_FRAME_DEBUG) +#add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} + ) + +# Automatically build wasm-apps for this test +add_subdirectory(wasm-apps) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable (aot_stack_frame_test ${unit_test_sources}) + +add_dependencies (aot_stack_frame_test aot-stack-frame-test-wasm) + +target_link_libraries (aot_stack_frame_test ${LLVM_AVAILABLE_LIBS} gtest_main ) + +#gtest_discover_tests(aot_stack_frame_test) \ No newline at end of file diff --git a/tests/unit/aot-stack-frame/aot_stack_frame_test.cc b/tests/unit/aot-stack-frame/aot_stack_frame_test.cc new file mode 100644 index 0000000000..9bea2b2a03 --- /dev/null +++ b/tests/unit/aot-stack-frame/aot_stack_frame_test.cc @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "bh_platform.h" +#include "wasm_runtime_common.h" +#include "aot_runtime.h" +#include "test_helper.h" + +#ifndef __aligned +#define __aligned(n) +#endif +#include "wasm-apps/test_aot.h" + +typedef struct MyAOTFrame { + uintptr_t func_index; + + /* Instruction pointer: offset to the bytecode array */ + uintptr_t ip_offset; + + /* Operand stack top pointer of the current frame */ + uint32 *sp; + +#if WASM_ENABLE_GC != 0 + /* Frame ref flags (GC only) */ + uint8 *frame_ref; +#endif + + uint32 lp[1]; +} MyAOTFrame; + +class AOTStackFrameTest : public testing::Test +{ + protected: + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + } + + virtual void TearDown() + { + DestroyFrames(); + wasm_runtime_destroy(); + } + + public: + static void DestroyFrames() + { + if (my_frames) { + for (uint32 i = 0; i < my_frame_num; i++) { + if (my_frames[i]) + wasm_runtime_free(my_frames[i]); + } + wasm_runtime_free(my_frames); + my_frames = NULL; + my_frame_num = 0; + } + } + + public: + RuntimeInitArgs init_args; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_function_inst_t func_inst = NULL; + wasm_exec_env_t exec_env = NULL; + static MyAOTFrame **my_frames; + static uint32 my_frame_num; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + unsigned char test_aot_buf[16 * 1024]; + unsigned argv[8]; +}; + +MyAOTFrame **AOTStackFrameTest::my_frames = NULL; +uint32 AOTStackFrameTest::my_frame_num = 0; + +extern "C" { + +typedef void (*stack_frame_callback_t)(struct WASMExecEnv *exec_env); + +void +aot_set_stack_frame_callback(stack_frame_callback_t callback); + +void +aot_stack_frame_cb(struct WASMExecEnv *exec_env) +{ + AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst; + AOTModule *module = (AOTModule *)module_inst->module; + AOTFrame *frame = (AOTFrame *)exec_env->cur_frame; + MyAOTFrame *my_frame, **my_frames; + uint32 all_cell_num, max_local_cell_num, max_stack_cell_num; + uint32 frame_size_old, frame_size, i, frame_num = 0, aot_func_idx; + + AOTStackFrameTest::DestroyFrames(); + + while (frame) { + frame_num++; + frame = frame->prev_frame; + } + + my_frames = + (MyAOTFrame **)wasm_runtime_malloc(sizeof(MyAOTFrame *) * frame_num); + bh_assert(my_frames); + + frame = (AOTFrame *)exec_env->cur_frame; + for (i = 0; i < frame_num; i++) { + aot_func_idx = frame->func_index; + max_local_cell_num = module->max_local_cell_nums[aot_func_idx]; + max_stack_cell_num = module->max_stack_cell_nums[aot_func_idx]; + all_cell_num = max_local_cell_num + max_stack_cell_num; + + frame_size_old = (uint32)offsetof(AOTFrame, lp) + all_cell_num * 4; + frame_size = (uint32)offsetof(MyAOTFrame, lp) + all_cell_num * 4; + + my_frames[frame_num - 1 - i] = my_frame = + (MyAOTFrame *)wasm_runtime_malloc(frame_size); + + my_frame->func_index = aot_func_idx; + my_frame->ip_offset = frame->ip_offset; + my_frame->sp = my_frame->lp + (frame->sp - frame->lp); +#if WASM_ENABLE_GC != 0 + my_frame->frame_ref = + (uint8 *)my_frame->lp + (frame->frame_ref - (uint8 *)frame->lp); +#endif + + bh_memcpy_s(my_frame->lp, all_cell_num * 4, frame->lp, + all_cell_num * 4); + + frame = frame->prev_frame; + } + + AOTStackFrameTest::my_frames = my_frames; + AOTStackFrameTest::my_frame_num = frame_num; +} +} + +TEST_F(AOTStackFrameTest, test1) +{ + MyAOTFrame *frame, **frames; + uint32 frame_num; + + aot_set_stack_frame_callback(aot_stack_frame_cb); + + bh_memcpy_s(test_aot_buf, sizeof(test_aot_buf), test_aot, sizeof(test_aot)); + + module = wasm_runtime_load(test_aot_buf, sizeof(test_aot), error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + module_inst = wasm_runtime_instantiate(module, 16384, 0, error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + func_inst = wasm_runtime_lookup_function(module_inst, "test1"); + ASSERT_TRUE(func_inst != NULL); + + argv[0] = 33; + argv[1] = 44; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst)); + + frames = AOTStackFrameTest::my_frames; + frame_num = AOTStackFrameTest::my_frame_num; + + ASSERT_TRUE(frames != NULL); + ASSERT_TRUE(frame_num == 1); + + ASSERT_TRUE(frames[0]->lp[0] == 33); + ASSERT_TRUE(frames[0]->lp[1] == 44); + ASSERT_TRUE(frames[0]->lp[2] == 0x11223344); + ASSERT_TRUE(*(uint64 *)(frames[0]->lp + 3) == 0x12345678ABCDEF99LL); + ASSERT_TRUE(*(float *)(frames[0]->lp + 5) == 5566.7788f); + ASSERT_TRUE(*(double *)(frames[0]->lp + 6) == 99887766.55443322); + + wasm_runtime_destroy_exec_env(exec_env); + exec_env = NULL; + + wasm_runtime_deinstantiate(module_inst); + module_inst = NULL; + + wasm_runtime_unload(module); + module = NULL; +} + +TEST_F(AOTStackFrameTest, test2) +{ + MyAOTFrame *frame, **frames; + uint32 frame_num; + + aot_set_stack_frame_callback(aot_stack_frame_cb); + + bh_memcpy_s(test_aot_buf, sizeof(test_aot_buf), test_aot, sizeof(test_aot)); + + module = wasm_runtime_load(test_aot_buf, sizeof(test_aot), error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + module_inst = wasm_runtime_instantiate(module, 16384, 0, error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + func_inst = wasm_runtime_lookup_function(module_inst, "test2"); + ASSERT_TRUE(func_inst != NULL); + + argv[0] = 1234; + argv[1] = 5678; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst)); + + frames = AOTStackFrameTest::my_frames; + frame_num = AOTStackFrameTest::my_frame_num; + + ASSERT_TRUE(frames != NULL); + ASSERT_TRUE(frame_num == 1); + + ASSERT_TRUE(frames[0]->lp[0] == 1234); + ASSERT_TRUE(frames[0]->lp[1] == 5678); + ASSERT_TRUE(frames[0]->lp[2] == 0x11223344); + ASSERT_TRUE(*(uint64 *)(frames[0]->lp + 3) == 0x12345678ABCDEF99LL); + ASSERT_TRUE(*(float *)(frames[0]->lp + 5) == 5566.7788f); + ASSERT_TRUE(*(double *)(frames[0]->lp + 6) == 99887766.55443322); + ASSERT_TRUE(frames[0]->lp[8] == 0x1234); + ASSERT_TRUE(frames[0]->lp[9] == 0x5678); +} + +TEST_F(AOTStackFrameTest, test3) +{ + MyAOTFrame *frame, **frames; + uint32 frame_num; + + aot_set_stack_frame_callback(aot_stack_frame_cb); + + bh_memcpy_s(test_aot_buf, sizeof(test_aot_buf), test_aot, sizeof(test_aot)); + + module = wasm_runtime_load(test_aot_buf, sizeof(test_aot), error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + module_inst = wasm_runtime_instantiate(module, 16384, 0, error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + func_inst = wasm_runtime_lookup_function(module_inst, "test3"); + ASSERT_TRUE(func_inst != NULL); + + argv[0] = 1234; + argv[1] = 5678; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst)); + + frames = AOTStackFrameTest::my_frames; + frame_num = AOTStackFrameTest::my_frame_num; + + ASSERT_TRUE(frames != NULL); + ASSERT_TRUE(frame_num == 2); + + ASSERT_TRUE(frames[0]->sp - frames[0]->lp == 5); + ASSERT_TRUE(frames[0]->ip_offset == 24); + + ASSERT_TRUE(frames[0]->lp[0] == 1234); + ASSERT_TRUE(frames[0]->lp[1] == 5678); + ASSERT_TRUE(frames[0]->lp[2] == 0x11223344); + ASSERT_TRUE(*(uint64 *)(frames[0]->lp + 3) == 0x12345678ABCDEF99LL); + + ASSERT_TRUE(frames[1]->lp[0] == 0x1234); + ASSERT_TRUE(frames[1]->lp[1] == 0x5678); + ASSERT_TRUE(frames[1]->lp[2] == 0x11223344); + ASSERT_TRUE(*(uint64 *)(frames[1]->lp + 3) == 0x12345678ABCDEF99LL); + ASSERT_TRUE(*(float *)(frames[1]->lp + 5) == 5566.7788f); + ASSERT_TRUE(*(double *)(frames[1]->lp + 6) == 99887766.55443322); +} diff --git a/tests/unit/aot-stack-frame/wasm-apps/CMakeLists.txt b/tests/unit/aot-stack-frame/wasm-apps/CMakeLists.txt new file mode 100644 index 0000000000..9dd9565a5d --- /dev/null +++ b/tests/unit/aot-stack-frame/wasm-apps/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project(wasm-apps-aot-stack-frame) + +add_custom_target(aot-stack-frame-test-wasm ALL + COMMAND cmake -B ${CMAKE_CURRENT_BINARY_DIR}/build-wamrc + -S ${WAMR_ROOT_DIR}/wamr-compiler + && cmake --build ${CMAKE_CURRENT_BINARY_DIR}/build-wamrc + && /opt/wabt/bin/wat2wasm + -o ${CMAKE_CURRENT_BINARY_DIR}/test.wasm + ${CMAKE_CURRENT_LIST_DIR}/test.wast + && ${CMAKE_CURRENT_BINARY_DIR}/build-wamrc/wamrc + --enable-dump-call-stack --bounds-checks=1 + -o ${CMAKE_CURRENT_BINARY_DIR}/test.aot + ${CMAKE_CURRENT_BINARY_DIR}/test.wasm + && cmake -B ${CMAKE_CURRENT_BINARY_DIR}/build-binarydump + -S ${WAMR_ROOT_DIR}/test-tools/binarydump-tool + && cmake --build ${CMAKE_CURRENT_BINARY_DIR}/build-binarydump + && ${CMAKE_CURRENT_BINARY_DIR}/build-binarydump/binarydump + -o ${CMAKE_CURRENT_LIST_DIR}/test_aot.h -n test_aot + ${CMAKE_CURRENT_BINARY_DIR}/test.aot + +) + diff --git a/tests/unit/aot-stack-frame/wasm-apps/test.wast b/tests/unit/aot-stack-frame/wasm-apps/test.wast new file mode 100644 index 0000000000..1ef866efc6 --- /dev/null +++ b/tests/unit/aot-stack-frame/wasm-apps/test.wast @@ -0,0 +1,36 @@ +(module + (func $test1 (export "test1") (param i32 i32) (result i32) + i32.const 0x11223344 + i64.const 0x1234_5678_ABCD_EF99 + f32.const 5566.7788 + f64.const 99887766.55443322 + unreachable + ) + + (func $test2 (export "test2") (param f32 f32) (result i32) + i32.const 0x11223344 + i64.const 0x1234_5678_ABCD_EF99 + f32.const 5566.7788 + f64.const 99887766.55443322 + + loop + i32.const 0x1234 + i32.const 0x5678 + unreachable + end + + unreachable + ) + + (func $test3 (export "test3") (param i32 i32) (result i32) + i32.const 0x11223344 + i64.const 0x1234_5678_ABCD_EF99 + + i32.const 0x1234 + i32.const 0x5678 + call $test1 + + drop + drop + ) +) diff --git a/tests/unit/aot/CMakeLists.txt b/tests/unit/aot/CMakeLists.txt new file mode 100644 index 0000000000..6b9c70c888 --- /dev/null +++ b/tests/unit/aot/CMakeLists.txt @@ -0,0 +1,59 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-aot) + +add_definitions (-DRUN_ON_LINUX) + +add_definitions (-Dattr_container_malloc=malloc) +add_definitions (-Dattr_container_free=free) +add_definitions (-DWASM_ENABLE_WAMR_COMPILER=1) +add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1) +add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 1) + +include (../unit_common.cmake) + +set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") +if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif () +set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include (${IWASM_DIR}/compilation/iwasm_compl.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable (aot_test ${unit_test_sources}) + +target_link_libraries (aot_test ${LLVM_AVAILABLE_LIBS} gtest_main ) + +gtest_discover_tests(aot_test) + diff --git a/tests/unit/aot/aot_test.cc b/tests/unit/aot/aot_test.cc new file mode 100644 index 0000000000..261b378e46 --- /dev/null +++ b/tests/unit/aot/aot_test.cc @@ -0,0 +1,1190 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include "gtest/gtest.h" +#include "wasm_export.h" +#include "bh_platform.h" +#include "aot_llvm.h" +#include "aot_intrinsic.h" +#include "aot.h" + +#define G_INTRINSIC_COUNT (50u) +#define CONS(num) ("f##num##.const") + +const char *llvm_intrinsic_tmp[G_INTRINSIC_COUNT] = { + "llvm.experimental.constrained.fadd.f32", + "llvm.experimental.constrained.fadd.f64", + "llvm.experimental.constrained.fsub.f32", + "llvm.experimental.constrained.fsub.f64", + "llvm.experimental.constrained.fmul.f32", + "llvm.experimental.constrained.fmul.f64", + "llvm.experimental.constrained.fdiv.f32", + "llvm.experimental.constrained.fdiv.f64", + "llvm.fabs.f32", + "llvm.fabs.f64", + "llvm.ceil.f32", + "llvm.ceil.f64", + "llvm.floor.f32", + "llvm.floor.f64", + "llvm.trunc.f32", + "llvm.trunc.f64", + "llvm.rint.f32", + "llvm.rint.f64", + "llvm.sqrt.f32", + "llvm.sqrt.f64", + "llvm.copysign.f32", + "llvm.copysign.f64", + "llvm.minnum.f32", + "llvm.minnum.f64", + "llvm.maxnum.f32", + "llvm.maxnum.f64", + "llvm.ctlz.i32", + "llvm.ctlz.i64", + "llvm.cttz.i32", + "llvm.cttz.i64", + "llvm.ctpop.i32", + "llvm.ctpop.i64", + "f64_convert_i32_s", + "f64_convert_i32_u", + "f32_convert_i32_s", + "f32_convert_i32_u", + "f64_convert_i64_s", + "f64_convert_i64_u", + "f32_convert_i64_s", + "f32_convert_i64_u", + "i32_trunc_f32_u", + "i32_trunc_f32_s", + "i32_trunc_f64_u", + "i32_trunc_f64_s", + "f32_demote_f64", + "f64_promote_f32", + "f32_cmp", + "f64_cmp", + "f32.const", + "f64.const", +}; + +uint64 g_intrinsic_flag[G_INTRINSIC_COUNT] = { + AOT_INTRINSIC_FLAG_F32_FADD, AOT_INTRINSIC_FLAG_F64_FADD, + AOT_INTRINSIC_FLAG_F32_FSUB, AOT_INTRINSIC_FLAG_F64_FSUB, + AOT_INTRINSIC_FLAG_F32_FMUL, AOT_INTRINSIC_FLAG_F64_FMUL, + AOT_INTRINSIC_FLAG_F32_FDIV, AOT_INTRINSIC_FLAG_F64_FDIV, + AOT_INTRINSIC_FLAG_F32_FABS, AOT_INTRINSIC_FLAG_F64_FABS, + AOT_INTRINSIC_FLAG_F32_CEIL, AOT_INTRINSIC_FLAG_F64_CEIL, + AOT_INTRINSIC_FLAG_F32_FLOOR, AOT_INTRINSIC_FLAG_F64_FLOOR, + AOT_INTRINSIC_FLAG_F32_TRUNC, AOT_INTRINSIC_FLAG_F64_TRUNC, + AOT_INTRINSIC_FLAG_F32_RINT, AOT_INTRINSIC_FLAG_F64_RINT, + AOT_INTRINSIC_FLAG_F32_SQRT, AOT_INTRINSIC_FLAG_F64_SQRT, + AOT_INTRINSIC_FLAG_F32_COPYSIGN, AOT_INTRINSIC_FLAG_F64_COPYSIGN, + AOT_INTRINSIC_FLAG_F32_MIN, AOT_INTRINSIC_FLAG_F64_MIN, + AOT_INTRINSIC_FLAG_F32_MAX, AOT_INTRINSIC_FLAG_F64_MAX, + AOT_INTRINSIC_FLAG_I32_CLZ, AOT_INTRINSIC_FLAG_I64_CLZ, + AOT_INTRINSIC_FLAG_I32_CTZ, AOT_INTRINSIC_FLAG_I64_CTZ, + AOT_INTRINSIC_FLAG_I32_POPCNT, AOT_INTRINSIC_FLAG_I64_POPCNT, + AOT_INTRINSIC_FLAG_I32_TO_F64, AOT_INTRINSIC_FLAG_U32_TO_F64, + AOT_INTRINSIC_FLAG_I32_TO_F32, AOT_INTRINSIC_FLAG_U32_TO_F32, + AOT_INTRINSIC_FLAG_I32_TO_F64, AOT_INTRINSIC_FLAG_U64_TO_F64, + AOT_INTRINSIC_FLAG_I64_TO_F32, AOT_INTRINSIC_FLAG_U64_TO_F32, + AOT_INTRINSIC_FLAG_F32_TO_U32, AOT_INTRINSIC_FLAG_F32_TO_I32, + AOT_INTRINSIC_FLAG_F64_TO_U32, AOT_INTRINSIC_FLAG_F64_TO_I32, + AOT_INTRINSIC_FLAG_F64_TO_F32, AOT_INTRINSIC_FLAG_F32_TO_F64, + AOT_INTRINSIC_FLAG_F32_CMP, AOT_INTRINSIC_FLAG_F64_CMP, + AOT_INTRINSIC_FLAG_F32_CONST, AOT_INTRINSIC_FLAG_F64_CONST, +}; + +// To use a test fixture, derive a class from testing::Test. +class AOTTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() { wasm_runtime_destroy(); } + + public: + char global_heap_buf[512 * 1024]; + RuntimeInitArgs init_args; +}; + +TEST_F(AOTTest, aot_value_stack_push_pop) +{ + AOTValueStack *stack; + AOTValue *value1, *value2, *value3; + AOTCompContext comp_ctx = { 0 }; + + stack = (AOTValueStack *)wasm_runtime_malloc(sizeof(AOTValueStack)); + EXPECT_TRUE(stack != NULL); + + memset(stack, 0, sizeof(AOTValueStack)); + + value1 = (AOTValue *)wasm_runtime_malloc(sizeof(AOTValue)); + EXPECT_TRUE(value1 != NULL); + + memset(value1, 0, sizeof(AOTValue)); + value1->type = VALUE_TYPE_I32; + + aot_value_stack_push(&comp_ctx, stack, value1); + EXPECT_EQ(stack->value_list_head, value1); + EXPECT_EQ(stack->value_list_end, value1); + + value2 = (AOTValue *)wasm_runtime_malloc(sizeof(AOTValue)); + EXPECT_TRUE(value2 != NULL); + + memset(value2, 0, sizeof(AOTValue)); + value2->type = VALUE_TYPE_I64; + + aot_value_stack_push(&comp_ctx, stack, value2); + EXPECT_EQ(stack->value_list_head, value1); + EXPECT_EQ(stack->value_list_end, value2); + EXPECT_EQ(value2->prev, value1); + + value3 = aot_value_stack_pop(&comp_ctx, stack); + EXPECT_EQ(value3, value2); + EXPECT_EQ(stack->value_list_head, value1); + EXPECT_EQ(stack->value_list_end, value1); + EXPECT_TRUE(value3->prev == NULL); + + aot_value_stack_destroy(&comp_ctx, stack); + wasm_runtime_free(value3); + wasm_runtime_free(stack); +} + +TEST_F(AOTTest, aot_block_stack_push_pop) +{ + AOTBlockStack *stack; + AOTBlock *block1, *block2, *block3; + AOTCompContext comp_ctx = { 0 }; + + stack = (AOTBlockStack *)wasm_runtime_malloc(sizeof(AOTBlockStack)); + EXPECT_TRUE(stack != NULL); + + memset(stack, 0, sizeof(AOTBlockStack)); + + block1 = (AOTBlock *)wasm_runtime_malloc(sizeof(AOTBlock)); + EXPECT_TRUE(block1 != NULL); + + memset(block1, 0, sizeof(AOTBlock)); + block1->label_type = LABEL_TYPE_LOOP; + + aot_block_stack_push(stack, block1); + EXPECT_EQ(stack->block_list_head, block1); + EXPECT_EQ(stack->block_list_end, block1); + + block2 = (AOTBlock *)wasm_runtime_malloc(sizeof(AOTBlock)); + EXPECT_TRUE(block2 != NULL); + + memset(block2, 0, sizeof(AOTBlock)); + block2->label_type = LABEL_TYPE_IF; + + aot_block_stack_push(stack, block2); + EXPECT_EQ(stack->block_list_head, block1); + EXPECT_EQ(stack->block_list_end, block2); + EXPECT_EQ(block2->prev, block1); + + block3 = aot_block_stack_pop(stack); + EXPECT_EQ(block3, block2); + EXPECT_EQ(stack->block_list_head, block1); + EXPECT_EQ(stack->block_list_end, block1); + EXPECT_TRUE(block3->prev == NULL); + + aot_block_stack_destroy(&comp_ctx, stack); + wasm_runtime_free(block3); + wasm_runtime_free(stack); +} + +TEST_F(AOTTest, aot_intrinsic_fadd_f32) +{ + float32 a = 1.0; + float32 b = 1.0; + EXPECT_EQ(aot_intrinsic_fadd_f32(a, b), (a + b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fadd_f32(a, b), (a + b)); +} + +TEST_F(AOTTest, aot_intrinsic_fadd_f64) +{ + float64 a = 1.0; + float64 b = 1.0; + EXPECT_EQ(aot_intrinsic_fadd_f64(a, b), (a + b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fadd_f64(a, b), (a + b)); +} + +TEST_F(AOTTest, aot_intrinsic_fsub_f32) +{ + float32 a = 1.0; + float32 b = 1.0; + EXPECT_EQ(aot_intrinsic_fsub_f32(a, b), (a - b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fsub_f32(a, b), (a - b)); +} + +TEST_F(AOTTest, aot_intrinsic_fsub_f64) +{ + float64 a = 1.0; + float64 b = 1.0; + EXPECT_EQ(aot_intrinsic_fsub_f64(a, b), (a - b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fsub_f64(a, b), (a - b)); +} + +TEST_F(AOTTest, aot_intrinsic_fmul_f32) +{ + float32 a = 1.0; + float32 b = 1.0; + EXPECT_EQ(aot_intrinsic_fmul_f32(a, b), (a * b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fmul_f32(a, b), (a * b)); +} + +TEST_F(AOTTest, aot_intrinsic_fmul_f64) +{ + float64 a = 1.0; + float64 b = 1.0; + EXPECT_EQ(aot_intrinsic_fmul_f64(a, b), (a * b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fmul_f64(a, b), (a * b)); +} + +TEST_F(AOTTest, aot_intrinsic_fdiv_f32) +{ + float32 a = 1.0; + float32 b = 1.0; + EXPECT_EQ(aot_intrinsic_fdiv_f32(a, b), (a / b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fdiv_f32(a, b), (a / b)); + + a = -1.0; + b = 0.0; + EXPECT_EQ(aot_intrinsic_fdiv_f32(a, b), (a / b)); +} + +TEST_F(AOTTest, aot_intrinsic_fdiv_f64) +{ + float64 a = 1.0; + float64 b = 1.0; + EXPECT_EQ(aot_intrinsic_fdiv_f64(a, b), (a / b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fdiv_f64(a, b), (a / b)); + + a = -1.0; + b = 0.0; + EXPECT_EQ(aot_intrinsic_fdiv_f64(a, b), (a / b)); +} + +TEST_F(AOTTest, aot_intrinsic_fabs_f32) +{ + float32 a = 1.0; + EXPECT_EQ(aot_intrinsic_fabs_f32(a), fabs(a)); + + a = -1.0; + EXPECT_EQ(aot_intrinsic_fabs_f32(a), fabs(a)); + + a = -1.5; + EXPECT_EQ(aot_intrinsic_fabs_f32(a), fabs(a)); +} + +TEST_F(AOTTest, aot_intrinsic_fabs_f64) +{ + float64 a = 1.0; + EXPECT_EQ(aot_intrinsic_fabs_f64(a), fabs(a)); + + a = -1.0; + EXPECT_EQ(aot_intrinsic_fabs_f64(a), fabs(a)); + + a = -1.5; + EXPECT_EQ(aot_intrinsic_fabs_f64(a), fabs(a)); +} + +TEST_F(AOTTest, aot_intrinsic_ceil_f32) +{ + float32 a = 1.0; + EXPECT_EQ(aot_intrinsic_ceil_f32(a), ceilf(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_ceil_f32(a), 2); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_ceil_f32(a), 2); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_ceil_f32(a), -1); +} + +TEST_F(AOTTest, aot_intrinsic_ceil_f64) +{ + float64 a = 1.0; + EXPECT_EQ(aot_intrinsic_ceil_f64(a), ceil(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_ceil_f64(a), 2); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_ceil_f64(a), 2); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_ceil_f64(a), -1); +} + +TEST_F(AOTTest, aot_intrinsic_floor_f32) +{ + float32 a = 1.0; + EXPECT_EQ(aot_intrinsic_floor_f32(a), floorf(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_floor_f32(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_floor_f32(a), 1); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_floor_f32(a), -2); +} + +TEST_F(AOTTest, aot_intrinsic_floor_f64) +{ + float64 a = 1.0; + EXPECT_EQ(aot_intrinsic_floor_f64(a), floor(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_floor_f64(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_floor_f64(a), 1); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_floor_f64(a), -2); +} + +TEST_F(AOTTest, aot_intrinsic_trunc_f32) +{ + float32 a = 1.0; + EXPECT_EQ(aot_intrinsic_trunc_f32(a), trunc(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_trunc_f32(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_trunc_f32(a), 1); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_trunc_f32(a), -1); +} + +TEST_F(AOTTest, aot_intrinsic_trunc_f64) +{ + float64 a = 1.0; + EXPECT_EQ(aot_intrinsic_trunc_f64(a), trunc(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_trunc_f64(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_trunc_f64(a), 1); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_trunc_f64(a), -1); +} + +TEST_F(AOTTest, aot_intrinsic_rint_f32) +{ + float32 a = 1.0; + EXPECT_EQ(aot_intrinsic_rint_f32(a), rint(a)); + EXPECT_EQ(aot_intrinsic_rint_f32(a), 1); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_rint_f32(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_rint_f32(a), 2); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_rint_f32(a), -2); +} + +TEST_F(AOTTest, aot_intrinsic_rint_f64) +{ + float64 a = 1.0; + EXPECT_EQ(aot_intrinsic_rint_f64(a), rint(a)); + EXPECT_EQ(aot_intrinsic_rint_f64(a), 1); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_rint_f64(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_rint_f64(a), 2); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_rint_f64(a), -2); +} + +TEST_F(AOTTest, aot_intrinsic_sqrt_f32) +{ + float32 a = 2.0; + EXPECT_EQ(aot_intrinsic_sqrt_f32(a), sqrt(a)); + + a = 2; + EXPECT_EQ(aot_intrinsic_sqrt_f32(a), sqrt(a)); +} + +TEST_F(AOTTest, aot_intrinsic_sqrt_f64) +{ + float64 a = 2.0; + EXPECT_EQ(aot_intrinsic_sqrt_f64(a), sqrt(a)); + + a = 2; + EXPECT_EQ(aot_intrinsic_sqrt_f64(a), sqrt(a)); +} + +TEST_F(AOTTest, aot_intrinsic_copysign_f32) +{ + float32 a = 20.0; + float32 b = 2.0; + + EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), fabs(a)); + + b = 1.5; + EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), fabs(a)); + + b = -2.0; + EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), -fabs(a)); + + a = -20.0; + b = -1.5; + EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), -fabs(a)); +} + +TEST_F(AOTTest, aot_intrinsic_copysign_f64) +{ + float64 a = 20.0; + float64 b = 2.0; + + EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), fabs(a)); + + b = 1.5; + EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), fabs(a)); + + b = -2.0; + EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), -fabs(a)); + + a = -20.0; + b = -1.5; + EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), -fabs(a)); +} + +TEST_F(AOTTest, aot_intrinsic_fmin_f32) +{ + float32 a = 1.2; + float32 b = 2.5; + + EXPECT_EQ(aot_intrinsic_fmin_f32(a, b), a); + + a = -3; + b = -1; + EXPECT_EQ(aot_intrinsic_fmin_f32(a, b), a); + + b = 1; + EXPECT_EQ(aot_intrinsic_fmin_f32('a', b), b); + + a = 3; + EXPECT_EQ(aot_intrinsic_fmin_f32(a, 'b'), a); + + EXPECT_EQ(aot_intrinsic_fmin_f32('a', 'b'), 'a'); + + EXPECT_EQ(aot_intrinsic_fmin_f32('b', 'c'), 'b'); + EXPECT_EQ(aot_intrinsic_fmin_f32('c', 'b'), 'b'); + + EXPECT_EQ(aot_intrinsic_fmin_f32(true, 2.5), 1); + EXPECT_EQ(aot_intrinsic_fmin_f32(1.0, false), 0); + + EXPECT_NE(aot_intrinsic_fmin_f32(sqrt(-1), 3), 3); + EXPECT_NE(aot_intrinsic_fmin_f32(3, sqrt(-1)), 3); +} + +TEST_F(AOTTest, aot_intrinsic_fmin_f64) +{ + float64 a = 1.00000000; + float64 b = 3.00000000; + + EXPECT_EQ(aot_intrinsic_fmin_f64(a, b), a); + + EXPECT_EQ(aot_intrinsic_fmin_f64(-a, b), -a); + + EXPECT_EQ(aot_intrinsic_fmin_f64(-a, -b), -b); + + EXPECT_EQ(aot_intrinsic_fmin_f64(a, -b), -b); + + EXPECT_EQ(aot_intrinsic_fmin_f64(a, a), a); + + a = 0.0000; + EXPECT_EQ(aot_intrinsic_fmin_f64(-a, -a), -a); +} + +TEST_F(AOTTest, aot_intrinsic_fmax_f32) +{ + float32 a = 1.2; + float32 b = 2.5; + + EXPECT_EQ(aot_intrinsic_fmax_f32(a, b), b); + + a = -3; + b = -1; + EXPECT_EQ(aot_intrinsic_fmax_f32(a, b), b); + + b = 1; + EXPECT_EQ(aot_intrinsic_fmax_f32('a', b), 'a'); + + a = 3; + EXPECT_EQ(aot_intrinsic_fmax_f32(a, 'b'), 'b'); + + EXPECT_EQ(aot_intrinsic_fmax_f32('a', 'b'), 'b'); + + EXPECT_EQ(aot_intrinsic_fmax_f32(' ', 'b'), 'b'); + EXPECT_EQ(aot_intrinsic_fmax_f32('a', ' '), 'a'); + + EXPECT_NE(aot_intrinsic_fmax_f32(sqrt(-1), 3), 3); + EXPECT_NE(aot_intrinsic_fmax_f32(3, sqrt(-1)), 3); +} + +TEST_F(AOTTest, aot_intrinsic_fmax_f64) +{ + float64 a = 1.00000000; + float64 b = 3.00000000; + + EXPECT_EQ(aot_intrinsic_fmax_f64(a, b), b); + + EXPECT_EQ(aot_intrinsic_fmax_f64(-a, b), b); + + EXPECT_EQ(aot_intrinsic_fmax_f64(-a, -b), -a); + + EXPECT_EQ(aot_intrinsic_fmax_f64(a, -b), a); + + EXPECT_EQ(aot_intrinsic_fmax_f64(a, a), a); + + a = 0.0000; + EXPECT_EQ(aot_intrinsic_fmax_f64(-a, -a), -a); + + EXPECT_EQ(aot_intrinsic_fmax_f64(-0, -0), -0); +} + +TEST_F(AOTTest, aot_intrinsic_clz_i32) +{ + uint32 type = 0; + uint32 data = 0; + uint32 num = 0; + + EXPECT_EQ(aot_intrinsic_clz_i32(0), 32); + + for (uint32 i = 0; i < 0xFFFF; i++) { + /* Generate random numbers [1,0xFFFFFFFF] */ + type = 1 + (rand() % (0xFFFFFFFF - 1 + 1)); + data = type; + while (!(type & 0x80000000)) { + num++; + type <<= 1; + } + EXPECT_EQ(aot_intrinsic_clz_i32(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_clz_i32(0xFFFFFFFF), 0); +} + +TEST_F(AOTTest, aot_intrinsic_clz_i64) +{ + uint64 type = 0; + uint64 data = 0; + uint64 num = 0; + + EXPECT_EQ(aot_intrinsic_clz_i64(0), 64); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + /* Generate random numbers [1,0xFFFFFFFFFFFFFFFF] */ + type = 1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1)); + data = type; + while (!(type & 0x8000000000000000LL)) { + num++; + type <<= 1; + } + EXPECT_EQ(aot_intrinsic_clz_i64(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_clz_i64(0xFFFFFFFFFFFFFFFF), 0); +} + +TEST_F(AOTTest, ast_intrinsic_ctz_i32) +{ + uint32 type = 0; + uint32 data = 0; + uint32 num = 0; + + EXPECT_EQ(aot_intrinsic_ctz_i32(0), 32); + + for (uint32 i = 0; i < 0xFFFF; i++) { + type = 1 + (rand() % (0xFFFFFFFF - 1 + 1)); + data = type; + while (!(type & 1)) { + num++; + type >>= 1; + } + EXPECT_EQ(aot_intrinsic_ctz_i32(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_ctz_i32(0xFFFFFFFF), 0); +} + +TEST_F(AOTTest, ast_intrinsic_ctz_i64) +{ + uint64 type = 0; + uint64 data = 0; + uint64 num = 0; + + EXPECT_EQ(aot_intrinsic_ctz_i64(0), 64); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + type = 1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1)); + data = type; + while (!(type & 1)) { + num++; + type >>= 1; + } + EXPECT_EQ(aot_intrinsic_ctz_i64(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_ctz_i64(0xFFFFFFFFFFFFFFFF), 0); +} + +TEST_F(AOTTest, aot_intrinsic_popcnt_i32) +{ + uint32 data = 0; + uint32 num = 0; + uint32 temp = 0; + + EXPECT_EQ(aot_intrinsic_popcnt_i32(0), 0); + + for (uint32 i = 0; i < 0xFFFF; i++) { + temp = 1 + (rand() % (0x100000000 - 1 + 1)); + data = temp; + + while (temp) { + if (temp & 0x01) + num++; + temp >>= 1; + } + EXPECT_EQ(aot_intrinsic_popcnt_i32(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_popcnt_i32(0xFFFFFFFF), 32); +} + +TEST_F(AOTTest, aot_intrinsic_popcnt_i64) +{ + uint64 data = 0; + uint64 num = 0; + uint64 temp = 0; + + EXPECT_EQ(aot_intrinsic_popcnt_i64(0x00), 0); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + temp = 1 + (rand() % (0xFFFFFFFFFFFFFFFFLL - 1 + 1)); + data = temp; + + while (temp) { + if (temp & 0x01) + num++; + temp >>= 1; + } + EXPECT_EQ(aot_intrinsic_popcnt_i64(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_popcnt_i64(0xFFFFFFFFFFFFFFFF), 64); +} + +TEST_F(AOTTest, aot_intrinsic_i32_to_f32) +{ + int32 idata = 0; + + EXPECT_EQ(aot_intrinsic_i32_to_f32(idata), (float32)idata); + + for (uint32 i = 0; i < 0xFFFF; i++) { + idata = (int32)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_i32_to_f32(idata), (float32)idata); + } + + idata = 0xFFFFFFFF; + EXPECT_EQ(aot_intrinsic_i32_to_f32(idata), (float32)idata); +} + +TEST_F(AOTTest, aot_intrinsic_u32_to_f32) +{ + uint32 udata = 0; + + EXPECT_EQ(aot_intrinsic_u32_to_f32(udata), (float32)udata); + + for (uint32 i = 0; i < 0xFFFF; i++) { + udata = (uint32)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_u32_to_f32(udata), (float32)udata); + } + + udata = 0xFFFFFFFF; + EXPECT_EQ(aot_intrinsic_u32_to_f32(udata), (float32)udata); +} + +TEST_F(AOTTest, aot_intrinsic_i32_to_f64) +{ + int32 idata = 0; + + EXPECT_EQ(aot_intrinsic_i32_to_f64(idata), (float64)idata); + + for (uint32 i = 0; i < 0xFFFF; i++) { + idata = (int32)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_i32_to_f64(idata), (float64)idata); + } + + idata = 0xFFFFFFFF; + EXPECT_EQ(aot_intrinsic_i32_to_f64(idata), (float64)idata); +} + +TEST_F(AOTTest, aot_intrinsic_u32_to_f64) +{ + uint32 udata = 0; + + EXPECT_EQ(aot_intrinsic_u32_to_f64(udata), (float64)udata); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + udata = (uint32)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_u32_to_f64(udata), (float64)udata); + } + + udata = 0xFFFFFFFF; + EXPECT_EQ(aot_intrinsic_u32_to_f64(udata), (float64)udata); +} + +TEST_F(AOTTest, aot_intrinsic_i64_to_f32) +{ + int64 idata = 0LL; + + EXPECT_EQ(aot_intrinsic_i64_to_f32(idata), (float32)idata); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + idata = (int64)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_i64_to_f32(idata), (float32)idata); + } + + idata = 0xFFFFFFFFFFFFFFFFLL; + EXPECT_EQ(aot_intrinsic_i64_to_f32(idata), (float32)idata); +} + +TEST_F(AOTTest, aot_intrinsic_u64_to_f32) +{ + uint64 udata = 0LL; + + EXPECT_EQ(aot_intrinsic_u64_to_f32(udata), (float32)udata); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + udata = (uint64)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_u64_to_f32(udata), (float32)udata); + } + + udata = 0xFFFFFFFFFFFFFFFFLL; + EXPECT_EQ(aot_intrinsic_u64_to_f32(udata), (float32)udata); +} + +TEST_F(AOTTest, aot_intrinsic_i64_to_f64) +{ + int64 idata = 0LL; + + EXPECT_EQ(aot_intrinsic_i64_to_f64(idata), float64(idata)); + + for (uint32_t i = 0; i < 0xFFFFF; i++) { + idata = (int64)(1 + (rand() % (0xFFFFFFFFFFFFFFFLL - 1 + 1))); + EXPECT_EQ(aot_intrinsic_i64_to_f64(idata), (float64)idata); + } + + idata = 0xFFFFFFFFFFFFFFFFLL; + EXPECT_EQ(aot_intrinsic_i64_to_f64(idata), (float64)idata); +} + +TEST_F(AOTTest, aot_intrinsic_u64_to_f64) +{ + uint64 udata = 0LL; + + EXPECT_EQ(aot_intrinsic_u64_to_f64(udata), float64(udata)); + + for (uint32_t i = 0; i < 0xFFFFF; i++) { + udata = (uint64)(1 + (rand() % (0xFFFFFFFFFFFFFFFLL - 1 + 1))); + EXPECT_EQ(aot_intrinsic_u64_to_f64(udata), (float64)udata); + } + + udata = 0xFFFFFFFFFFFFFFFFLL; + EXPECT_EQ(aot_intrinsic_u64_to_f64(udata), (float64)udata); +} + +TEST_F(AOTTest, aot_intrinsic_f32_to_i32) +{ + float32 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f32_to_i32(data), (int32)data); + + for (uint32 i = 0; i < 0xFFFF; i++) { + data = (float32)((1 + (rand() % (100 - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f32_to_i32(data), (int32)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f32_to_u32) +{ + float32 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f32_to_u32(data), (uint32)data); + + for (uint32 i = 0; i < 0xFFFF; i++) { + data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f32_to_u32(data), (uint32)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f32_to_i64) +{ + float32 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f32_to_i64(data), (int64)data); + + for (uint32 i = 0; i < 0xFFFF; i++) { + data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f32_to_i64(data), (int64)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f32_to_u64) +{ + float32 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f32_to_u64(data), (uint64)data); + + for (uint32 i = 0; i < 0xFFFF; i++) { + data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f32_to_u64(data), (uint64)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f64_to_i32) +{ + float64 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f64_to_i32(data), (int32)data); + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f64_to_i32(data), (int32)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f64_to_u32) +{ + float64 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f64_to_u32(data), (uint32)data); + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f64_to_u32(data), (uint32)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f64_to_i64) +{ + float64 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f64_to_i64(data), (int64)data); + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f64_to_i64(data), (int64)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f64_to_u64) +{ + float64 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f64_to_u64(data), (uint64)data); + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f64_to_u64(data), (uint64)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f32_to_f64) +{ + float32 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f32_to_f64(data), (float64)data); + + for (uint32 i = 0; i < 0xFFFF; i++) { + data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f32_to_f64(data), (float64)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f64_to_f32) +{ + float64 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f64_to_f32(data), (float32)data); + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.06); + EXPECT_EQ(aot_intrinsic_f32_to_f64(data), (float32)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f32_cmp) +{ + float32 lhs = 0.0; + float32 rhs = 0.0; + AOTFloatCond index = FLOAT_EQ; + uint32 res = 0; + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + index = (AOTFloatCond)(1 + (rand() % (6 - 1 + 1))); + lhs = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + rhs = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + + /* cond : 0 */ + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_EQ, lhs, rhs), + lhs == rhs ? 1 : 0); + + /* cond : 1-6 */ + switch (index) { + case FLOAT_LT: // 2 + res = (lhs < rhs ? 1 : 0); + break; + case FLOAT_GT: // 3 + res = (lhs > rhs ? 1 : 0); + break; + case FLOAT_LE: // 4 + res = (lhs <= rhs ? 1 : 0); + break; + case FLOAT_GE: // 5 + res = (lhs >= rhs ? 1 : 0); + break; + case FLOAT_NE: // 1 + res = (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0; + break; + case FLOAT_UNO: // 6 + res = (isnan(lhs) || isnan(rhs)) ? 1 : 0; + break; + + default: + break; + } + + EXPECT_EQ(aot_intrinsic_f32_cmp(index, lhs, rhs), res); + index = FLOAT_EQ; + + /* cond : > 6 */ + EXPECT_EQ(aot_intrinsic_f32_cmp((AOTFloatCond)(i + 7), lhs, rhs), 0); + } + + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_NE, true, false), 1); + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_NE, true, true), 0); + + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_UNO, true, false), 0); + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_UNO, true, true), 0); + + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_UNO, 'a', 'b'), 0); +} + +TEST_F(AOTTest, aot_intrinsic_f64_cmp) +{ + float64 lhs = 0.0; + float64 rhs = 0.0; + AOTFloatCond index = FLOAT_EQ; + uint32 res = 0; + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + index = (AOTFloatCond)(1 + (rand() % (6 - 1 + 1))); + lhs = (float32)((1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1))) - 0.05); + rhs = (float32)((1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1))) - 0.05); + + /* cond : 0 */ + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_EQ, lhs, rhs), + lhs == rhs ? 1 : 0); + + /* cond : 1-6 */ + switch (index) { + case FLOAT_LT: // 2 + res = (lhs < rhs ? 1 : 0); + break; + case FLOAT_GT: // 3 + res = (lhs > rhs ? 1 : 0); + break; + case FLOAT_LE: // 4 + res = (lhs <= rhs ? 1 : 0); + break; + case FLOAT_GE: // 5 + res = (lhs >= rhs ? 1 : 0); + break; + case FLOAT_NE: // 1 + res = (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0; + break; + case FLOAT_UNO: // 6 + res = (isnan(lhs) || isnan(rhs)) ? 1 : 0; + break; + + default: + break; + } + + EXPECT_EQ(aot_intrinsic_f64_cmp(index, lhs, rhs), res); + index = FLOAT_EQ; + + /* cond : > 6 */ + EXPECT_EQ(aot_intrinsic_f64_cmp((AOTFloatCond)(i + 7), lhs, rhs), 0); + } + + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_NE, true, false), 1); + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_NE, true, true), 0); + + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_UNO, true, false), 0); + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_UNO, true, true), 0); + + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_UNO, 'a', 'b'), 0); +} + +TEST_F(AOTTest, aot_intrinsic_get_symbol) +{ + const char *llvm_intrinsic_t = NULL; + + for (int i = 0; i < 2; i++) { + if (i == 0) + llvm_intrinsic_t = CONS(32); + else + llvm_intrinsic_t = CONS(64); + + EXPECT_EQ((const char *)aot_intrinsic_get_symbol(llvm_intrinsic_t), + (const char *)NULL); + } + + for (int i = 0; i < G_INTRINSIC_COUNT - 2; i++) { + EXPECT_NE((const char *)aot_intrinsic_get_symbol(llvm_intrinsic_tmp[i]), + (const char *)NULL); + } +} + +TEST_F(AOTTest, aot_intrinsic_check_capability) +{ + AOTCompContext *comp_ctx = NULL; + AOTCompContext scomp_ctx = { 0 }; + const char *llvm_intrinsic_t = "f64_cmp"; + bool res = false; + uint64 flag = 0; + uint64 group = 0; + + comp_ctx = &scomp_ctx; + memset(comp_ctx->flags, 0, sizeof(comp_ctx->flags)); + + /* + EXPECT_FALSE(aot_intrinsic_check_capability(comp_ctx, (const char + *)NULL)); EXPECT_FALSE(aot_intrinsic_check_capability((const + AOTCompContext *)NULL, llvm_intrinsic_t)); + */ + + EXPECT_FALSE(aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_t)); + for (int i = 0; i < G_INTRINSIC_COUNT; i++) { + EXPECT_FALSE( + aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_tmp[i])); + } + + memset(comp_ctx->flags, 1, sizeof(comp_ctx->flags)); + EXPECT_FALSE(aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_t)); + for (int i = 0; i < G_INTRINSIC_COUNT; i++) { + flag = g_intrinsic_flag[i]; + group = AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag); + flag &= AOT_INTRINSIC_FLAG_MASK; + + res = aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_tmp[i]); + if ((flag & 0x01) || (flag & 0x100) || (flag & 0x10000) + || (flag & 0x1000000)) + EXPECT_TRUE(res); + else + EXPECT_FALSE(res); + } +} + +TEST_F(AOTTest, aot_intrinsic_fill_capability_flags) +{ + // AOTCompContext *comp_ctx = NULL; + AOTCompContext scomp_ctx = { 0 }; + + // comp_ctx = &scomp_ctx; + aot_intrinsic_fill_capability_flags(&scomp_ctx); + + AOTCompContext scomp_ctx_1{ + .target_cpu = (char *)"cortex-m7", + }; + strncpy(scomp_ctx_1.target_arch, "thumb", strlen("thumb")); + aot_intrinsic_fill_capability_flags(&scomp_ctx_1); + + AOTCompContext scomp_ctx_2{ + .target_cpu = (char *)"cortex-m4", + }; + strncpy(scomp_ctx_2.target_arch, "thumb", strlen("thumb")); + aot_intrinsic_fill_capability_flags(&scomp_ctx_2); + + AOTCompContext scomp_ctx_3{ + .target_cpu = (char *)"cortex-m4", + }; + strncpy(scomp_ctx_3.target_arch, "riscv", strlen("riscv")); + aot_intrinsic_fill_capability_flags(&scomp_ctx_3); + + AOTCompContext scomp_ctx_4{ + .target_cpu = (char *)"cortex-m4", + }; + strncpy(scomp_ctx_4.target_arch, "intrinsic", strlen("intrinsic")); + aot_intrinsic_fill_capability_flags(&scomp_ctx_4); +} diff --git a/tests/unit/common/mock_allocator.h b/tests/unit/common/mock_allocator.h new file mode 100644 index 0000000000..a57e2dea39 --- /dev/null +++ b/tests/unit/common/mock_allocator.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#pragma once + +#include "wasm_export.h" +#include + +template +class MockAllocator +{ + private: + RuntimeInitArgs init_args; + + public: + MockAllocator() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = (void *)my_malloc; + init_args.mem_alloc_option.allocator.realloc_func = (void *)realloc; + init_args.mem_alloc_option.allocator.free_func = (void *)free; + + /* Set count to INT32_MIN so the initialization will not fail */ + alloc_count = INT32_MIN; + + wasm_runtime_full_init(&init_args); + reset_count(); + } + + ~MockAllocator() { wasm_runtime_destroy(); } + + void reset_count() { alloc_count = 0; } + + protected: + static int32_t alloc_count; + static void *my_malloc(int32_t size) + { + if (alloc_count >= MaxAllocCount) { + return nullptr; + } + + alloc_count++; + + return malloc(size); + } +}; + +template +int32_t MockAllocator::alloc_count = 0; + +class DumpAllocUsage : public MockAllocator +{ + public: + DumpAllocUsage() + : MockAllocator() + {} + + ~DumpAllocUsage() + { + std::cout << "Alloc usage count: " << alloc_count << std::endl; + } +}; + +template +void +LIMIT_MALLOC_COUNT(std::function func) +{ + { + MockAllocator allocator; + func(); + } + + if (AllocRequired > 1) + LIMIT_MALLOC_COUNT(func); +} + +template<> +void +LIMIT_MALLOC_COUNT<0>(std::function func) +{ + { + MockAllocator<0> allocator; + func(); + } +} diff --git a/tests/unit/common/test_helper.h b/tests/unit/common/test_helper.h new file mode 100644 index 0000000000..4db465fc8d --- /dev/null +++ b/tests/unit/common/test_helper.h @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#pragma once + +#include "wasm_export.h" +#include "gtest/gtest.h" + +#include +#include +#include + +template +class WAMRRuntimeRAII +{ + private: + char global_heap_buf[Size]; + RuntimeInitArgs init_args; + + public: + WAMRRuntimeRAII() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + wasm_runtime_full_init(&init_args); + } + + ~WAMRRuntimeRAII() { wasm_runtime_destroy(); } +}; + +class WAMRModule +{ + private: + wasm_module_t module_; + + public: + WAMRModule(uint8_t *buffer, uint32_t size) + { + module_ = wasm_runtime_load(buffer, size, NULL, 0); + } + + ~WAMRModule() { wasm_runtime_unload(module_); } + + wasm_module_t get() const { return module_; } +}; + +class WAMRInstance +{ + private: + wasm_module_inst_t module_inst_; + + public: + WAMRInstance(WAMRModule &module, uint32_t stack_size = 8192, + uint32_t heap_size = 8192) + { + module_inst_ = wasm_runtime_instantiate(module.get(), stack_size, + heap_size, NULL, 0); + } + + ~WAMRInstance() { wasm_runtime_deinstantiate(module_inst_); } + + wasm_module_inst_t get() const { return module_inst_; } +}; + +class WAMRExecEnv +{ + private: + wasm_exec_env_t exec_env_; + + public: + WAMRExecEnv(WAMRInstance &instance, uint32_t stack_size = 8192) + { + exec_env_ = wasm_runtime_create_exec_env(instance.get(), stack_size); + } + + ~WAMRExecEnv() { wasm_runtime_destroy_exec_env(exec_env_); } + + wasm_exec_env_t get() const { return exec_env_; } + wasm_module_inst_t get_inst() const + { + return wasm_runtime_get_module_inst(exec_env_); + } +}; + +static uint8_t dummy_wasm_buffer[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x05, 0x03, 0x01, 0x00, + 0x02, 0x06, 0x08, 0x01, 0x7F, 0x01, 0x41, 0x80, 0x88, 0x04, 0x0B, 0x07, + 0x0A, 0x01, 0x06, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x00, + 0x19, 0x04, 0x6E, 0x61, 0x6D, 0x65, 0x07, 0x12, 0x01, 0x00, 0x0F, 0x5F, + 0x5F, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74, + 0x65, 0x72, 0x00, 0x76, 0x09, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, + 0x72, 0x73, 0x01, 0x0C, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x65, + 0x64, 0x2D, 0x62, 0x79, 0x01, 0x05, 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x56, + 0x31, 0x33, 0x2E, 0x30, 0x2E, 0x30, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, + 0x73, 0x3A, 0x2F, 0x2F, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, + 0x6F, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, + 0x2D, 0x70, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x20, 0x66, 0x64, 0x31, + 0x64, 0x38, 0x63, 0x32, 0x66, 0x30, 0x34, 0x64, 0x64, 0x65, 0x32, 0x33, + 0x62, 0x65, 0x65, 0x30, 0x66, 0x62, 0x33, 0x61, 0x37, 0x64, 0x30, 0x36, + 0x39, 0x61, 0x39, 0x62, 0x31, 0x30, 0x34, 0x36, 0x64, 0x61, 0x39, 0x37, + 0x39, 0x29 +}; + +class DummyExecEnv +{ + private: + std::shared_ptr dummy_exec_env_; + std::shared_ptr inst_; + std::shared_ptr mod_; + std::vector my_wasm_buffer; + + private: + void construct(uint8_t *buf, uint32_t len) + { + std::vector buffer(buf, buf + len); + my_wasm_buffer = buffer; + + mod_ = std::make_shared(my_wasm_buffer.data(), + my_wasm_buffer.size()); + EXPECT_NE(mod_.get(), nullptr); + inst_ = std::make_shared(*mod_); + EXPECT_NE(inst_.get(), nullptr); + dummy_exec_env_ = std::make_shared(*inst_); + EXPECT_NE(dummy_exec_env_.get(), nullptr); + } + + public: + DummyExecEnv() { construct(dummy_wasm_buffer, sizeof(dummy_wasm_buffer)); } + + DummyExecEnv(uint8_t *buf, uint32_t len) { construct(buf, len); } + + DummyExecEnv(std::string filename) + { + std::ifstream wasm_file(filename, std::ios::binary); + std::vector buffer(std::istreambuf_iterator(wasm_file), + {}); + + construct(buffer.data(), buffer.size()); + } + + ~DummyExecEnv() {} + + wasm_exec_env_t get() const { return dummy_exec_env_->get(); } + + void *app_to_native(uint32_t app_addr) const + { + return wasm_runtime_addr_app_to_native(inst_->get(), app_addr); + } + + uint32_t native_to_app(void *ptr) const + { + return wasm_runtime_addr_native_to_app(inst_->get(), ptr); + } + + const char *get_exception() const + { + return wasm_runtime_get_exception(inst_->get()); + } + + void set_exception(std::string str) const + { + wasm_runtime_set_exception(inst_->get(), str.c_str()); + } + + void clear_exception() const { wasm_runtime_clear_exception(inst_->get()); } + + bool execute(const char *func_name, uint32_t argc, uint32_t argv[]) + { + wasm_function_inst_t func; + + if (!(func = wasm_runtime_lookup_function(inst_->get(), func_name))) { + return false; + } + + return wasm_runtime_call_wasm(dummy_exec_env_->get(), func, argc, argv); + } +}; + +class WAMRVaList +{ + private: + void *buffer_; + uint32_t current_loc_; + uint32_t capacity_; + wasm_exec_env_t exec_env_; + + void _append(void *ptr, uint32_t size) + { + if (current_loc_ + size >= capacity_) { + capacity_ *= 2; + buffer_ = realloc(buffer_, capacity_); + ASSERT_NE(buffer_, nullptr); + } + + memcpy((void *)((uintptr_t)buffer_ + current_loc_), ptr, size); + current_loc_ += size; + } + + public: + explicit WAMRVaList(wasm_exec_env_t exec_env) + : exec_env_(exec_env) + { + capacity_ = 64; + buffer_ = malloc(capacity_); + EXPECT_NE(buffer_, nullptr); + current_loc_ = 0; + } + + ~WAMRVaList() + { + current_loc_ = 0; + free(buffer_); + } + + template + void add(T arg) + { + if (std::is_floating_point::value) { + /* float data should be 8 bytes aligned */ + current_loc_ = ((current_loc_ + 7) & ~7); + _append(&arg, sizeof(T)); + } + else if (std::is_integral::value) { + if (sizeof(T) > 4) { + current_loc_ = ((current_loc_ + 7) & ~7); + } + _append(&arg, sizeof(T)); + } + } + + void add(std::string arg) + { + void *native_addr; + auto inst = wasm_runtime_get_module_inst(exec_env_); + uint32_t addr = + wasm_runtime_module_malloc(inst, arg.size() + 1, &native_addr); + ASSERT_NE(addr, 0); + memcpy(native_addr, arg.data(), arg.size()); + *(char *)((uintptr_t)native_addr + arg.size()) = 0; + _append(&addr, sizeof(uint32_t)); + } + + void add(const char *arg) { add(std::string(arg)); } + + char *get() const + { + auto inst = wasm_runtime_get_module_inst(exec_env_); + uint32_t addr = wasm_runtime_module_dup_data( + inst, (const char *)buffer_, current_loc_); + EXPECT_NE(addr, 0); + return (char *)wasm_runtime_addr_app_to_native(inst, addr); + } +}; + +/* Get memory space in app */ +class AppMemory +{ + private: + wasm_exec_env_t exec_env_; + void *native_addr_; + uint32_t app_addr_; + + public: + AppMemory(wasm_exec_env_t exec_env, uint32_t size) + : exec_env_(exec_env) + { + app_addr_ = wasm_runtime_module_malloc(get_module_inst(exec_env_), size, + &native_addr_); + } + + ~AppMemory() + { + wasm_runtime_module_free(get_module_inst(exec_env_), app_addr_); + } + + void *get_native_addr() const + { + return wasm_runtime_addr_app_to_native(get_module_inst(exec_env_), + app_addr_); + } + uint32_t get_app_addr() const { return app_addr_; } +}; + +/* Put the data to app */ +class AppData +{ + private: + wasm_exec_env_t exec_env_; + void *native_addr_; + uint32_t app_addr_; + + public: + AppData(wasm_exec_env_t exec_env, void *data, uint32_t size) + : exec_env_(exec_env) + { + app_addr_ = wasm_runtime_module_dup_data(get_module_inst(exec_env_), + (const char *)data, size); + } + + AppData(wasm_exec_env_t exec_env, std::string str) + : exec_env_(exec_env) + { + app_addr_ = wasm_runtime_module_dup_data(get_module_inst(exec_env_), + (const char *)str.c_str(), + str.size() + 1); + } + + ~AppData() + { + wasm_runtime_module_free(get_module_inst(exec_env_), app_addr_); + } + + void *get_native_addr() const + { + return wasm_runtime_addr_app_to_native(get_module_inst(exec_env_), + app_addr_); + } + uint32_t get_app_addr() const { return app_addr_; } +}; \ No newline at end of file diff --git a/tests/unit/compilation/CMakeLists.txt b/tests/unit/compilation/CMakeLists.txt new file mode 100644 index 0000000000..0941a39ccf --- /dev/null +++ b/tests/unit/compilation/CMakeLists.txt @@ -0,0 +1,72 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-compilation) + +add_definitions (-DRUN_ON_LINUX) + +add_definitions (-Dattr_container_malloc=malloc) +add_definitions (-Dattr_container_free=free) +add_definitions (-DWASM_ENABLE_WAMR_COMPILER=1) +add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1) +add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) +set (WAMR_BUILD_THREAD_MGR 1) +set (WAMR_BUILD_AOT 1) + +include (../unit_common.cmake) + +set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") +if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif () +set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include (${IWASM_DIR}/compilation/iwasm_compl.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${LIB_HOST_AGENT_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} + ) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable (compilation_test ${unit_test_sources}) + +target_link_libraries (compilation_test ${LLVM_AVAILABLE_LIBS} gtest_main ) + +add_custom_command(TARGET compilation_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/main.wasm + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copy main.wasm to the directory: build/compilation." +) + +gtest_discover_tests(compilation_test) diff --git a/tests/unit/compilation/aot_compiler_test.cc b/tests/unit/compilation/aot_compiler_test.cc new file mode 100644 index 0000000000..8592a4b610 --- /dev/null +++ b/tests/unit/compilation/aot_compiler_test.cc @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "wasm_export.h" +#include "aot_export.h" +#include "bh_read_file.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +extern "C" { +char * +aot_generate_tempfile_name(const char *prefix, const char *extension, + char *buffer, uint32 len); +} + +class aot_compiler_test_suit : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +void +test_aot_emit_object_file_with_option(AOTCompOption *option_ptr) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + aot_comp_data_t comp_data = nullptr; + aot_comp_context_t comp_ctx = nullptr; + char out_file_name[] = "test.aot"; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data(wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + + comp_ctx = aot_create_comp_context(comp_data, option_ptr); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_STREQ(aot_get_last_error(), ""); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + EXPECT_TRUE(aot_emit_object_file(comp_ctx, out_file_name)); +} + +TEST_F(aot_compiler_test_suit, aot_emit_object_file) +{ + AOTCompOption option = { 0 }; + uint32_t i = 0; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + // Test opt_level in range from 0 to 3. + for (i = 0; i <= 3; i++) { + option.opt_level = i; + test_aot_emit_object_file_with_option(&option); + } + + // Test size_level in range from 0 to 3. + option.opt_level = 3; + for (i = 0; i <= 3; i++) { + option.size_level = i; + test_aot_emit_object_file_with_option(&option); + } + + // Test output_format in range from AOT_FORMAT_FILE to AOT_LLVMIR_OPT_FILE. + option.size_level = 3; + for (i = AOT_FORMAT_FILE; i <= AOT_LLVMIR_OPT_FILE; i++) { + option.output_format = i; + test_aot_emit_object_file_with_option(&option); + } + + // Test bounds_checks in range 0 to 2. + option.output_format = AOT_FORMAT_FILE; + for (i = 0; i <= 2; i++) { + option.bounds_checks = i; + test_aot_emit_object_file_with_option(&option); + } + + // Test all enable option is false. + option.bounds_checks = 2; + option.enable_simd = false; + option.enable_aux_stack_check = false; + option.enable_bulk_memory = false; + option.enable_ref_types = false; + test_aot_emit_object_file_with_option(&option); +} + +TEST_F(aot_compiler_test_suit, aot_emit_llvm_file) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + aot_comp_data_t comp_data = nullptr; + aot_comp_context_t comp_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "out_file_name_test"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data(wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_STREQ(aot_get_last_error(), ""); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + EXPECT_EQ(true, aot_emit_llvm_file(comp_ctx, out_file_name)); +} + +TEST_F(aot_compiler_test_suit, aot_generate_tempfile_name) +{ + char obj_file_name[64]; + + // Test common case. + aot_generate_tempfile_name("wamrc-obj", "o", obj_file_name, + sizeof(obj_file_name)); + EXPECT_NE(nullptr, strstr(obj_file_name, ".o")); + + // Test abnormal cases. + EXPECT_EQ(nullptr, + aot_generate_tempfile_name("wamrc-obj", "o", obj_file_name, 0)); + char obj_file_name_1[20]; + EXPECT_EQ(nullptr, aot_generate_tempfile_name( + "wamrc-obj", "12345678901234567890", obj_file_name_1, + sizeof(obj_file_name_1))); +} diff --git a/tests/unit/compilation/aot_emit_aot_file_test.cc b/tests/unit/compilation/aot_emit_aot_file_test.cc new file mode 100644 index 0000000000..64c5533bb2 --- /dev/null +++ b/tests/unit/compilation/aot_emit_aot_file_test.cc @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "wasm_export.h" +#include "aot_export.h" +#include "bh_read_file.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +extern "C" { +uint8 * +aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data, + uint32 *p_aot_file_size); +} + +class aot_emit_aot_file_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_aot_file_test_suite, aot_emit_aot_file) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + aot_comp_data_t comp_data = nullptr; + aot_comp_context_t comp_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "test.aot"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = false; + option.enable_aux_stack_check = false; + option.enable_bulk_memory = false; + option.enable_ref_types = false; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data(wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + EXPECT_EQ(false, aot_emit_aot_file(comp_ctx, comp_data, nullptr)); +} diff --git a/tests/unit/compilation/aot_emit_compare_test.cc b/tests/unit/compilation/aot_emit_compare_test.cc new file mode 100644 index 0000000000..dfd125f9ab --- /dev/null +++ b/tests/unit/compilation/aot_emit_compare_test.cc @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "aot_emit_compare.h" + +class compilation_aot_emit_compare_test : public testing::Test +{ + protected: + virtual void SetUp() {} + virtual void TearDown() {} + + public: +}; + +TEST_F(compilation_aot_emit_compare_test, aot_compile_op_i32_compare) +{ + AOTCompContext comp_ctx = { 0 }; + AOTFuncContext func_ctx = { 0 }; + IntCond cond = INT_EQZ; + IntCond cond1 = INT_EQZ; + + /* false cond = 0 */ + EXPECT_FALSE(aot_compile_op_i32_compare(&comp_ctx, &func_ctx, cond)); + + /* false cond = -1 */ + EXPECT_FALSE( + aot_compile_op_i32_compare(&comp_ctx, &func_ctx, (IntCond)(-1))); + + /* false cond = [1:10] || [11:100] */ + for (int i = 0; i < 0xFFFF; i++) { + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + cond = (IntCond)(1 + (rand() % (INT_GE_U - 1 + 1))); + cond1 = (IntCond)((INT_GE_U + 1) + (rand() % (100 - 1 + 1))); + EXPECT_FALSE(aot_compile_op_i32_compare(&comp_ctx, &func_ctx, cond)); + EXPECT_FALSE(aot_compile_op_i32_compare(&comp_ctx, &func_ctx, cond1)); + } +} + +TEST_F(compilation_aot_emit_compare_test, aot_compile_op_i64_compare) +{ + AOTCompContext comp_ctx = { 0 }; + AOTFuncContext func_ctx = { 0 }; + IntCond cond = INT_EQZ; + IntCond cond1 = INT_EQZ; + + /* false cond = 0 */ + // EXPECT_FALSE(aot_compile_op_i64_compare(&comp_ctx, &func_ctx, cond)); + + /* false cond = -1 */ + EXPECT_FALSE( + aot_compile_op_i64_compare(&comp_ctx, &func_ctx, (IntCond)(-1))); + + /* false cond = [1:10] || [11:100] */ + for (int i = 0; i < 0xFFFF; i++) { + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + cond = (IntCond)(1 + (rand() % (INT_GE_U - 1 + 1))); + cond1 = (IntCond)((INT_GE_U + 1) + (rand() % (100 - 1 + 1))); + EXPECT_FALSE(aot_compile_op_i64_compare(&comp_ctx, &func_ctx, cond)); + EXPECT_FALSE(aot_compile_op_i64_compare(&comp_ctx, &func_ctx, cond1)); + } +} + +TEST_F(compilation_aot_emit_compare_test, aot_compile_op_f32_compare) +{ + AOTCompContext comp_ctx = { 0 }; + AOTFuncContext func_ctx = { 0 }; + FloatCond cond = FLOAT_EQ; + FloatCond cond1 = FLOAT_EQ; + + /* false cond = 0 */ + EXPECT_FALSE(aot_compile_op_f32_compare(&comp_ctx, &func_ctx, cond)); + + /* false cond = -1 */ + EXPECT_FALSE( + aot_compile_op_f32_compare(&comp_ctx, &func_ctx, (FloatCond)(-1))); + + /* false cond = [1:10] || [7:100] */ + for (int i = 0; i < 0xFFFF; i++) { + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + cond = (FloatCond)(1 + (rand() % (FLOAT_UNO - 1 + 1))); + cond1 = (FloatCond)((FLOAT_UNO + 1) + (rand() % (100 - 1 + 1))); + EXPECT_FALSE(aot_compile_op_f32_compare(&comp_ctx, &func_ctx, cond)); + EXPECT_FALSE(aot_compile_op_f32_compare(&comp_ctx, &func_ctx, cond1)); + } +} + +TEST_F(compilation_aot_emit_compare_test, aot_compile_op_f64_compare) +{ + AOTCompContext comp_ctx = { 0 }; + AOTFuncContext func_ctx = { 0 }; + FloatCond cond = FLOAT_EQ; + FloatCond cond1 = FLOAT_EQ; + + /* false cond = 0 */ + EXPECT_FALSE(aot_compile_op_f64_compare(&comp_ctx, &func_ctx, cond)); + + /* false cond = -1 */ + EXPECT_FALSE( + aot_compile_op_f64_compare(&comp_ctx, &func_ctx, (FloatCond)(-1))); + + /* false cond = [1:10] || [7:100] */ + for (int i = 0; i < 0xFFFF; i++) { + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + cond = (FloatCond)(1 + (rand() % (FLOAT_UNO - 1 + 1))); + cond1 = (FloatCond)((FLOAT_UNO + 1) + (rand() % (100 - 1 + 1))); + EXPECT_FALSE(aot_compile_op_f64_compare(&comp_ctx, &func_ctx, cond)); + EXPECT_FALSE(aot_compile_op_f64_compare(&comp_ctx, &func_ctx, cond1)); + } +} diff --git a/tests/unit/compilation/aot_emit_control_test.cc b/tests/unit/compilation/aot_emit_control_test.cc new file mode 100644 index 0000000000..a269f51ebc --- /dev/null +++ b/tests/unit/compilation/aot_emit_control_test.cc @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot.h" +#include "aot_llvm.h" +#include "aot_emit_control.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_emit_control_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_control_test_suite, check_suspend_flags) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "out_file_name_test"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + func_ctx = comp_ctx->func_ctxes[1]; + EXPECT_EQ(true, check_suspend_flags(comp_ctx, func_ctx, false)); +} + +TEST_F(aot_emit_control_test_suite, aot_compile_op_block) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "out_file_name_test"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + func_ctx = comp_ctx->func_ctxes[1]; + func_ctx->block_stack.block_list_end = nullptr; + EXPECT_EQ(false, aot_compile_op_block(comp_ctx, func_ctx, nullptr, nullptr, + 0, 0, nullptr, 0, nullptr)); +} + +TEST_F(aot_emit_control_test_suite, aot_compile_op_else) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "out_file_name_test"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + func_ctx = comp_ctx->func_ctxes[1]; + func_ctx->block_stack.block_list_end = nullptr; + EXPECT_EQ(false, aot_compile_op_else(comp_ctx, func_ctx, nullptr)); + + AOTBlock block_list_end_test; + block_list_end_test.label_type = LABEL_TYPE_FUNCTION; + func_ctx->block_stack.block_list_end = &block_list_end_test; + EXPECT_EQ(false, aot_compile_op_else(comp_ctx, func_ctx, nullptr)); + + block_list_end_test.label_type = LABEL_TYPE_IF; + block_list_end_test.llvm_else_block = nullptr; + EXPECT_EQ(false, aot_compile_op_else(comp_ctx, func_ctx, nullptr)); +} diff --git a/tests/unit/compilation/aot_emit_function_test.cc b/tests/unit/compilation/aot_emit_function_test.cc new file mode 100644 index 0000000000..8c4c93fcea --- /dev/null +++ b/tests/unit/compilation/aot_emit_function_test.cc @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot_emit_control.h" +#include "aot_emit_function.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_emit_function_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_function_test_suite, aot_compile_op_call) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "out_file_name_test"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + func_ctx = comp_ctx->func_ctxes[1]; + EXPECT_EQ(false, aot_compile_op_call(comp_ctx, func_ctx, 9999, true)); +} diff --git a/tests/unit/compilation/aot_emit_memory_test.cc b/tests/unit/compilation/aot_emit_memory_test.cc new file mode 100644 index 0000000000..26a6a79bac --- /dev/null +++ b/tests/unit/compilation/aot_emit_memory_test.cc @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "bh_platform.h" +#include "bh_read_file.h" +#include "aot_emit_memory.h" +#include "test_helper.h" + +#define DEFAULT_CYCLE_TIMES 0xFFFF +#define DEFAULT_MAX_RAND_NUM 0xFFFFFFFF + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class compilation_aot_emit_memory_test : public testing::Test +{ + protected: + void SetUp() override + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + /* default value, enable or disable depends on the platform */ + option.stack_bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = reinterpret_cast(wasm_runtime_load( + wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf))); + EXPECT_NE(wasm_module, nullptr); + comp_data = aot_create_comp_data(wasm_module, NULL, false); + EXPECT_NE(comp_data, nullptr); + + // properly init compilation and function context, to do that, + // use as a dummy module(instead of compile the function in it, simply + // test the APIs) + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + func_ctx = comp_ctx->func_ctxes[0]; + EXPECT_NE(func_ctx, nullptr); + } + + void TearDown() override + { + aot_destroy_comp_context(comp_ctx); + aot_destroy_comp_data(comp_data); + wasm_runtime_unload(reinterpret_cast(wasm_module)); + } + + public: + WASMModule *wasm_module = nullptr; + AOTCompData *comp_data = nullptr; + AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(compilation_aot_emit_memory_test, aot_check_memory_overflow) +{ + uint32 offset = 64; + uint32 bytes = 4; + + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes, false); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i32_load) +{ + uint32 align = 0; + uint32 offset = 1024; + uint32 bytes = 0; + bool sign = false; + bool atomic = false; + + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + bytes = (1 + (rand() % (4 - 1 + 1))); + printf("---%d", aot_compile_op_i32_load(comp_ctx, func_ctx, align, + offset, bytes, sign, atomic)); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i64_load) +{ + uint32 align = 0; + uint32 offset = 1024; + uint32 bytes = 0; + bool sign = false; + bool atomic = false; + + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + bytes = (1 + (rand() % (4 - 1 + 1))); + sign = !sign; + atomic = !atomic; + aot_compile_op_i64_load(comp_ctx, func_ctx, align, offset, bytes, sign, + atomic); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f32_load) +{ + uint32 align = 10; + uint32 offset = 10; + + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + aot_compile_op_f32_load(comp_ctx, func_ctx, align, offset); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f64_load) +{ + uint32 align = 10; + uint32 offset = 10; + + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + aot_compile_op_f64_load(comp_ctx, func_ctx, align, offset); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i32_store) +{ + uint32 align = 0; + uint32 offset = 0; + uint32 bytes = 0; + bool atomic = false; + + EXPECT_FALSE(aot_compile_op_i32_store(comp_ctx, func_ctx, align, offset, + bytes, atomic)); + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + bytes = (1 + (rand() % (4 - 1 + 1))); + offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + align = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + atomic = !atomic; + + EXPECT_FALSE(aot_compile_op_i32_store(comp_ctx, func_ctx, align, offset, + bytes, atomic)); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i64_store) +{ + uint32 align = 0; + uint32 offset = 0; + uint32 bytes = 0; + bool atomic = false; + + EXPECT_FALSE(aot_compile_op_i64_store(comp_ctx, func_ctx, align, offset, + bytes, atomic)); + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + bytes = (1 + (rand() % (8 - 1 + 1))); + offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + align = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + atomic = !atomic; + + EXPECT_FALSE(aot_compile_op_i64_store(comp_ctx, func_ctx, align, offset, + bytes, atomic)); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f32_store) +{ + uint32 align = 0; + uint32 offset = 0; + + EXPECT_FALSE(aot_compile_op_f32_store(comp_ctx, func_ctx, align, offset)); + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + align = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + + EXPECT_FALSE( + aot_compile_op_f32_store(comp_ctx, func_ctx, align, offset)); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f64_store) +{ + uint32 align = 0; + uint32 offset = 0; + + EXPECT_FALSE(aot_compile_op_f64_store(comp_ctx, func_ctx, align, offset)); + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + align = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + + EXPECT_FALSE( + aot_compile_op_f64_store(comp_ctx, func_ctx, align, offset)); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_size) +{ + aot_compile_op_memory_size(comp_ctx, func_ctx); +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_grow) +{ + aot_compile_op_memory_grow(comp_ctx, func_ctx); +} + +#if WASM_ENABLE_BULK_MEMORY != 0 +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_init) +{ + uint32 seg_index = 0; + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + seg_index = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + aot_compile_op_memory_init(comp_ctx, func_ctx, seg_index); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_data_drop) +{ + uint32 seg_index = 0; + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + seg_index = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + aot_compile_op_data_drop(comp_ctx, func_ctx, seg_index); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_copy) +{ + aot_compile_op_memory_copy(comp_ctx, func_ctx); +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_fill) +{ + aot_compile_op_memory_fill(comp_ctx, func_ctx); +} +#endif + +#if WASM_ENABLE_SHARED_MEMORY != 0 +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_atomic_rmw) +{ + uint8 atomic_op = LLVMAtomicRMWBinOpAdd; + uint8 op_type = VALUE_TYPE_I32; + uint32 align = 4; + uint32 offset = 64; + uint32 bytes = 4; + + aot_compile_op_atomic_rmw(comp_ctx, func_ctx, atomic_op, op_type, align, + offset, bytes); +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_atomic_cmpxchg) +{ + + uint8 op_type = VALUE_TYPE_I32; + uint32 align = 4; + uint32 offset = 64; + uint32 bytes = 4; + + aot_compile_op_atomic_cmpxchg(comp_ctx, func_ctx, op_type, align, offset, + bytes); +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_atomic_wait) +{ + + uint8 op_type = VALUE_TYPE_I32; + uint32 align = 4; + uint32 offset = 64; + uint32 bytes = 4; + + aot_compile_op_atomic_wait(comp_ctx, func_ctx, op_type, align, offset, + bytes); +} + +TEST_F(compilation_aot_emit_memory_test, aot_compiler_op_atomic_notify) +{ + + uint32 align = 4; + uint32 offset = 64; + uint32 bytes = 4; + + aot_compiler_op_atomic_notify(comp_ctx, func_ctx, align, offset, bytes); +} +#endif diff --git a/tests/unit/compilation/aot_emit_numberic_test.cc b/tests/unit/compilation/aot_emit_numberic_test.cc new file mode 100644 index 0000000000..f7e6e8ee78 --- /dev/null +++ b/tests/unit/compilation/aot_emit_numberic_test.cc @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot_llvm.h" +#include "aot_emit_numberic.h" +#include "aot_compiler.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_emit_numberic_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_numberic_test_suite, aot_compile_op_functions) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + + EXPECT_EQ(false, + aot_compile_op_f32_arithmetic(comp_ctx, func_ctx, FLOAT_SUB)); + EXPECT_EQ(false, aot_compile_op_f32_copysign(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_f32_math(comp_ctx, func_ctx, FLOAT_NEG)); + EXPECT_EQ(false, + aot_compile_op_f64_arithmetic(comp_ctx, func_ctx, FLOAT_SUB)); + EXPECT_EQ(false, aot_compile_op_f64_copysign(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_f64_math(comp_ctx, func_ctx, FLOAT_NEG)); + EXPECT_EQ(false, aot_compile_op_i32_clz(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i32_ctz(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i32_popcnt(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i32_shift(comp_ctx, func_ctx, INT_SHR_S)); + EXPECT_EQ(false, aot_compile_op_i64_arithmetic(comp_ctx, func_ctx, INT_SUB, + nullptr)); + EXPECT_EQ(false, aot_compile_op_i64_bitwise(comp_ctx, func_ctx, INT_OR)); + EXPECT_EQ(false, aot_compile_op_i64_clz(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i64_ctz(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i64_popcnt(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i64_shift(comp_ctx, func_ctx, INT_SHR_S)); +} diff --git a/tests/unit/compilation/aot_emit_parametric_test.cc b/tests/unit/compilation/aot_emit_parametric_test.cc new file mode 100644 index 0000000000..f9dabe1c81 --- /dev/null +++ b/tests/unit/compilation/aot_emit_parametric_test.cc @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot_llvm.h" +#include "aot_emit_parametric.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_emit_parametric_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_parametric_test_suite, aot_compile_op_select) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + + EXPECT_FALSE(aot_compile_op_select(comp_ctx, func_ctx, true)); + EXPECT_FALSE(aot_compile_op_select(comp_ctx, func_ctx, false)); +} + +TEST_F(aot_emit_parametric_test_suite, aot_compile_op_drop) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + func_ctx->block_stack.block_list_end = nullptr; + + EXPECT_FALSE(aot_compile_op_drop(comp_ctx, func_ctx, true)); + EXPECT_FALSE(aot_compile_op_drop(comp_ctx, func_ctx, false)); +} diff --git a/tests/unit/compilation/aot_emit_table_test.cc b/tests/unit/compilation/aot_emit_table_test.cc new file mode 100644 index 0000000000..fc4bfe2f1f --- /dev/null +++ b/tests/unit/compilation/aot_emit_table_test.cc @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot_llvm.h" +#include "aot_emit_table.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_emit_table_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_table_test_suite, get_tbl_inst_offset) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + + EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 6)); + EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 1)); + EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 0)); + ((AOTCompData *)comp_ctx->comp_data)->import_table_count = 1; + AOTImportTable import_tables_test; + ((AOTCompData *)comp_ctx->comp_data)->import_tables = &import_tables_test; + EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 6)); +} diff --git a/tests/unit/compilation/aot_emit_variable_test.cc b/tests/unit/compilation/aot_emit_variable_test.cc new file mode 100644 index 0000000000..11cc238f00 --- /dev/null +++ b/tests/unit/compilation/aot_emit_variable_test.cc @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "aot_emit_variable.h" + +#define DEFAULT_CYCLE_TIMES 0xFFFF +#define DEFAULT_MAX_RAND_NUM 0xFFFFFFFF + +class compilation_aot_emit_variable_test : public testing::Test +{ + protected: + virtual void SetUp() {} + virtual void TearDown() {} + + public: + AOTCompContext comp_ctx = { 0 }; + AOTFuncContext func_ctx = { 0 }; +}; + +TEST_F(compilation_aot_emit_variable_test, aot_compile_op_get_local) +{ + AOTCompContext *pcomp_ctx = &comp_ctx; + AOTFuncContext *pfunc_ctx = &func_ctx; + uint32 local_idx = 0; + + // aot_compile_op_get_local(NULL, pfunc_ctx, local_idx); + + // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + // local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + // aot_compile_op_get_local(pcomp_ctx, pfunc_ctx, local_idx); + // } +} + +TEST_F(compilation_aot_emit_variable_test, aot_compile_op_set_local) +{ + + AOTCompContext *pcomp_ctx = &comp_ctx; + AOTFuncContext *pfunc_ctx = &func_ctx; + uint32 local_idx = 0; + + // aot_compile_op_set_local(pcomp_ctx, pfunc_ctx, local_idx); + + // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + // local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + // aot_compile_op_set_local(pcomp_ctx, pfunc_ctx, local_idx); + // } +} + +TEST_F(compilation_aot_emit_variable_test, aot_compile_op_tee_local) +{ + + AOTCompContext *pcomp_ctx = &comp_ctx; + AOTFuncContext *pfunc_ctx = &func_ctx; + uint32 local_idx = 0; + + // aot_compile_op_tee_local(pcomp_ctx, pfunc_ctx, local_idx); + + // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + // local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + // aot_compile_op_tee_local(pcomp_ctx, pfunc_ctx, local_idx); + // } +} + +TEST_F(compilation_aot_emit_variable_test, aot_compile_op_get_global) +{ + AOTCompContext *pcomp_ctx = &comp_ctx; + AOTFuncContext *pfunc_ctx = &func_ctx; + uint32 global_idx = 0; + + // aot_compile_op_get_global(pcomp_ctx, pfunc_ctx, global_idx); + + // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + // local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + // aot_compile_op_get_global(pcomp_ctx, pfunc_ctx, global_idx); + // } +} + +TEST_F(compilation_aot_emit_variable_test, aot_compile_op_set_global) +{ + AOTCompContext *pcomp_ctx = &comp_ctx; + AOTFuncContext *pfunc_ctx = &func_ctx; + uint32 global_idx = 0; + bool is_aux_stack = false; + + // aot_compile_op_set_global(pcomp_ctx, pfunc_ctx, global_idx, + // is_aux_stack); + + // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + // is_aux_stack = is_aux_stack ? false : ture; + // local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + // aot_compile_op_set_global(pcomp_ctx, pfunc_ctx, + // global_idx,is_aux_stack); + // } +} \ No newline at end of file diff --git a/tests/unit/compilation/aot_llvm_test.cc b/tests/unit/compilation/aot_llvm_test.cc new file mode 100644 index 0000000000..dcebe04b47 --- /dev/null +++ b/tests/unit/compilation/aot_llvm_test.cc @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot_llvm.h" +#include "aot_compiler.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_llvm_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_llvm_test_suite, aot_functions) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTCompOption option = { 0 }; + AOTFuncContext *func_ctx = nullptr; + WASMValue wasm_value; + LLVMTypeRef param_types[1]; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + + param_types[0] = F64_TYPE; + EXPECT_TRUE(aot_call_llvm_intrinsic(comp_ctx, func_ctx, "f32_demote_f64", + F32_TYPE, param_types, 0)); + + /* Test function aot_get_native_symbol_index. */ + AOTNativeSymbol elem_insert_1; + elem_insert_1.index = -1; + bh_list_insert(&comp_ctx->native_symbols, &elem_insert_1); + + AOTNativeSymbol elem_insert_2; + strcpy(elem_insert_2.symbol, "f64#_test"); + elem_insert_2.index = -1; + bh_list_insert(&comp_ctx->native_symbols, &elem_insert_2); + comp_ctx->pointer_size = sizeof(uint32); + strcpy(comp_ctx->target_arch, "i386"); + EXPECT_NE(-1, aot_get_native_symbol_index(comp_ctx, "f64#_test")); +} + +TEST_F(aot_llvm_test_suite, wasm_type_to_llvm_type) {} + +TEST_F(aot_llvm_test_suite, aot_build_zero_function_ret) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTCompOption option = { 0 }; + AOTFuncContext *func_ctx = nullptr; + AOTFuncType func_type; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = false; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + + func_type.result_count = 1; + func_type.param_count = 0; + func_type.types[func_type.param_count] = VALUE_TYPE_I32; + EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type)); + func_type.types[func_type.param_count] = VALUE_TYPE_I64; + EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type)); + func_type.types[func_type.param_count] = VALUE_TYPE_F32; + EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type)); + func_type.types[func_type.param_count] = VALUE_TYPE_F64; + EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type)); + func_type.types[func_type.param_count] = VALUE_TYPE_V128; + EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type)); + /* THe current optimization, if not actually use ref_types in wasm module, + * it will set to false, so test false condition */ + func_type.types[func_type.param_count] = VALUE_TYPE_FUNCREF; + EXPECT_DEATH(aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type), + ".*"); + func_type.types[func_type.param_count] = VALUE_TYPE_EXTERNREF; + EXPECT_DEATH(aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type), + ".*"); + func_type.types[func_type.param_count] = 0xFF; + EXPECT_DEATH(aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type), + ".*"); +} + +TEST_F(aot_llvm_test_suite, aot_destroy_comp_context) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTCompOption option = { 0 }; + AOTFuncContext *func_ctx = nullptr; + AOTFuncType func_type; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + AOTNativeSymbol elem_insert_1; + elem_insert_1.index = -1; + bh_list_insert(&comp_ctx->native_symbols, &elem_insert_1); + aot_destroy_comp_context(comp_ctx); + + aot_destroy_comp_context(nullptr); +} + +TEST_F(aot_llvm_test_suite, aot_create_comp_context) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + + option.enable_thread_mgr = true; + option.enable_tail_call = true; + option.is_indirect_mode = true; + option.disable_llvm_intrinsics = true; + option.disable_llvm_lto = true; + option.is_jit_mode = true; + + option.target_arch = (char *)"arm"; + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + option.output_format = 100; + comp_ctx = aot_create_comp_context(comp_data, &option); + + // Test every target_arch. + option.is_jit_mode = false; + option.target_arch = (char *)"arm"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"armeb"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"thumb"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"thumbeb"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"aarch64"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"aarch64_be"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"help"; + comp_ctx = aot_create_comp_context(comp_data, &option); + + // Test every target_abi. + option.target_arch = (char *)"arm"; + option.target_abi = (char *)"test"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_abi = (char *)"help"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_abi = (char *)"msvc"; + option.target_arch = (char *)"i386"; + comp_ctx = aot_create_comp_context(comp_data, &option); + + option.cpu_features = (char *)"test"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.is_sgx_platform = true; + comp_ctx = aot_create_comp_context(comp_data, &option); + comp_data->func_count = 0; + comp_ctx = aot_create_comp_context(comp_data, &option); +} diff --git a/tests/unit/compilation/wasm-apps/main.wasm b/tests/unit/compilation/wasm-apps/main.wasm new file mode 100644 index 0000000000..28af80e405 Binary files /dev/null and b/tests/unit/compilation/wasm-apps/main.wasm differ diff --git a/tests/unit/custom-section/CMakeLists.txt b/tests/unit/custom-section/CMakeLists.txt new file mode 100644 index 0000000000..1529d0ea6b --- /dev/null +++ b/tests/unit/custom-section/CMakeLists.txt @@ -0,0 +1,65 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-custom-section) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_LIBC_BUILTIN 0) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LAZY_JIT 0) +set (WAMR_BUILD_AOT 1) + +add_definitions(-DWASM_ENABLE_WAMR_COMPILER=1) +add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1) +add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1) + +# Feature to test +set (WAMR_BUILD_LOAD_CUSTOM_SECTION 1) + +include (../unit_common.cmake) + +set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") +if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif () +set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include (${IWASM_DIR}/compilation/iwasm_compl.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} + ) + +# Automatically build wasm-apps for this test +add_subdirectory(wasm-apps) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable (custom_section_test ${unit_test_sources}) + +target_link_libraries (custom_section_test ${LLVM_AVAILABLE_LIBS} gtest_main ) + +gtest_discover_tests(custom_section_test) diff --git a/tests/unit/custom-section/custom_section_test.cc b/tests/unit/custom-section/custom_section_test.cc new file mode 100644 index 0000000000..9bf04664ab --- /dev/null +++ b/tests/unit/custom-section/custom_section_test.cc @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "bh_platform.h" +#include +#include "test_helper.h" +#include "aot_export.h" + +class CustomSectionTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<1 * 1024 * 1024> runtime; +}; + +TEST_F(CustomSectionTest, get_custom_section_from_wasm_module_t) +{ + uint32_t length, len_from_aot; + const uint8_t *content, *content_from_aot; + std::ifstream wasm_file("wasm-apps/app.wasm", std::ios::binary); + std::vector buffer(std::istreambuf_iterator(wasm_file), + {}); + { + WAMRModule module(buffer.data(), buffer.size()); + aot_comp_data_t comp_data = NULL; + aot_comp_context_t comp_ctx = NULL; + std::vector sections_to_emit{ + "name", + ".debug_info", + ".debug_abbrev", + /* skip ".debug_line" section in AoT module */ + ".debug_str", + "producers", + }; + + AOTCompOption option = { 0 }; + option.custom_sections = (char **)sections_to_emit.data(); + option.custom_sections_count = 5; + + { + /* Compile an AoT module */ + comp_data = aot_create_comp_data(module.get(), NULL, false); + EXPECT_NE(comp_data, nullptr); + + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + EXPECT_TRUE(aot_emit_aot_file(comp_ctx, comp_data, "temp.aot")); + } + + std::ifstream aot_file("temp.aot", std::ios::binary); + std::vector aot_buffer( + std::istreambuf_iterator(aot_file), {}); + WAMRModule aot_module(aot_buffer.data(), aot_buffer.size()); + + /* name */ + content = + wasm_runtime_get_custom_section(module.get(), "name", &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + /* TODO: aot_emit_name_section don't + EMIT_U32(AOT_CUSTOM_SECTION_RAW);* + EMIT_STR("name"); + but instead + EMIT_U32(AOT_CUSTOM_SECTION_NAME); + can't use get_custom_section to get it + */ + // content_from_aot = wasm_runtime_get_custom_section( + // aot_module.get(), "name", &len_from_aot); + // EXPECT_NE(content_from_aot, nullptr); + // EXPECT_EQ(len_from_aot, length); + // EXPECT_EQ(memcmp(content_from_aot, content, length), 0); + + /* .debug_info */ + content = wasm_runtime_get_custom_section(module.get(), ".debug_info", + &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), ".debug_info", &len_from_aot); + EXPECT_NE(content_from_aot, nullptr); + EXPECT_EQ(len_from_aot, length); + EXPECT_EQ(memcmp(content_from_aot, content, length), 0); + + /* .debug_abbrev */ + content = wasm_runtime_get_custom_section(module.get(), ".debug_abbrev", + &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), ".debug_abbrev", &len_from_aot); + EXPECT_NE(content_from_aot, nullptr); + EXPECT_EQ(len_from_aot, length); + EXPECT_EQ(memcmp(content_from_aot, content, length), 0); + + /* .debug_line */ + content = wasm_runtime_get_custom_section(module.get(), ".debug_line", + &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), ".debug_line", &len_from_aot); + EXPECT_EQ(content_from_aot, nullptr); + + /* .debug_str */ + content = wasm_runtime_get_custom_section(module.get(), ".debug_str", + &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), ".debug_str", &len_from_aot); + EXPECT_NE(content_from_aot, nullptr); + EXPECT_EQ(len_from_aot, length); + EXPECT_EQ(memcmp(content_from_aot, content, length), 0); + + /* producers */ + content = + wasm_runtime_get_custom_section(module.get(), "producers", &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), "producers", &len_from_aot); + EXPECT_NE(content_from_aot, nullptr); + EXPECT_EQ(len_from_aot, length); + EXPECT_EQ(memcmp(content_from_aot, content, length), 0); + + /* Not exist */ + content = wasm_runtime_get_custom_section(module.get(), "producers1", + &length); + EXPECT_EQ(content, nullptr); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), "producers1", &len_from_aot); + EXPECT_EQ(content_from_aot, nullptr); + } +} diff --git a/tests/unit/custom-section/wasm-apps/CMakeLists.txt b/tests/unit/custom-section/wasm-apps/CMakeLists.txt new file mode 100644 index 0000000000..a539dd2361 --- /dev/null +++ b/tests/unit/custom-section/wasm-apps/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project(wasm-apps-custom-section) + +# Add -g option so there will be debugger related custom sections +add_custom_target(app.wasm ALL + COMMAND /opt/wasi-sdk/bin/clang -g -nostdlib + -Wl,--no-entry,--export-all + -o ${CMAKE_CURRENT_BINARY_DIR}/app.wasm + ${CMAKE_CURRENT_LIST_DIR}/app.c +) diff --git a/tests/unit/custom-section/wasm-apps/app.c b/tests/unit/custom-section/wasm-apps/app.c new file mode 100644 index 0000000000..3820e3c7cc --- /dev/null +++ b/tests/unit/custom-section/wasm-apps/app.c @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +int +main(int argc, char const *argv[]) +{ + return 0; +} diff --git a/tests/unit/gc/CMakeLists.txt b/tests/unit/gc/CMakeLists.txt new file mode 100644 index 0000000000..e0f70d1427 --- /dev/null +++ b/tests/unit/gc/CMakeLists.txt @@ -0,0 +1,51 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-wamr-gc) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_GC 1) +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${LIB_HOST_AGENT_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} +) + +add_executable (gc_test ${unit_test_sources}) +target_link_libraries (gc_test gtest_main) + +add_custom_command(TARGET gc_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/*.was* + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copy wasm files to directory ${CMAKE_CURRENT_BINARY_DIR}" +) + +#gtest_discover_tests(gc_test) \ No newline at end of file diff --git a/tests/unit/gc/gc_test.cc b/tests/unit/gc/gc_test.cc new file mode 100644 index 0000000000..196ddba65a --- /dev/null +++ b/tests/unit/gc/gc_test.cc @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "bh_platform.h" +#include "bh_read_file.h" +#include "wasm_export.h" + +class WasmGCTest : public testing::Test +{ + private: + std::string get_binary_path() + { + char cwd[1024] = { 0 }; + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + return NULL; + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); + } + + protected: + void SetUp() + { + CWD = get_binary_path(); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + + cleanup = true; + } + + void TearDown() + { + if (cleanup) { + wasm_runtime_destroy(); + } + } + + public: + bool load_wasm_file(const char *wasm_file) + { + const char *file; + unsigned char *wasm_file_buf; + uint32 wasm_file_size; + + file = strdup((CWD + "/" + wasm_file).c_str()); + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size); + if (!wasm_file_buf) + return false; + + module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + if (!module) + return false; + + return true; + } + + public: + std::string CWD; + RuntimeInitArgs init_args; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_function_inst_t func_inst = NULL; + wasm_exec_env_t exec_env = NULL; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + bool cleanup = true; +}; + +TEST_F(WasmGCTest, Test_app1) +{ + ASSERT_TRUE(load_wasm_file("test1.wasm")); + ASSERT_TRUE(load_wasm_file("test2.wasm")); + ASSERT_TRUE(load_wasm_file("test3.wasm")); + ASSERT_TRUE(load_wasm_file("test4.wasm")); + ASSERT_TRUE(load_wasm_file("test5.wasm")); + ASSERT_TRUE(load_wasm_file("test6.wasm")); + + ASSERT_TRUE(load_wasm_file("struct1.wasm")); + ASSERT_TRUE(load_wasm_file("struct2.wasm")); + ASSERT_TRUE(load_wasm_file("struct3.wasm")); + + ASSERT_TRUE(load_wasm_file("func1.wasm")); + ASSERT_TRUE(load_wasm_file("func2.wasm")); +} diff --git a/tests/unit/gc/wasm-apps/func1.wasm b/tests/unit/gc/wasm-apps/func1.wasm new file mode 100644 index 0000000000..51b316b54e Binary files /dev/null and b/tests/unit/gc/wasm-apps/func1.wasm differ diff --git a/tests/unit/gc/wasm-apps/func1.wast b/tests/unit/gc/wasm-apps/func1.wast new file mode 100644 index 0000000000..1b4941787d --- /dev/null +++ b/tests/unit/gc/wasm-apps/func1.wast @@ -0,0 +1,35 @@ +(module + (type $t (func)) + + (func (export "test") (param structref i31ref) + (local funcref) + (local funcref) + (local funcref) + (local externref) + (local externref) + (local externref) + (local anyref) + (local eqref) + (local structref) + (local arrayref) + (local i31ref) + (local (ref null 0)) + (local (ref null 0)) + (local (ref null 0)) + (local (ref null 1)) + (local (ref null func)) + (local (ref null 0)) + (local (ref null extern)) + (local (ref null any)) + (local (ref null eq)) + (local (ref null i31)) + (local (ref null struct)) + + local.get 0 + ref.test null array + drop + local.get 1 + ref.cast i31 + drop + ) +) diff --git a/tests/unit/gc/wasm-apps/func2.wasm b/tests/unit/gc/wasm-apps/func2.wasm new file mode 100644 index 0000000000..e5d852ce46 Binary files /dev/null and b/tests/unit/gc/wasm-apps/func2.wasm differ diff --git a/tests/unit/gc/wasm-apps/func2.wast b/tests/unit/gc/wasm-apps/func2.wast new file mode 100644 index 0000000000..bfe588dd56 --- /dev/null +++ b/tests/unit/gc/wasm-apps/func2.wast @@ -0,0 +1,78 @@ +(module + (type $t0 (func)) + (type $t1 (func (param (ref null 1)))) + (type $t2 (func (param funcref externref (ref func)(ref extern) + anyref eqref structref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 1) (ref $t0) (ref null func) + (ref null extern) (ref null 2) (ref null $t0)) + (result (ref null func)))) + (type $t3 (func (param i32 i32) (result (ref null 3)))) + + (type $t4 (func)) + (type $t5 (func (param (ref null 3)))) + (type $t6 (func (param funcref externref (ref func)(ref extern) + anyref eqref structref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)) + (result (ref null func)))) + (type $t7 (func (param i32 i32) (result (ref null 4)))) + + (type $t11 (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null struct) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + + (type $t12 (struct)) + (type $t13 (struct (field))) + (type $t14 (struct (field i8))) + (type $t15 (struct (field i8 i8 i8 i8))) + (type $t16 (struct (field $x1 i32) (field $y1 i32))) + (type $t17 (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type $t18 (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type $t19 (struct (field $x2 i32) (field f32 f64) (field $y2 i32))) + + (type $t20 (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func)(ref extern) + anyref eqref structref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + + (type $t21 (struct)) + (type $t22 (struct (field))) + (type $t23 (struct (field i8))) + (type $t24 (struct (field i8 i8 i8 i8))) + (type $t25 (struct (field $x3 i32) (field $y3 i32))) + (type $t26 (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type $t27 (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type $t28 (struct (field $x4 i32) (field f32 f64) (field $y4 i32))) + + (type $t31 (array i8)) + (type $t32 (array i16)) + (type $t33 (array i32)) + (type $t34 (array i64)) + (type $t35 (array f32)) + (type $t36 (array f64)) + (type $t37 (array anyref)) + (type $t38 (array (ref i31))) + (type $t39 (array (ref 0))) + (type $t40 (array (ref null 1))) + (type $t43 (array (mut i8))) + (type $t44 (array (mut i16))) + (type $t45 (array (mut i32))) + (type $t46 (array (mut i64))) + (type $t47 (array (mut i32))) + (type $t48 (array (mut i64))) + (type $t49 (array (mut anyref))) + (type $t50 (array (mut (ref struct)))) + (type $t51 (array (mut (ref 0)))) + (type $t52 (array (mut (ref null i31)))) +) diff --git a/tests/unit/gc/wasm-apps/global1.wasm b/tests/unit/gc/wasm-apps/global1.wasm new file mode 100644 index 0000000000..706cc954c4 Binary files /dev/null and b/tests/unit/gc/wasm-apps/global1.wasm differ diff --git a/tests/unit/gc/wasm-apps/global1.wast b/tests/unit/gc/wasm-apps/global1.wast new file mode 100644 index 0000000000..9842f8d930 --- /dev/null +++ b/tests/unit/gc/wasm-apps/global1.wast @@ -0,0 +1,91 @@ +(module + (type $ftype0 (func (param i32))) + (type $ftype1 (func (param i32 i64) (result i32))) + (type $ftype2 (func (param f32 f64) (result f64))) + (type $t0 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2)))) + (type $t1 (func (param funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 3) (ref null $t0)) + (result (ref null func)))) + (type $t2 (func (param i32 i32) (result (ref null 4)))) + + ;; Duplicated types + (type $t3 (func)) + (type $t4 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2)))) + (type $t5 (func (param funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 3) (ref null $t0)) + (result (ref null func)))) + (type $t6 (func (param i32 i32) (result (ref null 4)))) + + (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + + (type (struct)) + (type (struct (field))) + (type (struct (field i8))) + (type (struct (field i8 i8 i8 i8))) + (type (struct (field $x1 i32) (field $y1 i32))) + (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32))) + + ;; Duplicated types + (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + + (type (struct)) + (type (struct (field))) + (type (struct (field i8))) + (type (struct (field i8 i8 i8 i8))) + (type (struct (field $x3 i32) (field $y3 i32))) + (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type (struct (field $x4 i32) (field f32 f64) (field $y4 i32))) + + (type (array i8)) + (type (array i16)) + (type (array i32)) + (type (array i64)) + (type (array f32)) + (type (array f64)) + (type (array anyref)) + (type (array (ref array))) + (type (array (ref 0))) + (type (array (ref null 1))) + (type (array (mut i8))) + (type (array (mut i16))) + (type (array (mut i32))) + (type (array (mut i64))) + (type (array (mut i32))) + (type (array (mut i64))) + (type (array (mut anyref))) + (type (array (mut (ref array)))) + (type (array (mut (ref 0)))) + (type (array (mut (ref null i31)))) + + (global $g0 funcref (ref.func $f0)) + (global $g1 externref (ref.null extern)) + (global $g2 anyref (ref.null any)) + (global $g3 eqref (ref.null array)) + (global $g4 arrayref (ref.null array)) + (global $g5 i31ref (ref.null i31)) + + (func $f0) +) diff --git a/tests/unit/gc/wasm-apps/struct1.wasm b/tests/unit/gc/wasm-apps/struct1.wasm new file mode 100644 index 0000000000..513442f96f Binary files /dev/null and b/tests/unit/gc/wasm-apps/struct1.wasm differ diff --git a/tests/unit/gc/wasm-apps/struct1.wast b/tests/unit/gc/wasm-apps/struct1.wast new file mode 100644 index 0000000000..3ce6fde6bf --- /dev/null +++ b/tests/unit/gc/wasm-apps/struct1.wast @@ -0,0 +1,10 @@ +(module + (type (struct)) + (type (struct (field))) + (type (struct (field i8))) + (type (struct (field i8 i8 i8 i8))) + (type (struct (field $x1 i32) (field $y1 i32))) + (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32))) +) diff --git a/tests/unit/gc/wasm-apps/struct2.wasm b/tests/unit/gc/wasm-apps/struct2.wasm new file mode 100644 index 0000000000..497a964419 Binary files /dev/null and b/tests/unit/gc/wasm-apps/struct2.wasm differ diff --git a/tests/unit/gc/wasm-apps/struct2.wast b/tests/unit/gc/wasm-apps/struct2.wast new file mode 100644 index 0000000000..266841d62e --- /dev/null +++ b/tests/unit/gc/wasm-apps/struct2.wast @@ -0,0 +1,33 @@ +(module + (type $vec (struct (field f32) (field $y (mut f32)) (field $z f32))) + + ;;(global (ref $vec) (struct.new_canon $vec (f32.const 1) (f32.const 2) (f32.const 3))) + (global (ref $vec) (struct.new_canon_default $vec)) + + (func (export "new") (result anyref) + (struct.new_canon_default $vec) + ) + + (func $get_0 (param $v (ref $vec)) (result f32) + (struct.get $vec 0 (local.get $v)) + ) + (func (export "get_0") (result f32) + (call $get_0 (struct.new_canon_default $vec)) + ) + + (func $set_get_y (param $v (ref $vec)) (param $y f32) (result f32) + (struct.set $vec $y (local.get $v) (local.get $y)) + (struct.get $vec $y (local.get $v)) + ) + (func (export "set_get_y") (param $y f32) (result f32) + (call $set_get_y (struct.new_canon_default $vec) (local.get $y)) + ) + + (func $set_get_1 (param $v (ref $vec)) (param $y f32) (result f32) + (struct.set $vec 1 (local.get $v) (local.get $y)) + (struct.get $vec $y (local.get $v)) + ) + (func (export "set_get_1") (param $y f32) (result f32) + (call $set_get_1 (struct.new_canon_default $vec) (local.get $y)) + ) +) diff --git a/tests/unit/gc/wasm-apps/struct3.wasm b/tests/unit/gc/wasm-apps/struct3.wasm new file mode 100644 index 0000000000..0da32361a7 Binary files /dev/null and b/tests/unit/gc/wasm-apps/struct3.wasm differ diff --git a/tests/unit/gc/wasm-apps/struct3.wast b/tests/unit/gc/wasm-apps/struct3.wast new file mode 100644 index 0000000000..b7678ba78f --- /dev/null +++ b/tests/unit/gc/wasm-apps/struct3.wast @@ -0,0 +1,9 @@ +(module + (type $t (struct (field i32 (mut i32)))) + (func (export "struct.get-null") + (local (ref null $t)) (drop (struct.get $t 1 (local.get 0))) + ) + (func (export "struct.set-null") + (local (ref null $t)) (struct.set $t 1 (local.get 0) (i32.const 0)) + ) +) diff --git a/tests/unit/gc/wasm-apps/table1.wasm b/tests/unit/gc/wasm-apps/table1.wasm new file mode 100644 index 0000000000..f43b425398 Binary files /dev/null and b/tests/unit/gc/wasm-apps/table1.wasm differ diff --git a/tests/unit/gc/wasm-apps/table1.wast b/tests/unit/gc/wasm-apps/table1.wast new file mode 100644 index 0000000000..8e00618357 --- /dev/null +++ b/tests/unit/gc/wasm-apps/table1.wast @@ -0,0 +1,108 @@ +(module + (type $ftype0 (func (param i32))) + (type $ftype1 (func (param i32 i64) (result i32))) + (type $ftype2 (func (param f32 f64) (result f64))) + (type $t0 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2)))) + (type $t1 (func (param funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 3) (ref null $t0)) + (result (ref null func)))) + (type $t2 (func (param i32 i32) (result (ref null 4)))) + + ;; Duplicated types + (type $t3 (func)) + (type $t4 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2)))) + (type $t5 (func (param funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 3) (ref null $t0)) + (result (ref null func)))) + (type $t6 (func (param i32 i32) (result (ref null 4)))) + + (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + (type (struct)) + (type (struct (field))) + (type (struct (field i8))) + (type (struct (field i8 i8 i8 i8))) + (type (struct (field $x1 i32) (field $y1 i32))) + (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32))) + + ;; Duplicated types + (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + + (type (struct)) + (type (struct (field))) + (type (struct (field i8))) + (type (struct (field i8 i8 i8 i8))) + (type (struct (field $x3 i32) (field $y3 i32))) + (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type (struct (field $x4 i32) (field f32 f64) (field $y4 i32))) + + (type (array i8)) + (type (array i16)) + (type (array i32)) + (type (array i64)) + (type (array f32)) + (type (array f64)) + (type (array anyref)) + (type (array (ref array))) + (type (array (ref 0))) + (type (array (ref null 1))) + (type (array (mut i8))) + (type (array (mut i16))) + (type (array (mut i32))) + (type (array (mut i64))) + (type (array (mut i32))) + (type (array (mut i64))) + (type (array (mut anyref))) + (type (array (mut (ref array)))) + (type (array (mut (ref 0)))) + (type (array (mut (ref null i31)))) + + (table 10 funcref) + (table 20 externref) + ;; non-defaultable element type + ;; (table 30 (ref func)) + ;; (table 40 (ref extern)) + (table 50 anyref) + (table 60 eqref) + (table 100 arrayref) + (table 100 i31ref) + (table 100 (ref null 0)) + (table 100 (ref null 2)) + (table 100 (ref null func)) + (table 100 (ref null extern)) + (table 100 (ref null any)) + (table 100 (ref null eq)) + (table 100 (ref null i31)) + (table 100 (ref null array)) + ;; non-defaultable element type + ;; (table 100 (ref 0)) + ;; (table 100 (ref $t0)) + ;; (table 100 (ref 3)) + ;; (table 100 (ref $t0)) + (table 100 (ref null func)) + (table 100 (ref null extern)) + (table 100 (ref null 5)) + (table 100 (ref null $t0)) +) diff --git a/tests/unit/gc/wasm-apps/test1.wasm b/tests/unit/gc/wasm-apps/test1.wasm new file mode 100644 index 0000000000..d907e457f5 Binary files /dev/null and b/tests/unit/gc/wasm-apps/test1.wasm differ diff --git a/tests/unit/gc/wasm-apps/test1.wast b/tests/unit/gc/wasm-apps/test1.wast new file mode 100644 index 0000000000..0f282895c0 --- /dev/null +++ b/tests/unit/gc/wasm-apps/test1.wast @@ -0,0 +1,117 @@ +(module + (type $t (func)) + (type $t0 (func (param (ref null $t) (ref $t) (ref null 0) (ref 0) (ref null 1) (ref 1)))) + (type $t1 (func (param funcref externref anyref eqref + i31ref structref arrayref + nullref nullfuncref nullexternref + (ref null func) (ref null extern) (ref null any) (ref null eq) + (ref null i31) (ref null struct) (ref null array) + (ref null none) (ref null nofunc) (ref null noextern) + (ref func) (ref extern) (ref any) (ref eq) + (ref i31) (ref struct) (ref array) + (ref none) (ref nofunc) (ref noextern) + + (ref null 0) (ref null $t0) (ref null $t1) + (ref null func) (ref null extern) (ref null any) (ref null eq) + (ref null i31) (ref null struct) (ref null array) + (ref $t) (ref $t0) (ref $t1) + (ref func) (ref extern) (ref any) (ref eq) + (ref i31) (ref struct) (ref array)) + (result (ref null func) (ref null extern) (ref $t0)))) + (type $t2 (func (param i32 i32) (result (ref null $t1)))) + + ;; Duplicated types + (type $t3 (func)) + (type $t4 (func (param (ref null $t) (ref $t) (ref null 0) (ref 0) (ref null 1) (ref 1)))) + (type $t5 (func (param funcref externref anyref eqref + i31ref structref arrayref + nullref nullfuncref nullexternref + (ref null func) (ref null extern) (ref null any) (ref null eq) + (ref null i31) (ref null struct) (ref null array) + (ref null none) (ref null nofunc) (ref null noextern) + (ref func) (ref extern) (ref any) (ref eq) + (ref i31) (ref struct) (ref array) + (ref none) (ref nofunc) (ref noextern) + + (ref null 0) (ref null $t0) (ref null $t1) + (ref null func) (ref null extern) (ref null any) (ref null eq) + (ref null i31) (ref null struct) (ref null array) + (ref $t) (ref $t0) (ref $t1) + (ref func) (ref extern) (ref any) (ref eq) + (ref i31) (ref struct) (ref array)) + (result (ref null func) (ref null extern) (ref $t0)))) + (type $t6 (func (param i32 i32) (result (ref null $t1)))) + + (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func) (ref extern) + anyref eqref structref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null struct) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + + (type (struct)) + (type (struct (field))) + (type (struct (field i8))) + (type (struct (field i8 i8 i8 i8))) + (type (struct (field $x1 i32) (field $y1 i32))) + (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32))) + + ;; Duplicated types + (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func) (ref extern) + anyref eqref structref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null struct) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + (type (struct)) + (type (struct (field))) + (type (struct (field i8))) + (type (struct (field i8 i8 i8 i8))) + (type (struct (field $x3 i32) (field $y3 i32))) + (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type (struct (field $x4 i32) (field f32 f64) (field $y4 i32))) + + (type (array i8)) + (type (array i16)) + (type (array i32)) + (type (array i64)) + (type (array f32)) + (type (array f64)) + (type (array anyref)) + (type (array (ref struct))) + (type (array (ref array))) + (type (array (ref null struct))) + (type (array (ref null array))) + (type (array (ref 0))) + (type (array (ref null 1))) + (type (array (mut i8))) + (type (array (mut i16))) + (type (array (mut i32))) + (type (array (mut i64))) + (type (array (mut i32))) + (type (array (mut i64))) + (type (array (mut anyref))) + (type (array (mut (ref struct)))) + (type (array (mut (ref array)))) + (type (array (mut (ref null struct)))) + (type (array (mut (ref null array)))) + (type (array (mut (ref 0)))) + (type (array (mut (ref null i31)))) + + ;; sub types + (type $e0 (sub (array i32))) + (type $e1 (sub $e0 (array i32))) + + (type $e2 (sub (array anyref))) + (type $e3 (sub (array (ref null $e0)))) + (type $e4 (sub (array (ref $e1)))) + (type $e5 (sub $e1 (array i32))) + + (type $m1 (sub (array (mut i32)))) + (type $m2 (sub $m1 (array (mut i32)))) +) diff --git a/tests/unit/gc/wasm-apps/test2.wasm b/tests/unit/gc/wasm-apps/test2.wasm new file mode 100644 index 0000000000..04507f1748 Binary files /dev/null and b/tests/unit/gc/wasm-apps/test2.wasm differ diff --git a/tests/unit/gc/wasm-apps/test2.wast b/tests/unit/gc/wasm-apps/test2.wast new file mode 100644 index 0000000000..c2f7f36365 --- /dev/null +++ b/tests/unit/gc/wasm-apps/test2.wast @@ -0,0 +1,104 @@ +(module + (type $ft (func)) + (type $st (struct)) + (type $at (array i8)) + + (table $ta 10 anyref) + (table $tf 10 funcref) + (table $te 10 externref) + + (elem declare func $f) + (func $f) + + (func (export "init") (param $x externref) + (table.set $ta (i32.const 0) (ref.null any)) + (table.set $ta (i32.const 1) (ref.null struct)) + (table.set $ta (i32.const 2) (ref.null none)) + (table.set $ta (i32.const 3) (i31.new (i32.const 7))) + (table.set $ta (i32.const 4) (struct.new_canon_default $st)) + (table.set $ta (i32.const 5) (array.new_canon_default $at (i32.const 0))) + (table.set $ta (i32.const 6) (extern.internalize (local.get $x))) + (table.set $ta (i32.const 7) (extern.internalize (ref.null extern))) + + (table.set $tf (i32.const 0) (ref.null nofunc)) + (table.set $tf (i32.const 1) (ref.null func)) + (table.set $tf (i32.const 2) (ref.func $f)) + + (table.set $te (i32.const 0) (ref.null noextern)) + (table.set $te (i32.const 1) (ref.null extern)) + (table.set $te (i32.const 2) (local.get $x)) + (table.set $te (i32.const 3) (extern.externalize (i31.new (i32.const 8)))) + (table.set $te (i32.const 4) (extern.externalize (struct.new_canon_default $st))) + (table.set $te (i32.const 5) (extern.externalize (ref.null any))) + ) + + (func (export "ref_test_null_data") (param $i i32) (result i32) + (i32.add + (ref.is_null (table.get $ta (local.get $i))) + (ref.test null none (table.get $ta (local.get $i))) + ) + ) + + (func (export "ref_test_any") (param $i i32) (result i32) + (i32.add + (ref.test any (table.get $ta (local.get $i))) + (ref.test null any (table.get $ta (local.get $i))) + ) + ) + + (func (export "ref_test_eq") (param $i i32) (result i32) + (i32.add + (ref.test eq (table.get $ta (local.get $i))) + (ref.test null eq (table.get $ta (local.get $i))) + ) + ) + + (func (export "ref_test_i31") (param $i i32) (result i32) + (i32.add + (ref.test i31 (table.get $ta (local.get $i))) + (ref.test null i31 (table.get $ta (local.get $i))) + ) + ) + + (func (export "ref_test_struct") (param $i i32) (result i32) + (i32.add + (ref.test struct (table.get $ta (local.get $i))) + (ref.test null struct (table.get $ta (local.get $i))) + ) + ) + + (func (export "ref_test_array") (param $i i32) (result i32) + (i32.add + (ref.test array (table.get $ta (local.get $i))) + (ref.test null array (table.get $ta (local.get $i))) + ) + ) + + (func (export "ref_test_null_func") (param $i i32) (result i32) + (i32.add + (ref.is_null (table.get $tf (local.get $i))) + (ref.test null nofunc (table.get $tf (local.get $i))) + ) + ) + + (func (export "ref_test_func") (param $i i32) (result i32) + (i32.add + (ref.test func (table.get $tf (local.get $i))) + (ref.test null func (table.get $tf (local.get $i))) + ) + ) + + (func (export "ref_test_null_extern") (param $i i32) (result i32) + (i32.add + (ref.is_null (table.get $te (local.get $i))) + (ref.test null noextern (table.get $te (local.get $i))) + ) + ) + + (func (export "ref_test_extern") (param $i i32) (result i32) + (i32.add + (ref.test extern (table.get $te (local.get $i))) + (ref.test null extern (table.get $te (local.get $i))) + ) + ) +) diff --git a/tests/unit/gc/wasm-apps/test3.wasm b/tests/unit/gc/wasm-apps/test3.wasm new file mode 100644 index 0000000000..8ee87dc812 Binary files /dev/null and b/tests/unit/gc/wasm-apps/test3.wasm differ diff --git a/tests/unit/gc/wasm-apps/test3.wast b/tests/unit/gc/wasm-apps/test3.wast new file mode 100644 index 0000000000..4df02ce8fc --- /dev/null +++ b/tests/unit/gc/wasm-apps/test3.wast @@ -0,0 +1,146 @@ +(module + (type $t0 (sub (struct))) + (type $t1 (sub $t0 (struct (field i32)))) + (type $t1' (sub $t0 (struct (field i32)))) + (type $t2 (sub $t1 (struct (field i32 i32)))) + (type $t2' (sub $t1' (struct (field i32 i32)))) + (type $t3 (sub $t0 (struct (field i32 i32)))) + (type $t0' (sub $t0 (struct))) + (type $t4 (sub $t0' (struct (field i32 i32)))) + + (table 20 (ref null struct)) + + (func $init + (table.set (i32.const 0) (struct.new_canon_default $t0)) + (table.set (i32.const 10) (struct.new_canon_default $t0)) + (table.set (i32.const 1) (struct.new_canon_default $t1)) + (table.set (i32.const 11) (struct.new_canon_default $t1')) + (table.set (i32.const 2) (struct.new_canon_default $t2)) + (table.set (i32.const 12) (struct.new_canon_default $t2')) + (table.set (i32.const 3) (struct.new_canon_default $t3)) + (table.set (i32.const 4) (struct.new_canon_default $t4)) + ) + + (func (export "test-sub") + (call $init) + (block $l + ;; must hold + (br_if $l (i32.eqz (ref.test null $t0 (ref.null struct)))) + (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 0))))) + (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 2))))) + (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 3))))) + (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 4))))) + + (br_if $l (i32.eqz (ref.test null $t1 (ref.null struct)))) + (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test null $t1 (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test null $t1 (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test null $t2 (ref.null struct)))) + (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test null $t2 (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test null $t3 (ref.null struct)))) + (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test null $t3 (table.get (i32.const 3))))) + + (br_if $l (i32.eqz (ref.test null $t4 (ref.null struct)))) + (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test null $t4 (table.get (i32.const 4))))) + + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 0))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 2))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 3))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 4))))) + + (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test $t2 (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test $t3 (table.get (i32.const 3))))) + + (br_if $l (i32.eqz (ref.test $t4 (table.get (i32.const 4))))) + + ;; must not hold + (br_if $l (ref.test $t0 (ref.null struct))) + (br_if $l (ref.test $t1 (ref.null struct))) + (br_if $l (ref.test $t2 (ref.null struct))) + (br_if $l (ref.test $t3 (ref.null struct))) + (br_if $l (ref.test $t4 (ref.null struct))) + + (br_if $l (ref.test $t1 (table.get (i32.const 0)))) + (br_if $l (ref.test $t1 (table.get (i32.const 3)))) + (br_if $l (ref.test $t1 (table.get (i32.const 4)))) + + (br_if $l (ref.test $t2 (table.get (i32.const 0)))) + (br_if $l (ref.test $t2 (table.get (i32.const 1)))) + (br_if $l (ref.test $t2 (table.get (i32.const 3)))) + (br_if $l (ref.test $t2 (table.get (i32.const 4)))) + + (br_if $l (ref.test $t3 (table.get (i32.const 0)))) + (br_if $l (ref.test $t3 (table.get (i32.const 1)))) + (br_if $l (ref.test $t3 (table.get (i32.const 2)))) + (br_if $l (ref.test $t3 (table.get (i32.const 4)))) + + (br_if $l (ref.test $t4 (table.get (i32.const 0)))) + (br_if $l (ref.test $t4 (table.get (i32.const 1)))) + (br_if $l (ref.test $t4 (table.get (i32.const 2)))) + (br_if $l (ref.test $t4 (table.get (i32.const 3)))) + + (return) + ) + (unreachable) + ) + + (func (export "test-canon") + (call $init) + (block $l + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 0))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 2))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 3))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 4))))) + + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 10))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 11))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 12))))) + + (br_if $l (i32.eqz (ref.test $t1' (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test $t1' (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 11))))) + (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 12))))) + + (br_if $l (i32.eqz (ref.test $t2' (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test $t2 (table.get (i32.const 12))))) + + (return) + ) + (unreachable) + ) +) diff --git a/tests/unit/gc/wasm-apps/test4.wasm b/tests/unit/gc/wasm-apps/test4.wasm new file mode 100644 index 0000000000..b4841a82cb Binary files /dev/null and b/tests/unit/gc/wasm-apps/test4.wasm differ diff --git a/tests/unit/gc/wasm-apps/test4.wast b/tests/unit/gc/wasm-apps/test4.wast new file mode 100644 index 0000000000..8bf02e4307 --- /dev/null +++ b/tests/unit/gc/wasm-apps/test4.wast @@ -0,0 +1,46 @@ +(module + (type $ft (func)) + (type $st (struct)) + (type $at (array i8)) + + (table 10 anyref) + + (elem declare func $f) + (func $f) + + (func (export "init") (param $x externref) + (table.set (i32.const 0) (ref.null any)) + (table.set (i32.const 1) (i31.new (i32.const 7))) + (table.set (i32.const 2) (struct.new_canon_default $st)) + (table.set (i32.const 3) (array.new_canon_default $at (i32.const 0))) + (table.set (i32.const 4) (extern.internalize (local.get $x))) + (table.set (i32.const 5) (ref.null i31)) + (table.set (i32.const 6) (ref.null struct)) + (table.set (i32.const 7) (ref.null none)) + ) + + (func (export "ref_cast_non_null") (param $i i32) + (drop (ref.as_non_null (table.get (local.get $i)))) + (drop (ref.cast null any (table.get (local.get $i)))) + ) + (func (export "ref_cast_null") (param $i i32) + (drop (ref.cast null any (table.get (local.get $i)))) + (drop (ref.cast null struct (table.get (local.get $i)))) + (drop (ref.cast null array (table.get (local.get $i)))) + (drop (ref.cast null i31 (table.get (local.get $i)))) + (drop (ref.cast null none (table.get (local.get $i)))) + ) + (func (export "ref_cast_i31") (param $i i32) + (drop (ref.cast i31 (table.get (local.get $i)))) + (drop (ref.cast null i31 (table.get (local.get $i)))) + ) + (func (export "ref_cast_struct") (param $i i32) + (drop (ref.cast struct (table.get (local.get $i)))) + (drop (ref.cast null struct (table.get (local.get $i)))) + ) + (func (export "ref_cast_array") (param $i i32) + (drop (ref.cast array (table.get (local.get $i)))) + (drop (ref.cast null array (table.get (local.get $i)))) + ) +) + diff --git a/tests/unit/gc/wasm-apps/test5.wasm b/tests/unit/gc/wasm-apps/test5.wasm new file mode 100644 index 0000000000..050ead4ae9 Binary files /dev/null and b/tests/unit/gc/wasm-apps/test5.wasm differ diff --git a/tests/unit/gc/wasm-apps/test5.wast b/tests/unit/gc/wasm-apps/test5.wast new file mode 100644 index 0000000000..895473ce31 --- /dev/null +++ b/tests/unit/gc/wasm-apps/test5.wast @@ -0,0 +1,85 @@ +(module + (type $t0 (sub (struct))) + (type $t1 (sub $t0 (struct (field i32)))) + (type $t1' (sub $t0 (struct (field i32)))) + (type $t2 (sub $t1 (struct (field i32 i32)))) + (type $t2' (sub $t1' (struct (field i32 i32)))) + (type $t3 (sub $t0 (struct (field i32 i32)))) + (type $t0' (sub $t0 (struct))) + (type $t4 (sub $t0' (struct (field i32 i32)))) + + (table 20 (ref null struct)) + + (func $init + (table.set (i32.const 0) (struct.new_canon_default $t0)) + (table.set (i32.const 10) (struct.new_canon_default $t0)) + (table.set (i32.const 1) (struct.new_canon_default $t1)) + (table.set (i32.const 11) (struct.new_canon_default $t1')) + (table.set (i32.const 2) (struct.new_canon_default $t2)) + (table.set (i32.const 12) (struct.new_canon_default $t2')) + (table.set (i32.const 3) (struct.new_canon_default $t3)) + (table.set (i32.const 4) (struct.new_canon_default $t4)) + ) + + (func (export "test-sub") + (call $init) + + (drop (ref.cast null $t0 (ref.null struct))) + (drop (ref.cast null $t0 (table.get (i32.const 0)))) + (drop (ref.cast null $t0 (table.get (i32.const 1)))) + (drop (ref.cast null $t0 (table.get (i32.const 2)))) + (drop (ref.cast null $t0 (table.get (i32.const 3)))) + (drop (ref.cast null $t0 (table.get (i32.const 4)))) + + (drop (ref.cast null $t0 (ref.null struct))) + (drop (ref.cast null $t1 (table.get (i32.const 1)))) + (drop (ref.cast null $t1 (table.get (i32.const 2)))) + + (drop (ref.cast null $t0 (ref.null struct))) + (drop (ref.cast null $t2 (table.get (i32.const 2)))) + + (drop (ref.cast null $t0 (ref.null struct))) + (drop (ref.cast null $t3 (table.get (i32.const 3)))) + + (drop (ref.cast null $t4 (table.get (i32.const 4)))) + + (drop (ref.cast $t0 (table.get (i32.const 0)))) + (drop (ref.cast $t0 (table.get (i32.const 1)))) + (drop (ref.cast $t0 (table.get (i32.const 2)))) + (drop (ref.cast $t0 (table.get (i32.const 3)))) + (drop (ref.cast $t0 (table.get (i32.const 4)))) + + (drop (ref.cast $t1 (table.get (i32.const 1)))) + (drop (ref.cast $t1 (table.get (i32.const 2)))) + + (drop (ref.cast $t2 (table.get (i32.const 2)))) + + (drop (ref.cast $t3 (table.get (i32.const 3)))) + + (drop (ref.cast $t4 (table.get (i32.const 4)))) + ) + + (func (export "test-canon") + (call $init) + + (drop (ref.cast $t0 (table.get (i32.const 0)))) + (drop (ref.cast $t0 (table.get (i32.const 1)))) + (drop (ref.cast $t0 (table.get (i32.const 2)))) + (drop (ref.cast $t0 (table.get (i32.const 3)))) + (drop (ref.cast $t0 (table.get (i32.const 4)))) + + (drop (ref.cast $t0 (table.get (i32.const 10)))) + (drop (ref.cast $t0 (table.get (i32.const 11)))) + (drop (ref.cast $t0 (table.get (i32.const 12)))) + + (drop (ref.cast $t1' (table.get (i32.const 1)))) + (drop (ref.cast $t1' (table.get (i32.const 2)))) + + (drop (ref.cast $t1 (table.get (i32.const 11)))) + (drop (ref.cast $t1 (table.get (i32.const 12)))) + + (drop (ref.cast $t2' (table.get (i32.const 2)))) + + (drop (ref.cast $t2 (table.get (i32.const 12)))) + ) +) diff --git a/tests/unit/gc/wasm-apps/test6.wasm b/tests/unit/gc/wasm-apps/test6.wasm new file mode 100644 index 0000000000..b1abc14729 Binary files /dev/null and b/tests/unit/gc/wasm-apps/test6.wasm differ diff --git a/tests/unit/gc/wasm-apps/test6.wast b/tests/unit/gc/wasm-apps/test6.wast new file mode 100644 index 0000000000..0959b36f0c --- /dev/null +++ b/tests/unit/gc/wasm-apps/test6.wast @@ -0,0 +1,27 @@ +(module + (type $st (sub (struct))) + (type $st' (sub (struct (field i32)))) + (type $at (array i8)) + (type $st-sub1 (sub $st (struct))) + (type $st-sub2 (sub $st (struct))) + (type $st'-sub1 (sub $st' (struct (field i32)))) + (type $st'-sub2 (sub $st' (struct (field i32)))) + + (table 20 (ref null eq)) + + (func (export "init") + (table.set (i32.const 0) (ref.null eq)) + (table.set (i32.const 1) (ref.null i31)) + (table.set (i32.const 2) (i31.new (i32.const 7))) + (table.set (i32.const 3) (i31.new (i32.const 7))) + (table.set (i32.const 4) (i31.new (i32.const 8))) + (table.set (i32.const 5) (struct.new_canon_default $st)) + (table.set (i32.const 6) (struct.new_canon_default $st)) + (table.set (i32.const 7) (array.new_canon_default $at (i32.const 0))) + (table.set (i32.const 8) (array.new_canon_default $at (i32.const 0))) + ) + + (func (export "eq") (param $i i32) (param $j i32) (result i32) + (ref.eq (table.get (local.get $i)) (table.get (local.get $j))) + ) +) diff --git a/tests/unit/interpreter/.gitignore b/tests/unit/interpreter/.gitignore new file mode 100644 index 0000000000..d9b4f015d3 --- /dev/null +++ b/tests/unit/interpreter/.gitignore @@ -0,0 +1 @@ +/build/* diff --git a/tests/unit/interpreter/CMakeLists.txt b/tests/unit/interpreter/CMakeLists.txt new file mode 100644 index 0000000000..c99908b2ed --- /dev/null +++ b/tests/unit/interpreter/CMakeLists.txt @@ -0,0 +1,42 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-interpreter) + +add_definitions (-DRUN_ON_LINUX) + +add_definitions (-Dattr_container_malloc=malloc) +add_definitions (-Dattr_container_free=free) +# add_definitions (-DWASM_ENABLE_WAMR_COMPILER=1) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 1) +set (WAMR_BUILD_AOT 0) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable (interpreter_test ${unit_test_sources}) + +target_link_libraries (interpreter_test ${LLVM_AVAILABLE_LIBS} gtest_main ) + +gtest_discover_tests(interpreter_test) diff --git a/tests/unit/interpreter/interpreter_test.cc b/tests/unit/interpreter/interpreter_test.cc new file mode 100644 index 0000000000..e9fa8f9e16 --- /dev/null +++ b/tests/unit/interpreter/interpreter_test.cc @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include "gtest/gtest.h" +#include "wasm_runtime_common.h" +#include "bh_platform.h" + +// To use a test fixture, derive a class from testing::Test. +class InterpreterTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() { wasm_runtime_destroy(); } + + public: + char global_heap_buf[512 * 1024]; + RuntimeInitArgs init_args; +}; + +TEST_F(InterpreterTest, wasm_runtime_is_built_in_module) +{ + bool ret = wasm_runtime_is_built_in_module("env"); + ASSERT_TRUE(ret); + + ret = ret = wasm_runtime_is_built_in_module("env1"); + ASSERT_FALSE(ret); +} \ No newline at end of file diff --git a/tests/unit/libc-builtin/CMakeLists.txt b/tests/unit/libc-builtin/CMakeLists.txt new file mode 100644 index 0000000000..4d88760e79 --- /dev/null +++ b/tests/unit/libc-builtin/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-libc-builtin) + +add_definitions (-DRUN_ON_LINUX) + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ) + +add_executable (libc_builtin_test ${unit_test_sources}) + +target_link_libraries (libc_builtin_test gtest_main) + +gtest_discover_tests(libc_builtin_test) diff --git a/tests/unit/libc-builtin/func_types.h b/tests/unit/libc-builtin/func_types.h new file mode 100644 index 0000000000..c653ee9c8f --- /dev/null +++ b/tests/unit/libc-builtin/func_types.h @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#pragma once + +#include "bh_platform.h" +#include "wasm_export.h" + +extern "C" { +typedef char *_va_list; + +typedef int (*printf_func_type)(wasm_exec_env_t exec_env, const char *format, + _va_list va_args); + +typedef int (*sprintf_func_type)(wasm_exec_env_t exec_env, char *str, + const char *format, _va_list va_args); + +typedef int (*snprintf_func_type)(wasm_exec_env_t exec_env, char *str, + uint32 size, const char *format, + _va_list va_args); + +typedef int (*puts_func_type)(wasm_exec_env_t exec_env, const char *str); + +typedef int (*putchar_func_type)(wasm_exec_env_t exec_env, int c); + +typedef uint32 (*strdup_func_type)(wasm_exec_env_t exec_env, const char *str); + +typedef uint32 (*_strdup_func_type)(wasm_exec_env_t exec_env, const char *str); + +typedef int32 (*memcmp_func_type)(wasm_exec_env_t exec_env, const void *s1, + const void *s2, uint32 size); + +typedef uint32 (*memcpy_func_type)(wasm_exec_env_t exec_env, void *dst, + const void *src, uint32 size); + +typedef uint32 (*memmove_func_type)(wasm_exec_env_t exec_env, void *dst, + void *src, uint32 size); + +typedef uint32 (*memset_func_type)(wasm_exec_env_t exec_env, void *s, int32 c, + uint32 size); + +typedef uint32 (*strchr_func_type)(wasm_exec_env_t exec_env, const char *s, + int32 c); + +typedef int32 (*strcmp_func_type)(wasm_exec_env_t exec_env, const char *s1, + const char *s2); + +typedef int32 (*strncmp_func_type)(wasm_exec_env_t exec_env, const char *s1, + const char *s2, uint32 size); + +typedef uint32 (*strcpy_func_type)(wasm_exec_env_t exec_env, char *dst, + const char *src); + +typedef uint32 (*strncpy_func_type)(wasm_exec_env_t exec_env, char *dst, + const char *src, uint32 size); + +typedef uint32 (*strlen_func_type)(wasm_exec_env_t exec_env, const char *s); + +typedef uint32 (*malloc_func_type)(wasm_exec_env_t exec_env, uint32 size); + +typedef uint32 (*calloc_func_type)(wasm_exec_env_t exec_env, uint32 nmemb, + uint32 size); + +typedef uint32 (*realloc_func_type)(wasm_exec_env_t exec_env, uint32 ptr, + uint32 new_size); + +typedef void (*free_func_type)(wasm_exec_env_t exec_env, void *ptr); + +typedef int32 (*atoi_func_type)(wasm_exec_env_t exec_env, const char *s); + +typedef void (*exit_func_type)(wasm_exec_env_t exec_env, int32 status); + +typedef int32 (*strtol_func_type)(wasm_exec_env_t exec_env, const char *nptr, + char **endptr, int32 base); + +typedef uint32 (*strtoul_func_type)(wasm_exec_env_t exec_env, const char *nptr, + char **endptr, int32 base); + +typedef uint32 (*memchr_func_type)(wasm_exec_env_t exec_env, const void *s, + int32 c, uint32 n); + +typedef int32 (*strncasecmp_func_type)(wasm_exec_env_t exec_env, const char *s1, + const char *s2, uint32 n); +typedef uint32 (*strspn_func_type)(wasm_exec_env_t exec_env, const char *s, + const char *accept); + +typedef uint32 (*strcspn_func_type)(wasm_exec_env_t exec_env, const char *s, + const char *reject); + +typedef uint32 (*strstr_func_type)(wasm_exec_env_t exec_env, const char *s, + const char *find); + +typedef int32 (*isupper_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isalpha_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isspace_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isgraph_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isprint_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isdigit_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isxdigit_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*tolower_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*toupper_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isalnum_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef void (*setTempRet0_func_type)(wasm_exec_env_t exec_env, + uint32 temp_ret); + +typedef uint32 (*getTempRet0_func_type)(wasm_exec_env_t exec_env); + +typedef uint32 (*llvm_bswap_i16_func_type)(wasm_exec_env_t exec_env, + uint32 data); + +typedef uint32 (*llvm_bswap_i32_func_type)(wasm_exec_env_t exec_env, + uint32 data); + +typedef uint32 (*bitshift64Lshr_func_type)(wasm_exec_env_t exec_env, + uint32 uint64_part0, + uint32 uint64_part1, uint32 bits); + +typedef uint32 (*bitshift64Shl_func_type)(wasm_exec_env_t exec_env, + uint32 int64_part0, + uint32 int64_part1, uint32 bits); + +typedef void (*llvm_stackrestore_func_type)(wasm_exec_env_t exec_env, + uint32 llvm_stack); + +typedef uint32 (*llvm_stacksave_func_type)(wasm_exec_env_t exec_env); + +typedef uint32 (*emscripten_memcpy_big_func_type)(wasm_exec_env_t exec_env, + void *dst, const void *src, + uint32 size); + +typedef void (*abort_func_type)(wasm_exec_env_t exec_env, int32 code); + +typedef void (*abortStackOverflow_func_type)(wasm_exec_env_t exec_env, + int32 code); + +typedef void (*nullFunc_X_func_type)(wasm_exec_env_t exec_env, int32 code); + +typedef uint32 (*__cxa_allocate_exception_func_type)(wasm_exec_env_t exec_env, + uint32 thrown_size); + +typedef void (*__cxa_begin_catch_func_type)(wasm_exec_env_t exec_env, + void *exception_object); + +typedef void (*__cxa_throw_func_type)(wasm_exec_env_t exec_env, + void *thrown_exception, void *tinfo, + uint32 table_elem_idx); + +struct timespec_app { + int64 tv_sec; + int32 tv_nsec; +}; + +typedef uint32 (*clock_gettime_func_type)(wasm_exec_env_t exec_env, + uint32 clk_id, + struct timespec_app *ts_app); + +typedef uint64 (*clock_func_type)(wasm_exec_env_t exec_env); +} diff --git a/tests/unit/libc-builtin/libc_builtin_test.cc b/tests/unit/libc-builtin/libc_builtin_test.cc new file mode 100644 index 0000000000..6598f7a8b6 --- /dev/null +++ b/tests/unit/libc-builtin/libc_builtin_test.cc @@ -0,0 +1,1412 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "func_types.h" +#include "test_helper.h" +#include "wasm_export.h" +#include "gtest/gtest.h" +#include + +#include "../interpreter/wasm.h" + +void *func_ptr; +#define CALL_FUNC(name, ...) \ + ((name##_func_type)get_func(#name))(dummy_exec_env.get(), ##__VA_ARGS__) + +extern "C" { +extern uint32_t +get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis); + +extern bool +wasm_native_lookup_libc_builtin_global(const char *module_name, + const char *global_name, + WASMGlobalImport *global); +} + +class LibcBuiltinTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() + { + n_native_symbols = get_libc_builtin_export_apis(&native_symbols); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; + DummyExecEnv dummy_exec_env; + static NativeSymbol *native_symbols; + static uint32_t n_native_symbols; + + static void *get_func(const char *name) + { + int32_t i; + + for (i = 0; i < n_native_symbols; i++) { + if (strcmp(native_symbols[i].symbol, name) == 0) { + return native_symbols[i].func_ptr; + } + } + + return NULL; + } +}; + +NativeSymbol *LibcBuiltinTest::native_symbols; +uint32_t LibcBuiltinTest::n_native_symbols; + +static const char very_long_string[] = + R"(2mwa9vxDhuuvO47XePZvc4DAMdR8dzgKrmRNAM3qVoedFhG7GYyhlC4JiuSdrw8G + 7vrPoCLGlVlGwMw7ATDL3bA5Filds8krTxS7h8ioq6CY4UmKl1zjHlmnOYRO3Wmp + ylp21RrG8LzfHFerFyKFxA1GB93OuTFcasO2n9uQljCx8h5KRolbvjdHVnado4B6 + 3zNV990V7T7LIJHwZKb0RGg0fFo4GQd6Mfdl6aD3UlpKBIxjbonyeaQBY7hPZB8R + J1JV5iw2PWB2BJEGoGhTvlc0a9FxmeqWIjpnU3yNEg2lD3NjZU627pTFcoAy5GCz + wDyF5QzcvtAgWBR95kRpDtV21CRyQ6HteorX1aHemoMYWOLIvX52stUTAnOImMD8 + tIw6xwkOZx5fs3x9m540pPnRDiihLn2XuQ1PLPwA6orWOGm3dBKthqsycTqaIl0L + 0gpycKbVYFHmakfgEyP9fyMziLT11B6EPzomHQAYgTVUdDl9u63P6sQCeaPwAYsY + gus28uK9YYjpXgOOziG8ocBddvids1iLJLdbiAqKyHaVY4IBLVWU3F74tKGF7TeI + DGAfvpzHls19VM9bKReBfCmDgbib7mCpYEFAQCmu5my0C8QrJlUoOgiljIO0x3sH + ByNf4k9OfhzYi1V4cvDnMELVrk0fyZWmIxDvig7nfzI57OltT28pughPBlLxTn8X + xyMNVYn1dD6Wpp7sqOBjxWGWmdrjleyin0iQ05UbfioHazvLKHtDfm5P2WwVejm6)"; + +TEST_F(LibcBuiltinTest, puts) +{ + char ll_string[2048]; + + /* Capture the stdout */ + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(puts, "Hello Wrold"), strlen("Hello Wrold\n")); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "Hello Wrold\n"); + + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(puts, "c"), strlen("c\n")); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "c\n"); + + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(puts, very_long_string), strlen(very_long_string) + 1); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + std::string(very_long_string) + "\n"); + + memset(ll_string, 0xAA, sizeof(ll_string)); + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(puts, ll_string), strlen(ll_string) + 1); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + std::string(ll_string) + "\n"); +} + +TEST_F(LibcBuiltinTest, printf) +{ + WAMRVaList empty_va_list(dummy_exec_env.get()); + + /* Capture the stdout */ + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", empty_va_list.get()), + strlen("Hello Wrold")); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "Hello Wrold"); + + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(printf, "c", empty_va_list.get()), strlen("c")); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "c"); + + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(printf, very_long_string, empty_va_list.get()), + strlen(very_long_string)); + EXPECT_EQ(testing::internal::GetCapturedStdout(), very_long_string); + + /* type */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(20); //%d 20 + va_list.add(65); //%i 65 + va_list.add(10); //%O 12 + va_list.add(10); //%u 10 + va_list.add(255); //%x ff + va_list.add(255); //%X FF + va_list.add(3.14); //%f 3.14 + va_list.add(3.14); //%F 3.14 + va_list.add(0.000001); //%e 1.000000e-06 + va_list.add(0.000001); //%E 1.000000E-06 + va_list.add(0.000001); //%g 1e-06 + va_list.add(0.000001); //%G 1E-06 + va_list.add("Hello World"); //%s Hello World + + testing::internal::CaptureStdout(); + /* clang-format off */ + EXPECT_EQ(CALL_FUNC(printf, "%d, %i, %o, %u, %x, %X, %f, %F, %e, %E, %g, %G, %s", va_list.get()), 97); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + "20, 65, 12, 10, ff, FF, 3.140000, 3.140000, 1.000000e-06, 1.000000E-06, 1e-06, 1E-06, Hello World"); + /* clang-format on */ + } + + /* %c */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add('C'); //%c C + // va_list.add("Hello"); //%p + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(printf, "%c", va_list.get()), 1); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "C"); + } + + /* %p */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add("Hello"); + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(printf, "%p", va_list.get()), 7); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "0x200a8"); + } + + { + /* clang-format off */ + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(20); //%td + va_list.add(20); //%zd + va_list.add(20); //%ld + + va_list.add(20L); //%jd + + testing::internal::CaptureStdout(); + + EXPECT_EQ(CALL_FUNC(printf, "%td, %zd, %ld, %jd", va_list.get()), 14); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + "20, 20, 20, 20"); + /* clang-format on */ + } + + /* %% */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + EXPECT_TRUE(CALL_FUNC(printf, "%%", va_list.get())); + } + + /* %n */ + { + /* Construct a va_list to call printf */ + WAMRVaList empty_va_list(dummy_exec_env.get()); + + /* Capture the stdout */ + testing::internal::CaptureStdout(); + CALL_FUNC(printf, "0123%n", empty_va_list.get()); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "0123"); + } + + /* flag */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + /*%-*/ + va_list.add(20); //%-d 20 + va_list.add(20); //%d 20 + + /*%+*/ + va_list.add(20); //%+d +20 + va_list.add(-20); //%+d -20 + + /*% */ + va_list.add(20); //% d 20 + va_list.add(-20); //% d -20 + + /*%#*/ + va_list.add(20); //%#o 024 + va_list.add(255); //%#x 0xff + va_list.add(255); //%#X 0xFF + va_list.add(3.14); //%#.f 3. + va_list.add(3.14); //%#.lf 3. + va_list.add(3.14); //%#.e 3.e+00 + va_list.add(3.14); //%#.E 3.E+00 + va_list.add(3.14); //%#.g 3. + va_list.add(3.14); //%#.G 3. + va_list.add(20); //%#.a %a + va_list.add(20); //%#.A %A + + /*%0*/ + va_list.add(20); //%03d 020 + + testing::internal::CaptureStdout(); + /* clang-format off */ + EXPECT_EQ(CALL_FUNC(printf, "%-d, %d, %+d, %+d, % d, % d, %#o, %#x, %#X, %#.f, %#.lf, %#.e, %#.E, %#.g, %#.G, %#.a, %#.A, %03d", va_list.get()), 88); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + "20, 20, +20, -20, 20, -20, 024, 0xff, 0XFF, 3., 3., 3.e+00, 3.E+00, 3., 3., %a, %A, 020"); + /* clang-format on */ + } + + /* precision */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(20); //%d 20 + va_list.add(20); //%.1d 20 + va_list.add(20); //%.2d 20 + va_list.add(20); //%.3d 020 + va_list.add(20); //%.4d 0020 + va_list.add(20); //%.5d 00020 + va_list.add(20); //%.6d 000020 + va_list.add(20); //%.7d 0000020 + va_list.add(20); //%.8d 00000020 + va_list.add(20); //%.9d 000000020 + testing::internal::CaptureStdout(); + /* clang-format off */ + EXPECT_EQ(CALL_FUNC(printf, "%d, %.1d, %.2d, %.3d, %.4d, %.5d, %.6d, %.7d, %.8d, %.9d", va_list.get()), 66); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + "20, 20, 20, 020, 0020, 00020, 000020, 0000020, 00000020, 000000020"); + /* clang-format on */ + } + + /*length*/ + { + /* clang-format off */ + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(0x7F); //%hhd 127 -char + va_list.add(0xFF); //%hhu.1d 255 -unsiged char + va_list.add(0x7FFF); //%hd 32767 -sing short int + va_list.add(0xFFFF); //%hu 65535 -unsiged short + va_list.add(0x7FFFFFFF); //%ld 2147483647 - sing long + va_list.add(0xFFFFFFFF); //%lu 4294967295 -unsigned long + va_list.add(0x7FFFFFFFFFFFFFFF); //%lld 9223372036854775807 sing long long + va_list.add(0xFFFFFFFFFFFFFFFF);//%llu 18446744073709551615 unsiged long long + + testing::internal::CaptureStdout(); + + EXPECT_EQ(CALL_FUNC(printf, "%hhd, %hhu, %hd, %hu, %ld, %lu, %lld, %llu", va_list.get()), 89); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + "127, 255, 32767, 65535, 2147483647, 4294967295, 9223372036854775807, 18446744073709551615"); + /* clang-format on */ + } + + EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", 0), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", NULL), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", (char *)-1), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_EQ(CALL_FUNC(printf, (char *)-1, (char *)-1), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); +} + +TEST_F(LibcBuiltinTest, sprintf) +{ + const char *buf; + const char *str = "Hello Wrold"; + const char *str_sig = "c"; + const char *str_f = "20, 3.140000, Hello World"; + const char *str_long = "eqwewerwerqwer34were"; // test ok + // const char *str_long = "TDSFGAWE%#$TERFQ@$%$@!%$@!RS!$#@$%" + // "WAWAAEWAFSDNGFUTKNZDAERQWYNZREWGHAH"; + // //fail + + WAMRVaList empty_va_list(dummy_exec_env.get()); + + AppData buf_app{ dummy_exec_env.get(), buf }; + AppData str_app{ dummy_exec_env.get(), str }; + AppData str_sig_app{ dummy_exec_env.get(), str_sig }; + AppData str_long_app{ dummy_exec_env.get(), str_long }; + + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_app.get_native_addr(), 0), + 0); + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_app.get_native_addr(), NULL), + 0); + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_app.get_native_addr(), (char *)-1), + 0); + + EXPECT_FALSE(CALL_FUNC(sprintf, (char *)-1, + (char *)str_app.get_native_addr(), + empty_va_list.get())); + + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_app.get_native_addr(), empty_va_list.get()), + strlen(str)); + EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(), + str_app.get_native_addr(), strlen(str)), + 0); + + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_sig_app.get_native_addr(), + empty_va_list.get()), + strlen(str_sig)); + EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(), + str_sig_app.get_native_addr(), strlen(str_sig)), + 0); + + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_long_app.get_native_addr(), + empty_va_list.get()), + strlen(str_long)); + EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(), + str_long_app.get_native_addr(), strlen(str_long)), + 0); + + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(20); + va_list.add(3.14); + va_list.add("Hello World"); + + /* This is like printf("%d, %f, %s", 20, 3.14, "Hello World") */ + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + "%d, %f, %s", va_list.get()), + 25); + EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(), str_f, 25), 0); + } +} + +TEST_F(LibcBuiltinTest, snprintf) +{ + char buf[1024]; + char buf1[10]; + + WAMRVaList empty_va_list(dummy_exec_env.get()); + + EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", 0), + 0); + EXPECT_EQ( + CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", NULL), + 0); + EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", + (char *)-1), + 0); + + EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", + empty_va_list.get()), + strlen("Hello Wrold")); + EXPECT_EQ(CALL_FUNC(memcmp, buf, "Hello Wrold", strlen("Hello Wrold")), 0); + + EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen(very_long_string), + very_long_string, empty_va_list.get()), + strlen(very_long_string)); + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(20); + va_list.add(3.14); + va_list.add("Hello World"); + + EXPECT_EQ(CALL_FUNC(snprintf, buf, 25, "%d, %f, %s", va_list.get()), + 25); + } +} + +TEST_F(LibcBuiltinTest, putchar) +{ + char ch; + + for (ch = 'a'; ch <= 'z'; ch++) + EXPECT_EQ(CALL_FUNC(putchar, ch), 1); + + for (ch = '0'; ch <= '9'; ch++) + EXPECT_EQ(CALL_FUNC(putchar, ch), 1); + + for (ch = 0; ch < 127; ch++) + EXPECT_EQ(CALL_FUNC(putchar, ch), 1); +} + +TEST_F(LibcBuiltinTest, strdup) +{ + const char *src = "Hello World!"; + + AppData src_app{ dummy_exec_env.get(), src }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(strdup, NULL), 0); + + EXPECT_GE(CALL_FUNC(strdup, (char *)src_app.get_native_addr()), 0); +} + +TEST_F(LibcBuiltinTest, _strdup) +{ + const char *src = "Hello World!"; + + AppData src_app{ dummy_exec_env.get(), src }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(_strdup, NULL), 0); + + EXPECT_GE(CALL_FUNC(_strdup, (char *)src_app.get_native_addr()), 0); +} + +TEST_F(LibcBuiltinTest, memcmp) +{ + const char *a = "aBcDeF"; + const char *b = "AbCdEf"; + const char *c = "aacdef"; + const char *d = "aBcDeF"; + + AppData a_app{ dummy_exec_env.get(), a }; + AppData b_app{ dummy_exec_env.get(), b }; + AppData c_app{ dummy_exec_env.get(), c }; + AppData d_app{ dummy_exec_env.get(), d }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(memcmp, (void *)-1, d_app.get_native_addr(), 0), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + /* size = 0 */ + EXPECT_EQ( + CALL_FUNC(memcmp, a_app.get_native_addr(), d_app.get_native_addr(), 0), + 0); + + // /* s1>s2 */ + EXPECT_GT(CALL_FUNC(memcmp, a_app.get_native_addr(), + b_app.get_native_addr(), strlen(a)), + 0); + // /* s1s2*/ + EXPECT_GT(CALL_FUNC(strcmp, (char *)b_app.get_native_addr(), + (char *)a_app.get_native_addr()), + 0); + /*s1s2*/ + EXPECT_GT(CALL_FUNC(strncmp, (char *)b_app.get_native_addr(), + (char *)a_app.get_native_addr(), strlen(a)), + 0); + /*s1s2*/ + EXPECT_GT(CALL_FUNC(strncmp, (char *)b_app.get_native_addr(), + (char *)a_app.get_native_addr(), 3), + 0); + /*s1= UINT32_MAX */ + EXPECT_EQ(CALL_FUNC(calloc, 1, 0xffffffff), 0); + + /* nmemb = 1 size=0xffffffff-1 total_size >= UINT32_MAX-1 */ + EXPECT_EQ(CALL_FUNC(calloc, 1, (0xffffffff - 1)), 0); + + /* nmemb = 1 size = 0 total_size = 0 */ + /* According to Linux man page: + If nmemb or size is 0, then calloc() returns either NULL, or a unique + pointer value that can later be successfully passed to free() */ + EXPECT_GE(CALL_FUNC(calloc, 1, 0), 0); + + /* nmemb = 10 size = 1024 total_size < UINT32_MAX */ + EXPECT_GT(CALL_FUNC(calloc, 10, 1024), 0); +} + +TEST_F(LibcBuiltinTest, realloc) +{ + unsigned int ptr = 0; + + // ptr = 0; + // EXPECT_EQ(CALL_FUNC(realloc, ptr, 1024), 0); + + // ptr = 1; + // EXPECT_GT(CALL_FUNC(realloc, ptr, 1024), 0); + + // ptr = 3; + // EXPECT_GT(CALL_FUNC(realloc, ptr, 1024), 0); + + /* If ptr is NULL, then the call is equivalent to malloc(size), for all + * values of size */ + ptr = CALL_FUNC(realloc, ptr, 1024); + EXPECT_EQ(ptr, ptr); + EXPECT_EQ(CALL_FUNC(realloc, ptr, 10), ptr); + EXPECT_EQ(CALL_FUNC(realloc, ptr, 15), ptr); + + ptr = CALL_FUNC(realloc, ptr, 2048); + EXPECT_EQ(ptr, ptr); + + /* If size is equal to zero, and ptr is not NULL, then + the call is equivalent to free(ptr) */ + CALL_FUNC(realloc, ptr, 0); +} + +TEST_F(LibcBuiltinTest, free) +{ + const char *src; + const char *s = "Hello World!"; + + AppMemory src_mem{ dummy_exec_env.get(), 15 }; + AppData s_app{ dummy_exec_env.get(), s }; + + CALL_FUNC(free, (char *)0xFFFFFFFF); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + CALL_FUNC(free, (char *)-1); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + CALL_FUNC(free, NULL); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + memset((char *)src_mem.get_native_addr(), '\0', 15); + strcpy((char *)src_mem.get_native_addr(), (char *)s_app.get_native_addr()); + EXPECT_EQ(CALL_FUNC(memcmp, (char *)src_mem.get_native_addr(), + s_app.get_native_addr(), 15), + 0); + + /* free */ + CALL_FUNC(free, (char *)src_mem.get_native_addr()); + EXPECT_NE(CALL_FUNC(memcmp, (char *)src_mem.get_native_addr(), + s_app.get_native_addr(), 15), + 0); +} + +TEST_F(LibcBuiltinTest, atoi) +{ + char *src = (char *)"123"; + char *src1 = (char *)"-123"; + + AppData src_app{ dummy_exec_env.get(), src }; + AppData src1_app{ dummy_exec_env.get(), src1 }; + + EXPECT_EQ(CALL_FUNC(atoi, (char *)src_app.get_native_addr()), 123); + EXPECT_EQ(CALL_FUNC(atoi, (char *)src1_app.get_native_addr()), -123); +} + +TEST_F(LibcBuiltinTest, exit) +{ + CALL_FUNC(exit, 3); + EXPECT_STREQ(dummy_exec_env.get_exception(), "Exception: env.exit(3)"); + dummy_exec_env.clear_exception(); +} + +TEST_F(LibcBuiltinTest, strtol) +{ + char str[20] = "20"; + char str1[20] = "-20"; + char buffer[20] = "0x31"; + char buffer1[20] = "10379cend$3"; + char *ptr; + + AppData src_app{ dummy_exec_env.get(), str }; + AppData src1_app{ dummy_exec_env.get(), str1 }; + AppData buffer_app{ dummy_exec_env.get(), buffer }; + AppData buffer1_app{ dummy_exec_env.get(), buffer1 }; + AppMemory ptr_app{ dummy_exec_env.get(), 20 }; + + CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 10); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + CALL_FUNC(strtol, (char *)src_app.get_native_addr(), &ptr, 10); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 2), 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 8), 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 10), + 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 16), + 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 32), + 0); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 2), + 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 8), + 16); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 20); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 16), + 32); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 32), + 64); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 2), + 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 8), + -16); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + -20); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 16), + -32); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 32), + -64); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 0), + 49); + EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 16), + 49); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 0); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 10379); + // EXPECT_STREQ((char *)ptr_app.get_native_addr(), "cend$3"); + + uint32_t str_app_addr = *(uint32_t *)ptr_app.get_native_addr(); + EXPECT_GT(str_app_addr, 0); + char *str_native_addr = (char *)dummy_exec_env.app_to_native(str_app_addr); + EXPECT_NE(str_native_addr, nullptr); + EXPECT_STREQ(str_native_addr, "cend$3"); +} + +TEST_F(LibcBuiltinTest, strtoul) +{ + char str[20] = "20"; + char buffer[20] = "0x31"; + char buffer1[20] = "10379cend$3"; + char *ptr; + + AppData src_app{ dummy_exec_env.get(), str }; + AppData buffer_app{ dummy_exec_env.get(), buffer }; + AppData buffer1_app{ dummy_exec_env.get(), buffer1 }; + AppMemory ptr_app{ dummy_exec_env.get(), 20 }; + + CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 10); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), &ptr, 10); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 2), + 0); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 8), + 0); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 10), + 0); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 16), + 0); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 32), + 0); + + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 2), + 0); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 8), + 16); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 20); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 16), + 32); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 32), + 64); + + EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 0), + 49); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 16), + 49); + + EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 0); + + EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 10379); + + uint32_t str_app_addr = *(uint32_t *)ptr_app.get_native_addr(); + EXPECT_GT(str_app_addr, 0); + char *str_native_addr = (char *)dummy_exec_env.app_to_native(str_app_addr); + EXPECT_NE(str_native_addr, nullptr); + EXPECT_STREQ(str_native_addr, "cend$3"); +} + +TEST_F(LibcBuiltinTest, memchr) +{ + const char src[] = "Hello World."; + char ch = 'o'; + + AppData src_app{ dummy_exec_env.get(), src }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(memchr, (char *)-1, ch, strlen(src)), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_GE(CALL_FUNC(memchr, src_app.get_native_addr(), ch, strlen(src)), 0); +} + +TEST_F(LibcBuiltinTest, strncasecmp) +{ + const char *src1 = "Hello World."; + const char *src2 = "hel"; + const char *src3 = "HELLO WORLD."; + + AppData src1_app{ dummy_exec_env.get(), src1 }; + AppData src2_app{ dummy_exec_env.get(), src2 }; + AppData src3_app{ dummy_exec_env.get(), src3 }; + + EXPECT_GT(CALL_FUNC(strncasecmp, (char *)src1_app.get_native_addr(), + (char *)src2_app.get_native_addr(), 4), + 0); + + EXPECT_LT(CALL_FUNC(strncasecmp, (char *)src2_app.get_native_addr(), + (char *)src1_app.get_native_addr(), 4), + 0); + + EXPECT_EQ(CALL_FUNC(strncasecmp, (char *)src1_app.get_native_addr(), + (char *)src3_app.get_native_addr(), strlen(src1)), + 0); +} + +TEST_F(LibcBuiltinTest, strspn) +{ + const char *src1 = "Hello world!"; + const char *src2 = "abcd"; + const char *src3 = "l"; + const char *src4 = "Hell"; + const char *src5 = "Helo"; + + AppData src1_app{ dummy_exec_env.get(), src1 }; + AppData src2_app{ dummy_exec_env.get(), src2 }; + AppData src3_app{ dummy_exec_env.get(), src3 }; + AppData src4_app{ dummy_exec_env.get(), src4 }; + AppData src5_app{ dummy_exec_env.get(), src5 }; + + EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(), + (char *)src2_app.get_native_addr()), + 0); + + EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(), + (char *)src3_app.get_native_addr()), + 0); + + EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(), + (char *)src4_app.get_native_addr()), + 4); + + EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(), + (char *)src5_app.get_native_addr()), + 5); +} + +TEST_F(LibcBuiltinTest, strcspn) +{ + const char *src1 = "Hello world!"; + const char *src2 = ".?"; + const char *src3 = "llo"; + const char *src4 = "http://www.baidu.com/"; + const char *src5 = "?.,:\"\'-!"; + + AppData src1_app{ dummy_exec_env.get(), src1 }; + AppData src2_app{ dummy_exec_env.get(), src2 }; + AppData src3_app{ dummy_exec_env.get(), src3 }; + AppData src4_app{ dummy_exec_env.get(), src4 }; + AppData src5_app{ dummy_exec_env.get(), src5 }; + + EXPECT_EQ(CALL_FUNC(strcspn, (char *)src1_app.get_native_addr(), + (char *)src2_app.get_native_addr()), + 12); + + EXPECT_EQ(CALL_FUNC(strcspn, (char *)src1_app.get_native_addr(), + (char *)src3_app.get_native_addr()), + 2); + + EXPECT_EQ(CALL_FUNC(strcspn, (char *)src4_app.get_native_addr(), + (char *)src5_app.get_native_addr()), + 4); +} + +TEST_F(LibcBuiltinTest, strstr) +{ + const char *src1 = "Hello world!"; + const char *src2 = "abcd"; + const char *src3 = "Hello"; + const char *src4 = "H"; + const char *src5 = "llo"; + + AppData src1_app{ dummy_exec_env.get(), src1 }; + AppData src2_app{ dummy_exec_env.get(), src2 }; + AppData src3_app{ dummy_exec_env.get(), src3 }; + AppData src4_app{ dummy_exec_env.get(), src4 }; + AppData src5_app{ dummy_exec_env.get(), src5 }; + + EXPECT_EQ(CALL_FUNC(strstr, (char *)src1_app.get_native_addr(), + (char *)src2_app.get_native_addr()), + 0); + + EXPECT_EQ(CALL_FUNC(strstr, (char *)src3_app.get_native_addr(), + (char *)src1_app.get_native_addr()), + 0); + + EXPECT_GT(CALL_FUNC(strstr, (char *)src1_app.get_native_addr(), + (char *)src4_app.get_native_addr()), + 0); + + EXPECT_GT(CALL_FUNC(strstr, (char *)src1_app.get_native_addr(), + (char *)src5_app.get_native_addr()), + 0); +} + +TEST_F(LibcBuiltinTest, isupper) +{ + EXPECT_FALSE(CALL_FUNC(isupper, 'a')); + + EXPECT_FALSE(CALL_FUNC(isupper, 97)); + + EXPECT_FALSE(CALL_FUNC(isupper, '0')); + + EXPECT_FALSE(CALL_FUNC(isupper, '.')); + + EXPECT_TRUE(CALL_FUNC(isupper, 'A')); + + EXPECT_TRUE(CALL_FUNC(isupper, 65)); +} + +TEST_F(LibcBuiltinTest, isalpha) +{ + EXPECT_FALSE(CALL_FUNC(isalpha, '0')); + + EXPECT_FALSE(CALL_FUNC(isalpha, 0)); + + EXPECT_FALSE(CALL_FUNC(isalpha, '?')); + + EXPECT_TRUE(CALL_FUNC(isalpha, 'A')); + + EXPECT_TRUE(CALL_FUNC(isalpha, 'a')); +} + +TEST_F(LibcBuiltinTest, isspace) +{ + EXPECT_FALSE(CALL_FUNC(isspace, '0')); + + EXPECT_FALSE(CALL_FUNC(isspace, 0)); + + EXPECT_FALSE(CALL_FUNC(isspace, '?')); + + EXPECT_TRUE(CALL_FUNC(isspace, ' ')); + EXPECT_TRUE(CALL_FUNC(isspace, '\t')); + EXPECT_TRUE(CALL_FUNC(isspace, '\n')); + EXPECT_TRUE(CALL_FUNC(isspace, '\v')); + EXPECT_TRUE(CALL_FUNC(isspace, '\f')); + EXPECT_TRUE(CALL_FUNC(isspace, '\r')); +} + +TEST_F(LibcBuiltinTest, isgraph) +{ + /* ASCII 0x00-0x20 */ + EXPECT_FALSE(CALL_FUNC(isgraph, 0x00)); + EXPECT_FALSE(CALL_FUNC(isgraph, 0x20)); + + /* ASCII 0x7F */ + EXPECT_FALSE(CALL_FUNC(isgraph, 0x7F)); + EXPECT_FALSE(CALL_FUNC(isgraph, 0x80)); + + /* ASCII 0x21-0x7E */ + EXPECT_TRUE(CALL_FUNC(isgraph, 0x21)); + EXPECT_TRUE(CALL_FUNC(isgraph, 0x7E)); +} + +TEST_F(LibcBuiltinTest, isprint) +{ + /* ASCII 0x00-0x1F */ + EXPECT_FALSE(CALL_FUNC(isprint, 0x00)); + EXPECT_FALSE(CALL_FUNC(isprint, 0x1F)); + + /* ASCII 0x7F */ + EXPECT_FALSE(CALL_FUNC(isprint, 0x7F)); + EXPECT_FALSE(CALL_FUNC(isprint, 0x80)); + + /* ASCII 0x20-0x7E */ + EXPECT_TRUE(CALL_FUNC(isprint, 0x20)); + EXPECT_TRUE(CALL_FUNC(isprint, 0x7E)); +} + +TEST_F(LibcBuiltinTest, isdigit) +{ + /* ASCII 0x00-0x2F */ + EXPECT_FALSE(CALL_FUNC(isdigit, 0x00)); + EXPECT_FALSE(CALL_FUNC(isdigit, 0x2F)); + + /* ASCII 0x3A-0x7F */ + EXPECT_FALSE(CALL_FUNC(isdigit, 0x3A)); + EXPECT_FALSE(CALL_FUNC(isdigit, 0x7F)); + + /* ASCII 0x30-0x39 */ + EXPECT_TRUE(CALL_FUNC(isdigit, 0x30)); + EXPECT_TRUE(CALL_FUNC(isdigit, 0x39)); +} + +TEST_F(LibcBuiltinTest, isxdigit) +{ + char str[] = "-FFEE"; + char str1[] = "FFEE"; + + EXPECT_FALSE(CALL_FUNC(isxdigit, str[0])); + EXPECT_TRUE(CALL_FUNC(isxdigit, str1[0])); + + /* ASCII 0x00-0x2F */ + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x00)); + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x2F)); + + /* ASCII 0x3A-0x40 */ + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x3A)); + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x40)); + + /* ASCII 0x49-0x60 */ + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x49)); + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x60)); + + /* ASCII 0x67-0x7F */ + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x67)); + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x7F)); + + /* ASCII 0x30-0x39 */ + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x30)); + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x39)); + + /* ASCII 0x41-0x46 */ + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x41)); + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x46)); + + /* ASCII 0x61-0x66 */ + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x61)); + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x66)); +} + +TEST_F(LibcBuiltinTest, tolower) +{ + char src[] = "aBcDeFgH12345;!#$"; + char dest[sizeof(src)]; + int i; + + for (i = 0; i < sizeof(src); i++) { + dest[i] = CALL_FUNC(tolower, (src[i])); + } + EXPECT_STREQ(dest, "abcdefgh12345;!#$"); +} + +TEST_F(LibcBuiltinTest, toupper) +{ + char src[] = "aBcDeFgH12345;!#$"; + char dest[sizeof(src)]; + int i; + + for (i = 0; i < sizeof(src); i++) { + dest[i] = CALL_FUNC(toupper, (src[i])); + } + EXPECT_STREQ(dest, "ABCDEFGH12345;!#$"); +} + +TEST_F(LibcBuiltinTest, isalnum) +{ + char src[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678" + "9!\"#$%&'()*+,-./:;<=>?@[^_'{|}~"; + int i; + int isalnum_cnt = 0; + + for (i = 0; i < sizeof(src); i++) { + if (CALL_FUNC(isalnum, (src[i]))) + isalnum_cnt++; + } + EXPECT_EQ(isalnum_cnt, 62); +} + +TEST_F(LibcBuiltinTest, emscripten_memcpy_big) +{ + const char *src = "Hell World"; + char *dest; + + AppData src_app{ dummy_exec_env.get(), src }; + AppData dest_app{ dummy_exec_env.get(), dest }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(emscripten_memcpy_big, (void *)-1, + src_app.get_native_addr(), 0), + 0); + + CALL_FUNC(emscripten_memcpy_big, dest_app.get_native_addr(), + src_app.get_native_addr(), strlen(src)); + EXPECT_EQ(CALL_FUNC(memcmp, dest_app.get_native_addr(), + src_app.get_native_addr(), strlen(src)), + 0); +} + +TEST_F(LibcBuiltinTest, abort) +{ + CALL_FUNC(abort, 33); + EXPECT_STREQ(dummy_exec_env.get_exception(), "Exception: env.abort(33)"); + dummy_exec_env.clear_exception(); +} + +TEST_F(LibcBuiltinTest, abortStackOverflow) +{ + CALL_FUNC(abortStackOverflow, 33); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: env.abortStackOverflow(33)"); + dummy_exec_env.clear_exception(); +} + +TEST_F(LibcBuiltinTest, nullFunc_X) +{ + CALL_FUNC(nullFunc_X, 33); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: env.nullFunc_X(33)"); + dummy_exec_env.clear_exception(); +} + +TEST_F(LibcBuiltinTest, __cxa_allocate_exception) +{ + EXPECT_NE(CALL_FUNC(__cxa_allocate_exception, 0x0), 0x0); + EXPECT_EQ(CALL_FUNC(__cxa_allocate_exception, 0xFFFF), 0x0); +} + +TEST_F(LibcBuiltinTest, __cxa_begin_catch) +{ + /* 无函数原型 */ +} + +TEST_F(LibcBuiltinTest, __cxa_throw) +{ + void *excepton; + void *tinfo; + + CALL_FUNC(__cxa_throw, excepton, tinfo, 1); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: exception thrown by stdc++"); + dummy_exec_env.clear_exception(); +} + +struct timespec_app app; +TEST_F(LibcBuiltinTest, clock_gettime) +{ + struct timespec_app *tsapp; + tsapp = &app; + + AppMemory tsapp_app{ dummy_exec_env.get(), sizeof(struct timespec_app) }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(clock_gettime, 0, (struct timespec_app *)-1), -1); + + EXPECT_EQ(CALL_FUNC(clock_gettime, 100, NULL), -1); + + EXPECT_EQ(CALL_FUNC(clock_gettime, 100, 0), -1); + + EXPECT_EQ(CALL_FUNC(clock_gettime, 10, + (struct timespec_app *)tsapp_app.get_native_addr()), + 0); +} + +TEST_F(LibcBuiltinTest, clock) +{ + EXPECT_GE(CALL_FUNC(clock), 0); +} + +WASMGlobalImport glb; +TEST_F(LibcBuiltinTest, wasm_native_lookup_libc_builtin_global) +{ + const char *module_name = "module name"; + const char *global_name = "global name"; + + const char *module_name1 = "global"; + const char *global_name1 = "NaN"; + const char *global_name2 = "Infinity"; + WASMGlobalImport *global = &glb; + + EXPECT_FALSE( + wasm_native_lookup_libc_builtin_global(NULL, global_name, global)); + EXPECT_FALSE( + wasm_native_lookup_libc_builtin_global(module_name, NULL, global)); + EXPECT_FALSE( + wasm_native_lookup_libc_builtin_global(module_name, global_name, NULL)); + EXPECT_FALSE(wasm_native_lookup_libc_builtin_global(module_name, + global_name, global)); + EXPECT_FALSE(wasm_native_lookup_libc_builtin_global(module_name, + global_name1, global)); + + EXPECT_TRUE(wasm_native_lookup_libc_builtin_global(module_name1, + global_name1, global)); + + EXPECT_TRUE(wasm_native_lookup_libc_builtin_global(module_name1, + global_name2, global)); +} diff --git a/tests/unit/linear-memory-aot/CMakeLists.txt b/tests/unit/linear-memory-aot/CMakeLists.txt new file mode 100644 index 0000000000..549b70ad6c --- /dev/null +++ b/tests/unit/linear-memory-aot/CMakeLists.txt @@ -0,0 +1,78 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-linear-memory-aot) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) +set (WAMR_BUILD_MEMORY_PROFILING 1) +set (WAMR_BUILD_INTERP 0) +set (WAMR_BUILD_AOT 1) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${LIB_HOST_AGENT_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} +) + +# Test case: .aot file with hardware bound check. +add_executable (linear_memory_test_aot ${unit_test_sources}) +target_link_libraries (linear_memory_test_aot gtest_main) +gtest_discover_tests(linear_memory_test_aot) +target_compile_definitions(linear_memory_test_aot PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=0) + +# Ensure that aot compiled is completed before linear_memory_test_aot is built +set(dummy_output "${CMAKE_CURRENT_BINARY_DIR}/dummy_output") + +add_custom_command(OUTPUT ${dummy_output} + COMMAND ./build_aot.sh + COMMAND ${CMAKE_COMMAND} -E touch ${dummy_output} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/build_aot.sh + COMMENT "Executing script to compile aot files" + VERBATIM +) + +add_custom_target( + RunBuildAot ALL + DEPENDS ${dummy_output} +) + +add_dependencies(linear_memory_test_aot RunBuildAot) + +add_custom_command(TARGET linear_memory_test_aot POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/build/*.aot + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copy aot files to the directory: build/linear-memory-aot." +) + +# Test case: .aot file with no hardware bound check. +add_executable (linear_memory_test_aot_no_hw_bound ${unit_test_sources}) +target_link_libraries (linear_memory_test_aot_no_hw_bound gtest_main) +gtest_discover_tests(linear_memory_test_aot_no_hw_bound) +target_compile_definitions(linear_memory_test_aot_no_hw_bound PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=1) diff --git a/tests/unit/linear-memory-aot/build_aot.sh b/tests/unit/linear-memory-aot/build_aot.sh new file mode 100755 index 0000000000..8f2b29edee --- /dev/null +++ b/tests/unit/linear-memory-aot/build_aot.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +# Define a list of .wasm files +file_names=("mem_grow_out_of_bounds_01" "mem_grow_out_of_bounds_02" + "mem_page_01" "mem_page_02" "mem_page_03" "mem_page_05" + "mem_page_07" "mem_page_08" "mem_page_09" "mem_page_10" + "mem_page_12" "mem_page_14" "mem_page_16" "mem_page_20" "out_of_bounds") + +WORKDIR="$PWD" +WAMRC_ROOT_DIR="${WORKDIR}/../../../wamr-compiler" +WAMRC="${WAMRC_ROOT_DIR}/build/wamrc" +WAST2WASM="/opt/wabt/bin/wat2wasm" + +# build wamrc if not exist +if [ ! -s "$WAMRC" ]; then + cd $WAMRC_ROOT_DIR + if [ -d "$WAMRC/build" ]; then + rm -r build + fi + cmake -B build && cmake --build build -j $(nproc) + cd $WORKDIR +fi + +# error if not exist +if [ ! -s "$WAST2WASM" ]; then + echo "please install wabt first" && exit -1 +fi + +# Iterate over the files array +rm -r build +mkdir build +for file_name in "${file_names[@]}"; do + # wast to wasm + $WAST2WASM "${file_name}.wast" -o "build/${file_name}.wasm" + # compile the aot files, x86-64, x86-32, no_hw_bounds, no_hw_bounds_x32 + $WAMRC -o "build/${file_name}.aot" "build/${file_name}.wasm" + $WAMRC --target=i386 -o "build/${file_name}_32.aot" "build/${file_name}.wasm" + $WAMRC --bounds-checks=1 -o "build/${file_name}_no_hw_bounds.aot" "build/${file_name}.wasm" + $WAMRC --bounds-checks=1 --target=i386 -o "build/${file_name}_no_hw_bounds_32.aot" "build/${file_name}.wasm" +done diff --git a/tests/unit/linear-memory-aot/linear_memory_aot_test.cc b/tests/unit/linear-memory-aot/linear_memory_aot_test.cc new file mode 100644 index 0000000000..dafdbb7917 --- /dev/null +++ b/tests/unit/linear-memory-aot/linear_memory_aot_test.cc @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "wasm_runtime_common.h" + +static std::string CWD; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +#if WASM_DISABLE_HW_BOUND_CHECK != 0 +#define TEST_SUITE_NAME linear_memory_test_suite_aot_no_hw_bound +#else +#define TEST_SUITE_NAME linear_memory_test_suite_aot +#endif + +class TEST_SUITE_NAME : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() { CWD = get_binary_path(); } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +struct ret_env { + wasm_exec_env_t exec_env; + wasm_module_t aot_module; + wasm_module_inst_t aot_module_inst; + unsigned char *aot_file_buf; + char error_buf[128]; +}; + +struct ret_env +load_aot(char *aot_file_tested, unsigned int app_heap_size) +{ + std::string aot_mem_page = aot_file_tested; + const char *aot_file = strdup((CWD + aot_mem_page).c_str()); + wasm_module_inst_t aot_module_inst = nullptr; + wasm_module_t aot_module = nullptr; + wasm_exec_env_t exec_env = nullptr; + unsigned char *aot_file_buf = nullptr; + unsigned int aot_file_size = 0; + unsigned int stack_size = 16 * 1024, heap_size = app_heap_size; + char error_buf[128] = { 0 }; + struct ret_env ret_module_env; + + memset(ret_module_env.error_buf, 0, 128); + aot_file_buf = + (unsigned char *)bh_read_file_to_buffer(aot_file, &aot_file_size); + if (!aot_file_buf) { + goto fail; + } + + aot_module = wasm_runtime_load(aot_file_buf, aot_file_size, error_buf, + sizeof(error_buf)); + if (!aot_module) { + memcpy(ret_module_env.error_buf, error_buf, 128); + goto fail; + } + + aot_module_inst = wasm_runtime_instantiate( + aot_module, stack_size, heap_size, error_buf, sizeof(error_buf)); + if (!aot_module_inst) { + memcpy(ret_module_env.error_buf, error_buf, 128); + goto fail; + } + + exec_env = wasm_runtime_create_exec_env(aot_module_inst, stack_size); + +fail: + ret_module_env.exec_env = exec_env; + ret_module_env.aot_module = aot_module; + ret_module_env.aot_module_inst = aot_module_inst; + ret_module_env.aot_file_buf = aot_file_buf; + + return ret_module_env; +} + +void +destroy_module_env(struct ret_env module_env) +{ + if (module_env.exec_env) { + wasm_runtime_destroy_exec_env(module_env.exec_env); + } + + if (module_env.aot_module_inst) { + wasm_runtime_deinstantiate(module_env.aot_module_inst); + } + + if (module_env.aot_module) { + wasm_runtime_unload(module_env.aot_module); + } + + if (module_env.aot_file_buf) { + wasm_runtime_free(module_env.aot_file_buf); + } +} + +TEST_F(TEST_SUITE_NAME, test_aot_mem_page_count) +{ + struct ret_env tmp_module_env; + const unsigned int num_normal_aot = 9; + const unsigned int num_error_aot = 2; + +#if UINTPTR_MAX == UINT64_MAX + const char *aot_file_normal[num_normal_aot] = { + "/mem_page_01.aot", "/mem_page_02.aot", "/mem_page_05.aot", + "/mem_page_07.aot", "/mem_page_08.aot", "/mem_page_09.aot", + "/mem_page_10.aot", "/mem_page_12.aot", "/mem_page_14.aot" + }; + + const char *aot_file_error[num_error_aot] = { "/mem_page_03.aot", + "/mem_page_16.aot" }; +#else + const char *aot_file_normal[num_normal_aot] = { + "/mem_page_01_32.aot", "/mem_page_02_32.aot", "/mem_page_05_32.aot", + "/mem_page_07_32.aot", "/mem_page_08_32.aot", "/mem_page_09_32.aot", + "/mem_page_10_32.aot", "/mem_page_12_32.aot", "/mem_page_14_32.aot" + }; + + const char *aot_file_error[num_error_aot] = { "/mem_page_03_32.aot", + "/mem_page_16_32.aot" }; +#endif + + // Test normal wasm file. + for (int i = 0; i < num_normal_aot; i++) { +#if UINTPTR_MAX != UINT64_MAX + // 32 bit do not load this wasm. + if ((0 == strcmp("/mem_page_14_32.aot", aot_file_normal[i]))) { + continue; + } +#endif + + tmp_module_env = load_aot((char *)aot_file_normal[i], 16 * 1024); + EXPECT_NE(nullptr, tmp_module_env.aot_module); + EXPECT_NE(nullptr, tmp_module_env.aot_file_buf); + + destroy_module_env(tmp_module_env); + } + + // Test error wasm file. + for (int i = 0; i < num_error_aot; i++) { + tmp_module_env = load_aot((char *)aot_file_error[i], 16 * 1024); + if (0 != strlen(tmp_module_env.error_buf)) { + /* 3 and 16 are for legit for loader, the init and max page count + * can be 65536, but they can't allocate any host managed heap, so + * instantiating errors */ + EXPECT_EQ(0, strncmp("AOT module instantiate failed", + (const char *)tmp_module_env.error_buf, 29)); + printf("%s\n", tmp_module_env.error_buf); + } + + destroy_module_env(tmp_module_env); + } +} + +TEST_F(TEST_SUITE_NAME, test_aot_about_app_heap) +{ + struct ret_env tmp_module_env; + + // Test case: init_page_count = 65536, app heap size = 1. +#if UINTPTR_MAX == UINT64_MAX + tmp_module_env = load_aot((char *)"/mem_page_03.aot", 1); +#else + tmp_module_env = load_aot((char *)"/mem_page_03_32.aot", 1); +#endif + EXPECT_EQ( + 0, strncmp("AOT module", (const char *)tmp_module_env.error_buf, 10)); + destroy_module_env(tmp_module_env); + + // Test case: init_page_count = 65535, app heap size = 65537. +#if UINTPTR_MAX == UINT64_MAX + tmp_module_env = load_aot((char *)"/mem_page_20.aot", 65537); +#else + tmp_module_env = load_aot((char *)"/mem_page_20_32.aot", 65537); +#endif + EXPECT_EQ( + 0, strncmp("AOT module", (const char *)tmp_module_env.error_buf, 10)); + destroy_module_env(tmp_module_env); +} + +TEST_F(TEST_SUITE_NAME, test_throw_exception_out_of_bounds) +{ + struct ret_env tmp_module_env; + WASMFunctionInstanceCommon *func = nullptr; + bool ret = false; + uint32 argv[1] = { 9999 * 64 * 1024 }; + const char *exception = nullptr; + + /* TODO: use no_hw_bounds version when disable */ +#if UINTPTR_MAX == UINT64_MAX + tmp_module_env = load_aot((char *)"/out_of_bounds.aot", 16 * 1024); +#else + tmp_module_env = load_aot((char *)"/out_of_bounds_32.aot", 16 * 1024); +#endif + func = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, "load"); + if (!func) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = wasm_runtime_call_wasm(tmp_module_env.exec_env, func, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + } + + exception = wasm_runtime_get_exception(tmp_module_env.aot_module_inst); + EXPECT_EQ(0, + strncmp("Exception: out of bounds memory access", exception, 38)); + +failed_out_of_bounds: + destroy_module_env(tmp_module_env); +} + +TEST_F(TEST_SUITE_NAME, test_mem_grow_out_of_bounds) +{ + struct ret_env tmp_module_env; + WASMFunctionInstanceCommon *func_mem_grow = nullptr; + WASMFunctionInstanceCommon *func_mem_size = nullptr; + bool ret = false; + uint32 argv[1] = { 65535 }; + const char *exception = nullptr; + + /* TODO: use no_hw_bounds version when disable */ + // Test case: module((memory 2)), memory.grow 65535, then memory.size. +#if UINTPTR_MAX == UINT64_MAX + tmp_module_env = load_aot((char *)"/mem_grow_out_of_bounds_01.aot", 0); +#else + tmp_module_env = load_aot((char *)"/mem_grow_out_of_bounds_01_32.aot", 0); +#endif + + func_mem_grow = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, + "mem_grow"); + if (!func_mem_grow) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + func_mem_size = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, + "mem_size"); + if (!func_mem_size) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_EQ(-1, argv[0]); + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_EQ(2, argv[0]); + + // Test case: wasm_runtime_instantiate(heap_size=32768), memory.grow 65534, + // memory.grow 1. + destroy_module_env(tmp_module_env); + +#if UINTPTR_MAX == UINT64_MAX + tmp_module_env = load_aot((char *)"/mem_grow_out_of_bounds_02.aot", 32768); +#else + tmp_module_env = + load_aot((char *)"/mem_grow_out_of_bounds_02_32.aot", 32768); +#endif + + func_mem_grow = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, + "mem_grow"); + if (!func_mem_grow) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + func_mem_size = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, + "mem_size"); + if (!func_mem_size) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + EXPECT_EQ(2, argv[0]); + + argv[0] = 65534; + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + +#if UINTPTR_MAX == UINT64_MAX + EXPECT_EQ(2, argv[0]); +#else + EXPECT_EQ(-1, argv[0]); +#endif + + argv[0] = 1; + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + +#if UINTPTR_MAX == UINT64_MAX + EXPECT_EQ(-1, argv[0]); +#else + EXPECT_EQ(2, argv[0]); +#endif + +failed_out_of_bounds: + destroy_module_env(tmp_module_env); +} diff --git a/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_01.wast b/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_01.wast new file mode 100644 index 0000000000..296455d86d --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_01.wast @@ -0,0 +1,16 @@ +(module + (type $0 (func (result i32))) + (type $1 (func (param i32) (result i32))) + (memory 2) + (export "mem_grow" (func $6)) + (export "mem_size" (func $7)) + + (func $6 (type $1) (param $0 i32) (result i32) + local.get $0 + memory.grow + ) + + (func $7 (type $0) (result i32) + memory.size + ) +) diff --git a/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_02.wast b/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_02.wast new file mode 100644 index 0000000000..7faceae496 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_02.wast @@ -0,0 +1,16 @@ +(module + (type $0 (func (result i32))) + (type $1 (func (param i32) (result i32))) + (memory 1) + (export "mem_grow" (func $6)) + (export "mem_size" (func $7)) + + (func $6 (type $1) (param $0 i32) (result i32) + local.get $0 + memory.grow + ) + + (func $7 (type $0) (result i32) + memory.size + ) +) diff --git a/tests/unit/linear-memory-aot/mem_page_01.wast b/tests/unit/linear-memory-aot/mem_page_01.wast new file mode 100644 index 0000000000..aa3aeed76f --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_01.wast @@ -0,0 +1 @@ +(module (memory 0)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_02.wast b/tests/unit/linear-memory-aot/mem_page_02.wast new file mode 100644 index 0000000000..eb1fba88ec --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_02.wast @@ -0,0 +1 @@ +(module (memory 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_03.wast b/tests/unit/linear-memory-aot/mem_page_03.wast new file mode 100644 index 0000000000..f3e09dcf42 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_03.wast @@ -0,0 +1 @@ +(module (memory 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_05.wast b/tests/unit/linear-memory-aot/mem_page_05.wast new file mode 100644 index 0000000000..7551af5145 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_05.wast @@ -0,0 +1 @@ +(module (memory 0 0)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_07.wast b/tests/unit/linear-memory-aot/mem_page_07.wast new file mode 100644 index 0000000000..709e6ca050 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_07.wast @@ -0,0 +1 @@ +(module (memory 1 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_08.wast b/tests/unit/linear-memory-aot/mem_page_08.wast new file mode 100644 index 0000000000..abf0818026 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_08.wast @@ -0,0 +1 @@ +(module (memory 0 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_09.wast b/tests/unit/linear-memory-aot/mem_page_09.wast new file mode 100644 index 0000000000..47b38fde53 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_09.wast @@ -0,0 +1 @@ +(module (memory 1 256)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_10.wast b/tests/unit/linear-memory-aot/mem_page_10.wast new file mode 100644 index 0000000000..523f9e6744 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_10.wast @@ -0,0 +1 @@ +(module (memory 0 65535)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_12.wast b/tests/unit/linear-memory-aot/mem_page_12.wast new file mode 100644 index 0000000000..d82dabb59f --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_12.wast @@ -0,0 +1 @@ +(module (memory 0 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_14.wast b/tests/unit/linear-memory-aot/mem_page_14.wast new file mode 100644 index 0000000000..9779bf2343 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_14.wast @@ -0,0 +1 @@ +(module (memory 65535 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_16.wast b/tests/unit/linear-memory-aot/mem_page_16.wast new file mode 100644 index 0000000000..94068a4e9a --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_16.wast @@ -0,0 +1 @@ +(module (memory 65536 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_20.wast b/tests/unit/linear-memory-aot/mem_page_20.wast new file mode 100644 index 0000000000..0d4b6ebd6e --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_20.wast @@ -0,0 +1 @@ +(module (memory 65535)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/out_of_bounds.wast b/tests/unit/linear-memory-aot/out_of_bounds.wast new file mode 100644 index 0000000000..89854b924d --- /dev/null +++ b/tests/unit/linear-memory-aot/out_of_bounds.wast @@ -0,0 +1,10 @@ +(module + (type $1 (func (param i32) (result i32))) + (memory $3 0) + (export "load" (func $4)) + + (func $4 (type $1) (param $0 i32) (result i32) + local.get $0 + i32.load + ) +) diff --git a/tests/unit/linear-memory-aot/readme b/tests/unit/linear-memory-aot/readme new file mode 100644 index 0000000000..a9ec33833f --- /dev/null +++ b/tests/unit/linear-memory-aot/readme @@ -0,0 +1,2 @@ +build 64 bit target: cmake .. +build 32 bit target: cmake .. -DWAMR_BUILD_TARGET=X86_32 \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/CMakeLists.txt b/tests/unit/linear-memory-wasm/CMakeLists.txt new file mode 100644 index 0000000000..03e1616d74 --- /dev/null +++ b/tests/unit/linear-memory-wasm/CMakeLists.txt @@ -0,0 +1,59 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-linear-memory-wasm) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) +set (WAMR_BUILD_MEMORY_PROFILING 1) +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 0) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${LIB_HOST_AGENT_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} +) + +# Test case: .wasm file with hardware bound check. +add_executable (linear_memory_test_wasm ${unit_test_sources}) +target_link_libraries (linear_memory_test_wasm gtest_main) +gtest_discover_tests(linear_memory_test_wasm) +target_compile_definitions(linear_memory_test_wasm PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=0) + +add_custom_command(TARGET linear_memory_test_wasm POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_LIST_DIR}/wasm_files/* + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copy wasm files to the directory: build/linear-memory-wasm." +) + +# Test case: .wasm file with no hardware bound check. +add_executable (linear_memory_test_wasm_no_hw_bound ${unit_test_sources}) +target_link_libraries (linear_memory_test_wasm_no_hw_bound gtest_main) +gtest_discover_tests(linear_memory_test_wasm_no_hw_bound) +target_compile_definitions(linear_memory_test_wasm_no_hw_bound PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=1) diff --git a/tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc b/tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc new file mode 100644 index 0000000000..77eb53d7ea --- /dev/null +++ b/tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "wasm_runtime_common.h" + +static std::string CWD; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +#if WASM_DISABLE_HW_BOUND_CHECK != 0 +#define TEST_SUITE_NAME linear_memory_test_suite_wasm_no_hw_bound +#else +#define TEST_SUITE_NAME linear_memory_test_suite_wasm +#endif + +class TEST_SUITE_NAME : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() { CWD = get_binary_path(); } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +struct ret_env { + wasm_exec_env_t exec_env; + wasm_module_t wasm_module; + wasm_module_inst_t wasm_module_inst; + unsigned char *wasm_file_buf; + char error_buf[128]; +}; + +struct ret_env +load_wasm(char *wasm_file_tested, unsigned int app_heap_size) +{ + std::string wasm_mem_page = wasm_file_tested; + const char *wasm_file = strdup((CWD + wasm_mem_page).c_str()); + wasm_module_inst_t wasm_module_inst = nullptr; + wasm_module_t wasm_module = nullptr; + wasm_exec_env_t exec_env = nullptr; + unsigned char *wasm_file_buf = nullptr; + unsigned int wasm_file_size = 0; + unsigned int stack_size = 16 * 1024, heap_size = app_heap_size; + char error_buf[128] = { 0 }; + struct ret_env ret_module_env; + + memset(ret_module_env.error_buf, 0, 128); + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + if (!wasm_file_buf) { + goto fail; + } + + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + if (!wasm_module) { + memcpy(ret_module_env.error_buf, error_buf, 128); + goto fail; + } + + wasm_module_inst = wasm_runtime_instantiate( + wasm_module, stack_size, heap_size, error_buf, sizeof(error_buf)); + if (!wasm_module_inst) { + memcpy(ret_module_env.error_buf, error_buf, 128); + goto fail; + } + + exec_env = wasm_runtime_create_exec_env(wasm_module_inst, stack_size); + +fail: + ret_module_env.exec_env = exec_env; + ret_module_env.wasm_module = wasm_module; + ret_module_env.wasm_module_inst = wasm_module_inst; + ret_module_env.wasm_file_buf = wasm_file_buf; + + return ret_module_env; +} + +void +destroy_module_env(struct ret_env module_env) +{ + if (module_env.exec_env) { + wasm_runtime_destroy_exec_env(module_env.exec_env); + } + + if (module_env.wasm_module_inst) { + wasm_runtime_deinstantiate(module_env.wasm_module_inst); + } + + if (module_env.wasm_module) { + wasm_runtime_unload(module_env.wasm_module); + } + + if (module_env.wasm_file_buf) { + wasm_runtime_free(module_env.wasm_file_buf); + } +} + +TEST_F(TEST_SUITE_NAME, test_wasm_mem_page_count) +{ + struct ret_env tmp_module_env; + unsigned int num_normal_wasm = 9; + unsigned int num_error_wasm = 10; + const char *wasm_file_normal[num_normal_wasm] = { + "/wasm_mem_page_01.wasm", "/wasm_mem_page_02.wasm", + "/wasm_mem_page_05.wasm", "/wasm_mem_page_07.wasm", + "/wasm_mem_page_08.wasm", "/wasm_mem_page_09.wasm", + "/wasm_mem_page_10.wasm", "/wasm_mem_page_12.wasm", + "/wasm_mem_page_14.wasm" + }; + + const char *wasm_file_error[num_error_wasm] = { + "/wasm_mem_page_03.wasm", "/wasm_mem_page_04.wasm", + "/wasm_mem_page_06.wasm", "/wasm_mem_page_11.wasm", + "/wasm_mem_page_13.wasm", "/wasm_mem_page_15.wasm", + "/wasm_mem_page_16.wasm", "/wasm_mem_page_17.wasm", + "/wasm_mem_page_18.wasm", "/wasm_mem_page_19.wasm" + }; + + // Test normal wasm file. + for (int i = 0; i < num_normal_wasm; i++) { +#if UINTPTR_MAX != UINT64_MAX + // 32 bit do not load this wasm. + if ((0 == strcmp("/wasm_mem_page_12.wasm", wasm_file_normal[i])) + || (0 == strcmp("/wasm_mem_page_14.wasm", wasm_file_normal[i]))) { + continue; + } +#endif + tmp_module_env = load_wasm((char *)wasm_file_normal[i], 16 * 1024); + EXPECT_NE(nullptr, tmp_module_env.wasm_module); + EXPECT_NE(nullptr, tmp_module_env.wasm_file_buf); + +#if WASM_DISABLE_HW_BOUND_CHECK == 0 + EXPECT_NE(nullptr, tmp_module_env.exec_env); + EXPECT_NE(nullptr, tmp_module_env.wasm_module_inst); +#endif + destroy_module_env(tmp_module_env); + } + + // Test error wasm file. + for (int i = 0; i < num_error_wasm; i++) { + tmp_module_env = load_wasm((char *)wasm_file_error[i], 16 * 1024); + + if (0 != strlen(tmp_module_env.error_buf)) { + EXPECT_EQ(0, strncmp("WASM module", + (const char *)tmp_module_env.error_buf, 11)); + } + + destroy_module_env(tmp_module_env); + } +} + +TEST_F(TEST_SUITE_NAME, test_wasm_about_app_heap) +{ + struct ret_env tmp_module_env; + + // Test case: init_page_count = 65536, app heap size = 1. + tmp_module_env = load_wasm((char *)"/wasm_mem_page_03.wasm", 1); + EXPECT_EQ(0, strncmp("WASM module instantiate failed", + (const char *)tmp_module_env.error_buf, 30)); + destroy_module_env(tmp_module_env); + + // Test case: init_page_count = 65535, app heap size = 65537. + tmp_module_env = load_wasm((char *)"/wasm_mem_page_20.wasm", 65537); + EXPECT_EQ(0, strncmp("WASM module instantiate failed", + (const char *)tmp_module_env.error_buf, 30)); + destroy_module_env(tmp_module_env); +} + +TEST_F(TEST_SUITE_NAME, test_throw_exception_out_of_bounds) +{ + struct ret_env tmp_module_env; + WASMFunctionInstanceCommon *func = nullptr; + bool ret = false; + uint32 argv[1] = { 9999 * 64 * 1024 }; + const char *exception = nullptr; + + tmp_module_env = load_wasm((char *)"/out_of_bounds.wasm", 16 * 1024); + func = + wasm_runtime_lookup_function(tmp_module_env.wasm_module_inst, "load"); + if (!func) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = wasm_runtime_call_wasm(tmp_module_env.exec_env, func, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + } + + exception = wasm_runtime_get_exception(tmp_module_env.wasm_module_inst); + EXPECT_EQ(0, + strncmp("Exception: out of bounds memory access", exception, 38)); + +failed_out_of_bounds: + destroy_module_env(tmp_module_env); +} + +TEST_F(TEST_SUITE_NAME, test_mem_grow_out_of_bounds) +{ + struct ret_env tmp_module_env; + WASMFunctionInstanceCommon *func_mem_grow = nullptr; + WASMFunctionInstanceCommon *func_mem_size = nullptr; + bool ret = false; + // after refactor, the 65536 pages to one 4G page optimization is removed + // the size can be 65536 now, so use 2 + 65535 to test OOB + uint32 argv[1] = { 65535 }; + const char *exception = nullptr; + + // Test case: module((memory 2)), memory.grow 65535, then memory.size. + tmp_module_env = load_wasm((char *)"/mem_grow_out_of_bounds_01.wasm", 0); + func_mem_grow = wasm_runtime_lookup_function( + tmp_module_env.wasm_module_inst, "mem_grow"); + if (!func_mem_grow) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + func_mem_size = wasm_runtime_lookup_function( + tmp_module_env.wasm_module_inst, "mem_size"); + if (!func_mem_size) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_EQ(-1, argv[0]); + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_EQ(2, argv[0]); + + // Test case: wasm_runtime_instantiate(heap_size=32768), memory.grow 65535, + // memory.grow 1. + destroy_module_env(tmp_module_env); + tmp_module_env = + load_wasm((char *)"/mem_grow_out_of_bounds_02.wasm", 32768); + func_mem_grow = wasm_runtime_lookup_function( + tmp_module_env.wasm_module_inst, "mem_grow"); + if (!func_mem_grow) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + func_mem_size = wasm_runtime_lookup_function( + tmp_module_env.wasm_module_inst, "mem_size"); + if (!func_mem_size) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + EXPECT_EQ(2, argv[0]); + + argv[0] = 65535; + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_NE(2, argv[0]); + + argv[0] = 1; + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_EQ(2, argv[0]); + +failed_out_of_bounds: + destroy_module_env(tmp_module_env); +} diff --git a/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_01.wast b/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_01.wast new file mode 100644 index 0000000000..296455d86d --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_01.wast @@ -0,0 +1,16 @@ +(module + (type $0 (func (result i32))) + (type $1 (func (param i32) (result i32))) + (memory 2) + (export "mem_grow" (func $6)) + (export "mem_size" (func $7)) + + (func $6 (type $1) (param $0 i32) (result i32) + local.get $0 + memory.grow + ) + + (func $7 (type $0) (result i32) + memory.size + ) +) diff --git a/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_02.wast b/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_02.wast new file mode 100644 index 0000000000..7faceae496 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_02.wast @@ -0,0 +1,16 @@ +(module + (type $0 (func (result i32))) + (type $1 (func (param i32) (result i32))) + (memory 1) + (export "mem_grow" (func $6)) + (export "mem_size" (func $7)) + + (func $6 (type $1) (param $0 i32) (result i32) + local.get $0 + memory.grow + ) + + (func $7 (type $0) (result i32) + memory.size + ) +) diff --git a/tests/unit/linear-memory-wasm/mem_page_01.wast b/tests/unit/linear-memory-wasm/mem_page_01.wast new file mode 100644 index 0000000000..aa3aeed76f --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_01.wast @@ -0,0 +1 @@ +(module (memory 0)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_02.wast b/tests/unit/linear-memory-wasm/mem_page_02.wast new file mode 100644 index 0000000000..eb1fba88ec --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_02.wast @@ -0,0 +1 @@ +(module (memory 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_03.wast b/tests/unit/linear-memory-wasm/mem_page_03.wast new file mode 100644 index 0000000000..f3e09dcf42 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_03.wast @@ -0,0 +1 @@ +(module (memory 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_04.wast b/tests/unit/linear-memory-wasm/mem_page_04.wast new file mode 100644 index 0000000000..b476caa2e7 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_04.wast @@ -0,0 +1 @@ +(module (memory 65537)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_05.wast b/tests/unit/linear-memory-wasm/mem_page_05.wast new file mode 100644 index 0000000000..7551af5145 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_05.wast @@ -0,0 +1 @@ +(module (memory 0 0)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_06.wast b/tests/unit/linear-memory-wasm/mem_page_06.wast new file mode 100644 index 0000000000..eae97baa2c --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_06.wast @@ -0,0 +1 @@ +(module (memory 1 0)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_07.wast b/tests/unit/linear-memory-wasm/mem_page_07.wast new file mode 100644 index 0000000000..709e6ca050 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_07.wast @@ -0,0 +1 @@ +(module (memory 1 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_08.wast b/tests/unit/linear-memory-wasm/mem_page_08.wast new file mode 100644 index 0000000000..abf0818026 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_08.wast @@ -0,0 +1 @@ +(module (memory 0 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_09.wast b/tests/unit/linear-memory-wasm/mem_page_09.wast new file mode 100644 index 0000000000..47b38fde53 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_09.wast @@ -0,0 +1 @@ +(module (memory 1 256)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_10.wast b/tests/unit/linear-memory-wasm/mem_page_10.wast new file mode 100644 index 0000000000..523f9e6744 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_10.wast @@ -0,0 +1 @@ +(module (memory 0 65535)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_11.wast b/tests/unit/linear-memory-wasm/mem_page_11.wast new file mode 100644 index 0000000000..1d9cf77cfd --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_11.wast @@ -0,0 +1 @@ +(module (memory 65535 0)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_12.wast b/tests/unit/linear-memory-wasm/mem_page_12.wast new file mode 100644 index 0000000000..d82dabb59f --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_12.wast @@ -0,0 +1 @@ +(module (memory 0 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_13.wast b/tests/unit/linear-memory-wasm/mem_page_13.wast new file mode 100644 index 0000000000..e3c1f1e219 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_13.wast @@ -0,0 +1 @@ +(module (memory 65536 0)) ;; Should report an error. diff --git a/tests/unit/linear-memory-wasm/mem_page_14.wast b/tests/unit/linear-memory-wasm/mem_page_14.wast new file mode 100644 index 0000000000..9779bf2343 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_14.wast @@ -0,0 +1 @@ +(module (memory 65535 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_15.wast b/tests/unit/linear-memory-wasm/mem_page_15.wast new file mode 100644 index 0000000000..d2862b9bb7 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_15.wast @@ -0,0 +1 @@ +(module (memory 65536 65535)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_16.wast b/tests/unit/linear-memory-wasm/mem_page_16.wast new file mode 100644 index 0000000000..94068a4e9a --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_16.wast @@ -0,0 +1 @@ +(module (memory 65536 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_17.wast b/tests/unit/linear-memory-wasm/mem_page_17.wast new file mode 100644 index 0000000000..d5a19eff29 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_17.wast @@ -0,0 +1 @@ +(module (memory 65537 65537)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_18.wast b/tests/unit/linear-memory-wasm/mem_page_18.wast new file mode 100644 index 0000000000..d5793de6a1 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_18.wast @@ -0,0 +1 @@ +(module (memory 65537 65535)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_19.wast b/tests/unit/linear-memory-wasm/mem_page_19.wast new file mode 100644 index 0000000000..8cf0a39f67 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_19.wast @@ -0,0 +1 @@ +(module (memory 65535 65537)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_20.wast b/tests/unit/linear-memory-wasm/mem_page_20.wast new file mode 100644 index 0000000000..0d4b6ebd6e --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_20.wast @@ -0,0 +1 @@ +(module (memory 65535)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/out_of_bounds.wast b/tests/unit/linear-memory-wasm/out_of_bounds.wast new file mode 100644 index 0000000000..89854b924d --- /dev/null +++ b/tests/unit/linear-memory-wasm/out_of_bounds.wast @@ -0,0 +1,10 @@ +(module + (type $1 (func (param i32) (result i32))) + (memory $3 0) + (export "load" (func $4)) + + (func $4 (type $1) (param $0 i32) (result i32) + local.get $0 + i32.load + ) +) diff --git a/tests/unit/linear-memory-wasm/readme b/tests/unit/linear-memory-wasm/readme new file mode 100644 index 0000000000..a9ec33833f --- /dev/null +++ b/tests/unit/linear-memory-wasm/readme @@ -0,0 +1,2 @@ +build 64 bit target: cmake .. +build 32 bit target: cmake .. -DWAMR_BUILD_TARGET=X86_32 \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/wasm_files/mem_grow_out_of_bounds_01.wasm b/tests/unit/linear-memory-wasm/wasm_files/mem_grow_out_of_bounds_01.wasm new file mode 100644 index 0000000000..544ed91e81 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/mem_grow_out_of_bounds_01.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/mem_grow_out_of_bounds_02.wasm b/tests/unit/linear-memory-wasm/wasm_files/mem_grow_out_of_bounds_02.wasm new file mode 100644 index 0000000000..ded9cc9fc4 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/mem_grow_out_of_bounds_02.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/out_of_bounds.wasm b/tests/unit/linear-memory-wasm/wasm_files/out_of_bounds.wasm new file mode 100644 index 0000000000..8ba6a862d7 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/out_of_bounds.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_app_heap_02.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_app_heap_02.wasm new file mode 100644 index 0000000000..518975da7f Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_app_heap_02.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_01.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_01.wasm new file mode 100644 index 0000000000..b55aac61b0 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_01.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_02.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_02.wasm new file mode 100644 index 0000000000..67d6849c74 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_02.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_03.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_03.wasm new file mode 100644 index 0000000000..5c82427261 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_03.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_04.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_04.wasm new file mode 100644 index 0000000000..6f2d7eb15e Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_04.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_05.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_05.wasm new file mode 100644 index 0000000000..93b6da7662 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_05.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_06.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_06.wasm new file mode 100644 index 0000000000..d09cfb187c Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_06.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_07.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_07.wasm new file mode 100644 index 0000000000..3ddd31c4f2 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_07.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_08.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_08.wasm new file mode 100644 index 0000000000..e47e0cf8d4 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_08.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_09.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_09.wasm new file mode 100644 index 0000000000..64ffe0388b Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_09.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_10.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_10.wasm new file mode 100644 index 0000000000..1bda46171f Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_10.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_11.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_11.wasm new file mode 100644 index 0000000000..8af96625b4 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_11.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_12.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_12.wasm new file mode 100644 index 0000000000..d3e6416146 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_12.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_13.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_13.wasm new file mode 100644 index 0000000000..89eab4185d Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_13.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_14.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_14.wasm new file mode 100644 index 0000000000..0650b259e1 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_14.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_15.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_15.wasm new file mode 100644 index 0000000000..e7a21b4049 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_15.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_16.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_16.wasm new file mode 100644 index 0000000000..dc19d35517 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_16.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_17.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_17.wasm new file mode 100644 index 0000000000..a7797b1165 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_17.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_18.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_18.wasm new file mode 100644 index 0000000000..f290721470 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_18.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_19.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_19.wasm new file mode 100644 index 0000000000..7c674320f1 Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_19.wasm differ diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_20.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_20.wasm new file mode 100644 index 0000000000..518975da7f Binary files /dev/null and b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_20.wasm differ diff --git a/tests/unit/linux-perf/CMakeLists.txt b/tests/unit/linux-perf/CMakeLists.txt new file mode 100644 index 0000000000..572a087050 --- /dev/null +++ b/tests/unit/linux-perf/CMakeLists.txt @@ -0,0 +1,46 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.14) + +project (test-linux-perf) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_LIBC_BUILTIN 0) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LAZY_JIT 0) +set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_MULTI_MODULE 0) +set (WAMR_BUILD_LINUX_PERF 1) + +add_definitions(-DWASM_ENABLE_WAMR_COMPILER=1) + +# Feature to test +set (WAMR_BUILD_DUMP_CALL_STACK 1) + +include (../unit_common.cmake) + +set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") +if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif () +set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include (${IWASM_DIR}/compilation/iwasm_compl.cmake) + +add_executable (linux_perf_test test_sort_func_ptrs.cc) +target_compile_options(linux_perf_test PUBLIC -fpermissive) +target_link_libraries(linux_perf_test gtest_main ) +target_link_options(linux_perf_test + PUBLIC + LINKER:--unresolved-symbols=ignore-all +) + +gtest_discover_tests(linux_perf_test) diff --git a/tests/unit/linux-perf/test_sort_func_ptrs.cc b/tests/unit/linux-perf/test_sort_func_ptrs.cc new file mode 100644 index 0000000000..68f4b850f0 --- /dev/null +++ b/tests/unit/linux-perf/test_sort_func_ptrs.cc @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_runtime.h" +#include +#include +#include + +extern "C" { +// TODO: won't work, for non static function create_perf_map have goto statement jump to label ‘quit’ +// #include "aot_perf_map.c" + +// simply copy the function +struct func_info { + uint32 idx; + void *ptr; +}; + +static int +compare_func_ptrs(const void *f1, const void *f2) +{ + return (intptr_t)((struct func_info *)f1)->ptr + - (intptr_t)((struct func_info *)f2)->ptr; +} + +static struct func_info * +sort_func_ptrs(const AOTModule *module, char *error_buf, uint32 error_buf_size) +{ + uint64 content_len; + struct func_info *sorted_func_ptrs; + unsigned i; + + content_len = (uint64)sizeof(struct func_info) * module->func_count; + sorted_func_ptrs = wasm_runtime_malloc(content_len); + if (!sorted_func_ptrs) { + snprintf(error_buf, error_buf_size, + "allocate memory failed when creating perf map"); + return NULL; + } + + for (i = 0; i < module->func_count; i++) { + sorted_func_ptrs[i].idx = i; + sorted_func_ptrs[i].ptr = module->func_ptrs[i]; + } + + qsort(sorted_func_ptrs, module->func_count, sizeof(struct func_info), + compare_func_ptrs); + + return sorted_func_ptrs; +} + +void * +wasm_runtime_malloc(unsigned int size) +{ + return malloc(size); +} + +void +wasm_runtime_free(void* ptr) +{ + return free(ptr); +} + +int +b_memcpy_s(void *s1, unsigned int s1max, const void *s2, unsigned int n) +{ + return memcpy(s1, s2, n); +} +} + +TEST(TestSortFuncPtrs, qsort) +{ + void *p = sort_func_ptrs; + ASSERT_NE(p, nullptr); + + void *funcs[5] = { + (void *)0x1024, (void *)0x10, (void *)0x24, (void *)0x102, (void *)0x4, + }; + + AOTModule module = { 0 }; + module.func_count = 5; + module.func_ptrs = &funcs[0]; + + char buf[64] = { 0 }; + + struct func_info *sorted_funcs = sort_func_ptrs(&module, buf, 64); + // sorted + ASSERT_EQ((uintptr_t)(sorted_funcs[0].ptr), 0x4); + ASSERT_EQ((uintptr_t)(sorted_funcs[1].ptr), 0x10); + ASSERT_EQ((uintptr_t)(sorted_funcs[2].ptr), 0x24); + ASSERT_EQ((uintptr_t)(sorted_funcs[3].ptr), 0x102); + ASSERT_EQ((uintptr_t)(sorted_funcs[4].ptr), 0x1024); + + ASSERT_EQ(sorted_funcs[0].idx, 4); + ASSERT_EQ(sorted_funcs[1].idx, 1); + ASSERT_EQ(sorted_funcs[2].idx, 2); + ASSERT_EQ(sorted_funcs[3].idx, 3); + ASSERT_EQ(sorted_funcs[4].idx, 0); + + // don't change input + ASSERT_EQ((uintptr_t)(funcs[0]), 0x1024); + ASSERT_EQ((uintptr_t)(funcs[1]), 0x10); + ASSERT_EQ((uintptr_t)(funcs[2]), 0x24); + ASSERT_EQ((uintptr_t)(funcs[3]), 0x102); + ASSERT_EQ((uintptr_t)(funcs[4]), 0x4); + + wasm_runtime_free(sorted_funcs); +} \ No newline at end of file diff --git a/tests/unit/memory64/CMakeLists.txt b/tests/unit/memory64/CMakeLists.txt new file mode 100644 index 0000000000..f3629a7c40 --- /dev/null +++ b/tests/unit/memory64/CMakeLists.txt @@ -0,0 +1,67 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.14) + +project(test-memory64) + +add_definitions(-DRUN_ON_LINUX) + +set(WAMR_BUILD_LIBC_WASI 1) +set(WAMR_BUILD_APP_FRAMEWORK 0) +# TODO: Currently only support classic interpreter mode +set(WAMR_BUILD_AOT 0) +set(WAMR_BUILD_INTERP 1) +set(WAMR_BUILD_FAST_INTERP 0) +set(WAMR_BUILD_JIT 0) +set(WAMR_BUILD_FAST_JIT 0) +set(WAMR_BUILD_MEMORY64 1) +set(WAMR_BUILD_SHARED_MEMORY 1) + +# if only load this CMake other than load it as subdirectory +# include(GoogleTest) +include(../unit_common.cmake) + +set(LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") + +if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message(FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif () + +set(CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include(${IWASM_DIR}/compilation/iwasm_compl.cmake) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +file(GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set(UNIT_SOURCE ${source_all}) + +aux_source_directory(. SRC_LIST) + +set(unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable(memory64_test ${unit_test_sources}) + +target_link_libraries(memory64_test ${LLVM_AVAILABLE_LIBS} gtest_main) + +add_custom_command(TARGET memory64_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps/*.wasm + ${CMAKE_CURRENT_BINARY_DIR}/ + COMMENT "Copy test wasm files to the directory of google test" + ) + +gtest_discover_tests(memory64_test) diff --git a/tests/unit/memory64/memory64_atomic_test.cc b/tests/unit/memory64/memory64_atomic_test.cc new file mode 100644 index 0000000000..2f97038905 --- /dev/null +++ b/tests/unit/memory64/memory64_atomic_test.cc @@ -0,0 +1,355 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "memory64_common.h" + +// To use a test fixture and Value Parameterized Tests, +// derive a class from testing::TestWithParam. +class memory64_atomic_test_suite : public testing::TestWithParam +{ + protected: + bool load_wasm_file(const char *wasm_file) + { + const char *file; + unsigned char *wasm_file_buf; + uint32 wasm_file_size; + + file = wasm_file; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size); + if (!wasm_file_buf) + goto fail; + + if (!(module = wasm_runtime_load(wasm_file_buf, wasm_file_size, + error_buf, sizeof(error_buf)))) { + printf("Load wasm module failed. error: %s\n", error_buf); + goto fail; + } + return true; + + fail: + if (!module) + wasm_runtime_unload(module); + + return false; + } + + bool init_exec_env() + { + if (!(module_inst = + wasm_runtime_instantiate(module, stack_size, heap_size, + error_buf, sizeof(error_buf)))) { + printf("Instantiate wasm module failed. error: %s\n", error_buf); + goto fail; + } + if (!(exec_env = + wasm_runtime_create_exec_env(module_inst, stack_size))) { + printf("Create wasm execution environment failed.\n"); + goto fail; + } + return true; + + fail: + if (exec_env) + wasm_runtime_destroy_exec_env(exec_env); + if (module_inst) + wasm_runtime_unload(module); + return false; + } + + void destory_exec_env() + { + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + } + + public: + // If your test fixture defines SetUpTestSuite() or TearDownTestSuite() + // they must be declared public rather than protected in order to use + // TEST_P. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the variables. + // Otherwise, this can be skipped. + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + ASSERT_TRUE(load_wasm_file("atomic_opcodes.wasm")); + ASSERT_TRUE(init_exec_env()); + + running_mode = GetParam(); + ASSERT_TRUE(wasm_runtime_set_running_mode(module_inst, running_mode)); + ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst)); + + for (auto &iter : func_map) { + iter.second = + wasm_runtime_lookup_function(module_inst, iter.first.c_str()); + ASSERT_TRUE(iter.second != NULL); + } + + cleanup = true; + } + + static void SetUpTestCase() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() + { + if (cleanup) { + destory_exec_env(); + wasm_runtime_destroy(); + cleanup = false; + } + } + + static void TearDownTestCase() {} + + RuntimeInitArgs init_args; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_exec_env_t exec_env = NULL; + RunningMode running_mode; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + uint32_t stack_size = 8092, heap_size = 8092; + bool cleanup = true; + std::unordered_map func_map = { + { "i32_atomic_store", nullptr }, + { "i32_atomic_store8", nullptr }, + { "i32_atomic_store16", nullptr }, + { "i64_atomic_store", nullptr }, + { "i64_atomic_store8", nullptr }, + { "i64_atomic_store16", nullptr }, + { "i64_atomic_store32", nullptr }, + { "i32_atomic_load", nullptr }, + { "i32_atomic_load8_u", nullptr }, + { "i32_atomic_load16_u", nullptr }, + { "i64_atomic_load", nullptr }, + { "i64_atomic_load8_u", nullptr }, + { "i64_atomic_load16_u", nullptr }, + { "i64_atomic_load32_u", nullptr }, + { "i32_atomic_rmw_add", nullptr }, + { "i32_atomic_rmw8_add_u", nullptr }, + { "i32_atomic_rmw16_add_u", nullptr }, + { "i64_atomic_rmw_add", nullptr }, + { "i64_atomic_rmw8_add_u", nullptr }, + { "i64_atomic_rmw16_add_u", nullptr }, + { "i64_atomic_rmw32_add_u", nullptr }, + { "i64_atomic_rmw_cmpxchg", nullptr }, + }; + uint32_t wasm_argv[6], i32; + uint64_t i64; +}; + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_st) +{ + // store at 0x2000, with value 0xbeefdead + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xcafedeadbeefdead); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + // check return value: 0xcafedeadbeefdead:i64 + i64 = 0xcafedeadbeefdead; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + // store at 0x2000, with value 0xbeefbeef + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xdeadbeef); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store32"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + // check return value: 0xcafedeaddeadbeef:i64 + i64 = 0xcafedeaddeadbeef; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + // store at 0x2000, with value 0xcafe + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xcafe); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store16"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + // check return value: 0xcafedeaddeadcafe:i64 + i64 = 0xcafedeaddeadcafe; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + // store at 0x2000, with value 0xcafe + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xaa); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store8"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + // check return value: 0xcafedeaddeadcaaa:i64 + i64 = 0xcafedeaddeadcaaa; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); +} + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i32_st) +{ + // store at 0x1000, with value 0xbeefbeef + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xaabbccdd); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_store"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2, + wasm_argv)); + // check return value: 0xaabbccdd:i32 + i32 = 0xaabbccdd; + ASSERT_EQ(i32, wasm_argv[0]); + + // store at 0x1000, with value 0xcafe + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xcafe); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_store16"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2, + wasm_argv)); + // check return value: 0xaabbcafe:i32 + i32 = 0xaabbcafe; + ASSERT_EQ(i32, wasm_argv[0]); + + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xaa); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_store8"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2, + wasm_argv)); + // check return value: 0xaabbcaaa:i32 + i32 = 0xaabbcaaa; + ASSERT_EQ(i32, wasm_argv[0]); +} + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_ld) +{ + // from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10 + PUT_I64_TO_ADDR(wasm_argv, 0x0); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + // check return value: 0x0807060504030201:i64 + i64 = 0x0807060504030201; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i64_atomic_load32_u"], 2, wasm_argv)); + // check return value: 0x0C0B0A09:i64 + i64 = 0x0C0B0A09; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i64_atomic_load16_u"], 2, wasm_argv)); + // check return value: 0x0A09:i64 + i64 = 0x0A09; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x0A); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load8_u"], + 2, wasm_argv)); + // check return value: 0x0B:i64 + i64 = 0x0B; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); +} + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i32_ld) +{ + // from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10 + PUT_I64_TO_ADDR(wasm_argv, 0x0); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2, + wasm_argv)); + // check return value: 0x04030201:i32 + i32 = 0x04030201; + ASSERT_EQ(i32, wasm_argv[0]); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i32_atomic_load16_u"], 2, wasm_argv)); + // check return value: 0x0A09:i32 + i32 = 0x0A09; + ASSERT_EQ(i32, wasm_argv[0]); + + PUT_I64_TO_ADDR(wasm_argv, 0xA); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load8_u"], + 2, wasm_argv)); + // check return value: 0x0B:i32 + i32 = 0x0B; + ASSERT_EQ(i32, wasm_argv[0]); +} + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_rmw_add) +{ + // from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10 + PUT_I64_TO_ADDR(wasm_argv, 0x8); + PUT_I64_TO_ADDR(wasm_argv + 2, 0x1010101020202020); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_rmw_add"], + 4, wasm_argv)); + i64 = 0x100F0E0D0C0B0A09; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + PUT_I64_TO_ADDR(wasm_argv + 2, 0x10103030); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i64_atomic_rmw32_add_u"], 4, wasm_argv)); + i64 = 0x2C2B2A29; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + PUT_I64_TO_ADDR(wasm_argv + 2, 0x1020); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i64_atomic_rmw16_add_u"], 4, wasm_argv)); + i64 = 0x5A59; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + PUT_I64_TO_ADDR(wasm_argv + 2, 0x30); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i64_atomic_rmw8_add_u"], 4, wasm_argv)); + i64 = 0x79; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + i64 = 0x201F1E1D3C3B6AA9; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); +} + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_rmw_cmpxchg) +{ + // from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10 + PUT_I64_TO_ADDR(wasm_argv, 0x8); + // old + PUT_I64_TO_ADDR(wasm_argv + 2, 0x100F0E0D0C0B0A09); + // new + PUT_I64_TO_ADDR(wasm_argv + 4, 0xdeadcafebeefdead); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_rmw_cmpxchg"], + 6, wasm_argv)); + i64 = 0x100F0E0D0C0B0A09; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + i64 = 0xdeadcafebeefdead; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); +} + +INSTANTIATE_TEST_CASE_P(RunningMode, memory64_atomic_test_suite, + testing::ValuesIn(running_mode_supported)); diff --git a/tests/unit/memory64/memory64_common.h b/tests/unit/memory64/memory64_common.h new file mode 100644 index 0000000000..76c43a8e7d --- /dev/null +++ b/tests/unit/memory64/memory64_common.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef UNIT_TEST_MEMORY64_COMMON_H +#define UNIT_TEST_MEMORY64_COMMON_H + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "platform_common.h" +#include "wasm_runtime_common.h" +#include "bh_read_file.h" +#include "wasm_runtime.h" +#include "bh_platform.h" +#include "wasm_export.h" +#include +// #include "aot_runtime.h" + +namespace { + +std::vector running_mode_supported = { Mode_Interp, +#if WASM_ENABLE_FAST_JIT != 0 + Mode_Fast_JIT, +#endif +#if WASM_ENABLE_JIT != 0 + Mode_LLVM_JIT, +#endif +#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + Mode_Multi_Tier_JIT +#endif +}; + +static inline uint64 +GET_U64_FROM_ADDR(uint32 *addr) +{ + union { + uint64 val; + uint32 parts[2]; + } u; + u.parts[0] = addr[0]; + u.parts[1] = addr[1]; + return u.val; +} + +static inline void +PUT_U64_TO_ADDR(uint32 *addr, uint64 value) +{ + uint32 *addr_u32 = (uint32 *)(addr); + union { + float64 val; + uint32 parts[2]; + } u; + u.val = (value); + addr_u32[0] = u.parts[0]; + addr_u32[1] = u.parts[1]; +} + +} + +#endif // UNIT_TEST_MEMORY64_COMMON_H diff --git a/tests/unit/memory64/memory64_test.cc b/tests/unit/memory64/memory64_test.cc new file mode 100644 index 0000000000..67315a594c --- /dev/null +++ b/tests/unit/memory64/memory64_test.cc @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "memory64_common.h" + +// To use a test fixture and Value Parameterized Tests, +// derive a class from testing::TestWithParam. +class memory64_test_suite : public testing::TestWithParam +{ + protected: + bool load_wasm_file(const char *wasm_file) + { + const char *file; + unsigned char *wasm_file_buf; + uint32 wasm_file_size; + + file = wasm_file; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size); + if (!wasm_file_buf) + goto fail; + + if (!(module = wasm_runtime_load(wasm_file_buf, wasm_file_size, + error_buf, sizeof(error_buf)))) { + printf("Load wasm module failed. error: %s\n", error_buf); + goto fail; + } + return true; + + fail: + if (!module) + wasm_runtime_unload(module); + + return false; + } + + bool init_exec_env() + { + if (!(module_inst = + wasm_runtime_instantiate(module, stack_size, heap_size, + error_buf, sizeof(error_buf)))) { + printf("Instantiate wasm module failed. error: %s\n", error_buf); + goto fail; + } + if (!(exec_env = + wasm_runtime_create_exec_env(module_inst, stack_size))) { + printf("Create wasm execution environment failed.\n"); + goto fail; + } + return true; + + fail: + if (exec_env) + wasm_runtime_destroy_exec_env(exec_env); + if (module_inst) + wasm_runtime_unload(module); + return false; + } + + void destory_exec_env() + { + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + } + + public: + // If your test fixture defines SetUpTestSuite() or TearDownTestSuite() + // they must be declared public rather than protected in order to use + // TEST_P. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + + cleanup = true; + } + + static void SetUpTestCase() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() + { + if (cleanup) { + wasm_runtime_destroy(); + cleanup = false; + } + } + + static void TearDownTestCase() {} + + RuntimeInitArgs init_args; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_exec_env_t exec_env = NULL; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + uint32_t stack_size = 8092, heap_size = 8092; + bool cleanup = true; +}; + +TEST_F(memory64_test_suite, wasm_runtime_is_running_mode_supported) +{ + // TODO: make sure the chosen running mode option is compiled, for memory64, + // currently only support classic interp mode + ASSERT_EQ(true, wasm_runtime_is_running_mode_supported( + static_cast(Mode_Default))); + for (auto running_mode : running_mode_supported) { + ASSERT_EQ(true, wasm_runtime_is_running_mode_supported(running_mode)); + } +} + +TEST_F(memory64_test_suite, page_exceed_u32_1) +{ + bool ret; + ret = load_wasm_file("page_exceed_u32.wasm"); + ASSERT_FALSE(ret); + ASSERT_TRUE(strcmp("WASM module load failed: integer too large", error_buf) + == 0); +} + +TEST_F(memory64_test_suite, page_exceed_u32_2) +{ + bool ret; + ret = load_wasm_file("page_exceed_u32_2.wasm"); + ASSERT_FALSE(ret); + ASSERT_TRUE(strcmp("WASM module load failed: integer too large", error_buf) + == 0); +} + +TEST_F(memory64_test_suite, page_u32_max) +{ + bool ret; + ret = load_wasm_file("page_u32_max.wasm"); + ASSERT_TRUE(ret); +} + +TEST_P(memory64_test_suite, memory_8GB) +{ + RunningMode running_mode = GetParam(); + wasm_function_inst_t touch_every_page_func, i64_store_offset_4GB, + i64_load_offset_4GB; + uint32_t wasm_argv[6], i32; + uint64_t i64; + bool ret; + + ret = load_wasm_file("8GB_memory.wasm"); + ASSERT_TRUE(ret); + ret = init_exec_env(); + ASSERT_TRUE(ret); + + ret = wasm_runtime_set_running_mode(module_inst, running_mode); + ASSERT_TRUE(ret); + ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst)); + + touch_every_page_func = + wasm_runtime_lookup_function(module_inst, "touch_every_page"); + ASSERT_TRUE(touch_every_page_func != NULL); + ret = wasm_runtime_call_wasm(exec_env, touch_every_page_func, 0, wasm_argv); + ASSERT_TRUE(ret); + // check return value: 0xfff8:i64,0x10000fff8:i64,0x1fff8:i32,0x1:i32 + i64 = 0xfff8; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + i64 = 0x10000fff8; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv + 2)); + i32 = 0x1fff8; + ASSERT_EQ(i32, wasm_argv[4]); + i32 = 0x1; + ASSERT_EQ(i32, wasm_argv[5]); + + // store at 0x100001000, with value 0xbeefdead + PUT_I64_TO_ADDR(wasm_argv, 0x1000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xbeefdead); + i64_store_offset_4GB = + wasm_runtime_lookup_function(module_inst, "i64_store_offset_4GB"); + ASSERT_TRUE(i64_store_offset_4GB != NULL); + ret = wasm_runtime_call_wasm(exec_env, i64_store_offset_4GB, 4, wasm_argv); + ASSERT_TRUE(ret); + + i64_load_offset_4GB = + wasm_runtime_lookup_function(module_inst, "i64_load_offset_4GB"); + ASSERT_TRUE(i64_load_offset_4GB != NULL); + ret = wasm_runtime_call_wasm(exec_env, i64_load_offset_4GB, 2, wasm_argv); + ASSERT_TRUE(ret); + // check return value: 0xbeefdead:i64 + i64 = 0xbeefdead; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + destory_exec_env(); +} + +TEST_P(memory64_test_suite, mem64_from_clang) +{ + RunningMode running_mode = GetParam(); + wasm_function_inst_t test_func; + uint32_t wasm_argv[1], i32; + bool ret; + + ret = load_wasm_file("mem64.wasm"); + ASSERT_TRUE(ret); + ret = init_exec_env(); + ASSERT_TRUE(ret); + + ret = wasm_runtime_set_running_mode(module_inst, running_mode); + ASSERT_TRUE(ret); + ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst)); + + test_func = + wasm_runtime_lookup_function(module_inst, "test"); + ASSERT_TRUE(test_func != NULL); + ret = wasm_runtime_call_wasm(exec_env, test_func, 0, wasm_argv); + ASSERT_TRUE(ret); + i32 = 0x109; + ASSERT_EQ(i32, wasm_argv[0]); + + destory_exec_env(); +} + +INSTANTIATE_TEST_CASE_P(RunningMode, memory64_test_suite, + testing::ValuesIn(running_mode_supported)); \ No newline at end of file diff --git a/tests/unit/memory64/wasm-apps/8GB_memory.wasm b/tests/unit/memory64/wasm-apps/8GB_memory.wasm new file mode 100644 index 0000000000..32028ff62b Binary files /dev/null and b/tests/unit/memory64/wasm-apps/8GB_memory.wasm differ diff --git a/tests/unit/memory64/wasm-apps/8GB_memory.wat b/tests/unit/memory64/wasm-apps/8GB_memory.wat new file mode 100644 index 0000000000..10e3551989 --- /dev/null +++ b/tests/unit/memory64/wasm-apps/8GB_memory.wat @@ -0,0 +1,53 @@ +(module + ;; Memory definition: 4 GB = 65536 + ;; 8 GB = 131072 + ;; 16 GB = 262144 + ;; 20 GB = 327680 + ;; 32 GB = 524288 + (memory (;0;) i64 131072 131072) + + ;; if touch too many pages more than physical memory can provide, + ;; the signal will kill the process + (func (export "touch_every_page") (result i64 i64 i32 i32) + (local $i i64) + i64.const 0x0000000000000ff8 + local.set $i + loop $loop + ;; a[i] = i + local.get $i + local.get $i + i64.store + local.get $i + i64.const 4096 + i64.add + local.set $i + local.get $i + ;; max boundary(exclusive) 8GB - 8 = 0x0000000200000000 - 8 + i64.const 0x0000000200000000 + i64.const 8 + i64.sub + i64.lt_u + br_if $loop + end + i64.const 0x000000000000fff8 + i64.load + i64.const 0x000000010000fff8 + i64.load + ;; lower 8 bytes of 0x000000010001fff8 -> 0x0001fff8 + i64.const 0x000000010001fff8 + i32.load + ;; higher 8 bytes of 0x000000010001fff8 -> 0x1 + i64.const 0x000000010001fffc + i32.load + return + ) + + ;; Function to test i64.atomic.store with i64 address + (func (export "i64_store_offset_4GB") (param $addr i64) (param $value i64) + (i64.store offset=0x100000000 (local.get $addr) (local.get $value)) + ) + + (func (export "i64_load_offset_4GB") (param $addr i64) (result i64) + (i64.load offset=0x100000000 (local.get $addr)) + ) +) \ No newline at end of file diff --git a/tests/unit/memory64/wasm-apps/atomic_opcodes.wasm b/tests/unit/memory64/wasm-apps/atomic_opcodes.wasm new file mode 100644 index 0000000000..fbdc587096 Binary files /dev/null and b/tests/unit/memory64/wasm-apps/atomic_opcodes.wasm differ diff --git a/tests/unit/memory64/wasm-apps/atomic_opcodes.wat b/tests/unit/memory64/wasm-apps/atomic_opcodes.wat new file mode 100644 index 0000000000..dd86fede8b --- /dev/null +++ b/tests/unit/memory64/wasm-apps/atomic_opcodes.wat @@ -0,0 +1,120 @@ +(module + ;; Memory definition: 4 GB = 65536 + ;; 8 GB = 131072 + ;; 16 GB = 262144 + ;; 20 GB = 327680 + (memory (;0;) i64 200 200 shared) + + ;; Initialize memory with some values + (data (i64.const 0) "\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10") + + ;; Function to test i32.atomic.store with i64 address + (func (export "i32_atomic_store") (param $addr i64) (param $value i32) + (i32.atomic.store (local.get $addr) (local.get $value)) + ) + + ;; Function to test i32.atomic.store8 with i64 address + (func (export "i32_atomic_store8") (param $addr i64) (param $value i32) + (i32.atomic.store8 (local.get $addr) (local.get $value)) + ) + + ;; Function to test i32.atomic.store16 with i64 address + (func (export "i32_atomic_store16") (param $addr i64) (param $value i32) + (i32.atomic.store16 (local.get $addr) (local.get $value)) + ) + + ;; Function to test i64.atomic.store with i64 address + (func (export "i64_atomic_store") (param $addr i64) (param $value i64) + (i64.atomic.store (local.get $addr) (local.get $value)) + ) + + ;; Function to test i64.atomic.store8 with i64 address + (func (export "i64_atomic_store8") (param $addr i64) (param $value i64) + (i64.atomic.store8 (local.get $addr) (local.get $value)) + ) + + ;; Function to test i64.atomic.store16 with i64 address + (func (export "i64_atomic_store16") (param $addr i64) (param $value i64) + (i64.atomic.store16 (local.get $addr) (local.get $value)) + ) + + ;; Function to test i64.atomic.store32 with i64 address + (func (export "i64_atomic_store32") (param $addr i64) (param $value i64) + (i64.atomic.store32 (local.get $addr) (local.get $value)) + ) + + ;; Function to test i32.atomic.load with i64 address + (func (export "i32_atomic_load") (param $addr i64) (result i32) + (i32.atomic.load (local.get $addr)) + ) + + ;; Function to test i32.atomic.load8_u with i64 address + (func (export "i32_atomic_load8_u") (param $addr i64) (result i32) + (i32.atomic.load8_u (local.get $addr)) + ) + + ;; Function to test i32.atomic.load16_u with i64 address + (func (export "i32_atomic_load16_u") (param $addr i64) (result i32) + (i32.atomic.load16_u (local.get $addr)) + ) + + ;; Function to test i64.atomic.load with i64 address + (func (export "i64_atomic_load") (param $addr i64) (result i64) + (i64.atomic.load (local.get $addr)) + ) + + ;; Function to test i64.atomic.load8_u with i64 address + (func (export "i64_atomic_load8_u") (param $addr i64) (result i64) + (i64.atomic.load8_u (local.get $addr)) + ) + + ;; Function to test i64.atomic.load16_u with i64 address + (func (export "i64_atomic_load16_u") (param $addr i64) (result i64) + (i64.atomic.load16_u (local.get $addr)) + ) + + ;; Function to test i64.atomic.load32_u with i64 address + (func (export "i64_atomic_load32_u") (param $addr i64) (result i64) + (i64.atomic.load32_u (local.get $addr)) + ) + + ;; Function to test i32.atomic.rmw.add with i64 address + (func (export "i32_atomic_rmw_add") (param $addr i64) (param $value i32) (result i32) + (i32.atomic.rmw.add (local.get $addr) (local.get $value)) + ) + + ;; Function to test i32.atomic.rmw8.add_u with i64 address + (func (export "i32_atomic_rmw8_add_u") (param $addr i64) (param $value i32) (result i32) + (i32.atomic.rmw8.add_u (local.get $addr) (local.get $value)) + ) + + ;; Function to test i32.atomic.rmw16.add_u with i64 address + (func (export "i32_atomic_rmw16_add_u") (param $addr i64) (param $value i32) (result i32) + (i32.atomic.rmw16.add_u (local.get $addr) (local.get $value)) + ) + + ;; Function to test i64.atomic.rmw.add with i64 address + (func (export "i64_atomic_rmw_add") (param $addr i64) (param $value i64) (result i64) + (i64.atomic.rmw.add (local.get $addr) (local.get $value)) + ) + + ;; Function to test i64.atomic.rmw8.add_u with i64 address + (func (export "i64_atomic_rmw8_add_u") (param $addr i64) (param $value i64) (result i64) + (i64.atomic.rmw8.add_u (local.get $addr) (local.get $value)) + ) + + ;; Function to test i64.atomic.rmw16.add_u with i64 address + (func (export "i64_atomic_rmw16_add_u") (param $addr i64) (param $value i64) (result i64) + (i64.atomic.rmw16.add_u (local.get $addr) (local.get $value)) + ) + + ;; Function to test i64.atomic.rmw32.add_u with i64 address + (func (export "i64_atomic_rmw32_add_u") (param $addr i64) (param $value i64) (result i64) + (i64.atomic.rmw32.add_u (local.get $addr) (local.get $value)) + ) + + (func (export "i64_atomic_rmw_cmpxchg") (param $addr i64) (param $old i64) (param $new i64) (result i64) + (i64.atomic.rmw.cmpxchg (local.get $addr) (local.get $old) (local.get $new)) + ) + +) \ No newline at end of file diff --git a/tests/unit/memory64/wasm-apps/mem64.c b/tests/unit/memory64/wasm-apps/mem64.c new file mode 100644 index 0000000000..447a75b693 --- /dev/null +++ b/tests/unit/memory64/wasm-apps/mem64.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +int +add_a_and_b_to_c(int *array, int *b, int *c) +{ + int i; + // Perform computation: multiply each element by 2 + for (i = 0; i < 5; i++) { + array[i] = array[i] * 2; + } + // Compute the product of corresponding elements of a and b + for (i = 0; i < 5; i++) { + c[i] = array[i] * b[i]; + } + return i; +} + +int +test() +{ + // Initialize an array with some values + int array[5] = { 1, 2, 3, 4, 5 }; + int b[5] = { 6, 7, 8, 9, 10 }; + int c[5], i, j, res = 0; + + j = add_a_and_b_to_c(array, b, c); + + for (i = 0; i < 5; i++) { + res += c[i]; + } + + return res + j; +} + +int +main(int argc, char *argv[]) +{ + // Initialize an array with some values + int array[5] = { 1, 2, 3, 4, 5 }; + int b[5] = { 6, 7, 8, 9, 10 }; + int c[5], i; + + // Perform computation: multiply each element by 2 + for (i = 0; i < 5; i++) { + array[i] = array[i] * 2; + } + // Compute the product of corresponding elements of a and b + for (i = 0; i < 5; i++) { + c[i] = array[i] * b[i]; + } + + return c[4]; +} diff --git a/tests/unit/memory64/wasm-apps/mem64.wasm b/tests/unit/memory64/wasm-apps/mem64.wasm new file mode 100755 index 0000000000..b4b0a58629 Binary files /dev/null and b/tests/unit/memory64/wasm-apps/mem64.wasm differ diff --git a/tests/unit/memory64/wasm-apps/page_exceed_u32.wasm b/tests/unit/memory64/wasm-apps/page_exceed_u32.wasm new file mode 100644 index 0000000000..3aa1786d06 Binary files /dev/null and b/tests/unit/memory64/wasm-apps/page_exceed_u32.wasm differ diff --git a/tests/unit/memory64/wasm-apps/page_exceed_u32.wat b/tests/unit/memory64/wasm-apps/page_exceed_u32.wat new file mode 100644 index 0000000000..8da477ff57 --- /dev/null +++ b/tests/unit/memory64/wasm-apps/page_exceed_u32.wat @@ -0,0 +1,4 @@ +(module + ;; u32 max pages is 4,294,967,295 + (memory i64 1 4294967296) +) \ No newline at end of file diff --git a/tests/unit/memory64/wasm-apps/page_exceed_u32_2.wasm b/tests/unit/memory64/wasm-apps/page_exceed_u32_2.wasm new file mode 100644 index 0000000000..cf2f876e48 Binary files /dev/null and b/tests/unit/memory64/wasm-apps/page_exceed_u32_2.wasm differ diff --git a/tests/unit/memory64/wasm-apps/page_exceed_u32_2.wat b/tests/unit/memory64/wasm-apps/page_exceed_u32_2.wat new file mode 100644 index 0000000000..4db1b838d6 --- /dev/null +++ b/tests/unit/memory64/wasm-apps/page_exceed_u32_2.wat @@ -0,0 +1,4 @@ +(module + ;; u32 max pages is 4,294,967,295 + (memory i64 4294967296) +) \ No newline at end of file diff --git a/tests/unit/memory64/wasm-apps/page_u32_max.wasm b/tests/unit/memory64/wasm-apps/page_u32_max.wasm new file mode 100644 index 0000000000..caa8de4543 Binary files /dev/null and b/tests/unit/memory64/wasm-apps/page_u32_max.wasm differ diff --git a/tests/unit/memory64/wasm-apps/page_u32_max.wat b/tests/unit/memory64/wasm-apps/page_u32_max.wat new file mode 100644 index 0000000000..ae2ef11c41 --- /dev/null +++ b/tests/unit/memory64/wasm-apps/page_u32_max.wat @@ -0,0 +1,4 @@ +(module + ;; u32 max pages is 4,294,967,295 + (memory i64 1 4294967295) +) \ No newline at end of file diff --git a/tests/unit/running-modes/CMakeLists.txt b/tests/unit/running-modes/CMakeLists.txt new file mode 100644 index 0000000000..5fc6a80bce --- /dev/null +++ b/tests/unit/running-modes/CMakeLists.txt @@ -0,0 +1,56 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.14) + +project(test-running-modes) + +# Compile wasm modules +add_subdirectory(wasm-apps) + +add_definitions(-DRUN_ON_LINUX) + +set(WAMR_BUILD_LIBC_WASI 1) +set(WAMR_BUILD_APP_FRAMEWORK 0) +set(WAMR_BUILD_JIT 1) +set(WAMR_BUILD_FAST_JIT 1) + +# if only load this CMake other than load it as subdirectory +include(../unit_common.cmake) + +set(LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") + +if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message(FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif () + +set(CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include(${IWASM_DIR}/compilation/iwasm_compl.cmake) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +file(GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set(UNIT_SOURCE ${source_all}) + +aux_source_directory(. SRC_LIST) + +set(unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable(wasm_running_modes_test ${unit_test_sources}) + +target_link_libraries(wasm_running_modes_test ${LLVM_AVAILABLE_LIBS} gtest_main) + +gtest_discover_tests(wasm_running_modes_test) diff --git a/tests/unit/running-modes/wasm-apps/CMakeLists.txt b/tests/unit/running-modes/wasm-apps/CMakeLists.txt new file mode 100644 index 0000000000..b2f1e9c0c5 --- /dev/null +++ b/tests/unit/running-modes/wasm-apps/CMakeLists.txt @@ -0,0 +1,49 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.14) +project(wasm-apps) + +set(WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../..) + +set(CMAKE_SYSTEM_PROCESSOR wasm32) +set(CMAKE_SYSROOT ${WAMR_ROOT_DIR}/wamr-sdk/app/libc-builtin-sysroot) + +if (NOT DEFINED WASI_SDK_DIR) + set(WASI_SDK_DIR "/opt/wasi-sdk") +endif () + +set(CMAKE_C_FLAGS "-nostdlib -pthread -Qunused-arguments") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -z stack-size=8192 -nostdlib") +set(CMAKE_C_COMPILER_TARGET "wasm32") +set(CMAKE_C_COMPILER "${WASI_SDK_DIR}/bin/clang") + +set(DEFINED_SYMBOLS + "${WAMR_ROOT_DIR}/wamr-sdk/app/libc-builtin-sysroot/share/defined-symbols.txt") + +set(CMAKE_EXE_LINKER_FLAGS + "-Wl,--no-entry \ + -Wl,--initial-memory=65536 \ + -Wl,--export-all \ + -Wl,--allow-undefined" + ) + +add_executable(mytest.wasm mytest.c) +target_link_libraries(mytest.wasm) + +add_executable(hello.wasm hello.c) +target_link_libraries(hello.wasm) + +add_custom_command(TARGET hello.wasm POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_BINARY_DIR}/hello.wasm + ${CMAKE_CURRENT_BINARY_DIR}/../ + COMMENT "Copy hello.wasm to the same directory of google test" + ) + +add_custom_command(TARGET mytest.wasm POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_BINARY_DIR}/mytest.wasm + ${CMAKE_CURRENT_BINARY_DIR}/../ + COMMENT "Copy mytest.wasm to the same directory of google test" + ) diff --git a/tests/unit/running-modes/wasm-apps/hello.c b/tests/unit/running-modes/wasm-apps/hello.c new file mode 100644 index 0000000000..3aa7c2a698 --- /dev/null +++ b/tests/unit/running-modes/wasm-apps/hello.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +double +foo(double d) +{ + return d / 3.0; +} + +double +maybe_min(double d, double e) +{ + return d < e ? d : e; +} + +double +factor(double a, double b, double c) +{ + return (a * c) + (b * c); +} + +int +echo(int a) +{ + double b = foo(14.5); + double c = maybe_min(12.2, 15.4); + double d = factor(a, b, c); + return 2 * a; +} \ No newline at end of file diff --git a/tests/unit/running-modes/wasm-apps/mytest.c b/tests/unit/running-modes/wasm-apps/mytest.c new file mode 100644 index 0000000000..c5d1916dee --- /dev/null +++ b/tests/unit/running-modes/wasm-apps/mytest.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include + +int +recursive(int a) +{ + if (a > 0) { + return recursive(a - 1) + 1; + } + else + return 0; +} + +int +testFunction(int *input, int length) +{ + int sum = 0; + for (int i = 0; i < length; ++i) { + sum += input[i]; + } + return sum; +} + +int +main(int argc, char **argv) +{ + + int arr[5] = { 1, 2, 3, 4, 5 }; + testFunction(arr, recursive(5)); + + char *buf; + + printf("Hello world!\n"); + + buf = malloc(1024); + if (!buf) { + printf("malloc buf failed\n"); + return -1; + } + + printf("buf ptr: %p\n", buf); + + snprintf(buf, 1024, "%s", "1234\n"); + printf("buf: %s", buf); + + free(buf); + return 0; +} diff --git a/tests/unit/running-modes/wasm_running_modes_test.cc b/tests/unit/running-modes/wasm_running_modes_test.cc new file mode 100644 index 0000000000..9d6a9379cd --- /dev/null +++ b/tests/unit/running-modes/wasm_running_modes_test.cc @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "platform_common.h" +#include "wasm_runtime_common.h" +#include "bh_read_file.h" +#include "wasm_runtime.h" +#include "bh_platform.h" +#include "wasm_export.h" +#include "aot_runtime.h" + +namespace { + +std::string CWD; +std::string TEST_WASM1 = "/hello.wasm"; +std::string TEST_WASM2 = "/mytest.wasm"; +char *WASM_FILE_1; +char *WASM_FILE_2; +std::vector running_mode_supportted = { Mode_Interp, +#if WASM_ENABLE_FAST_JIT != 0 + Mode_Fast_JIT, +#endif +#if WASM_ENABLE_JIT != 0 + Mode_LLVM_JIT, +#endif +#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + Mode_Multi_Tier_JIT +#endif +}; + +// To use a test fixture and Value Parameterized Tests, +// derive a class from testing::TestWithParam. +class wasm_running_modes_test_suite : public testing::TestWithParam +{ + private: + std::string get_binary_path() + { + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); + } + + bool load_wasm_file(const char *wasm_file) + { + const char *file; + unsigned char *wasm_file_buf; + uint32 wasm_file_size; + + file = wasm_file; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size); + if (!wasm_file_buf) + goto fail; + + if (!(module = wasm_runtime_load(wasm_file_buf, wasm_file_size, + error_buf, sizeof(error_buf)))) { + printf("Load wasm module failed. error: %s\n", error_buf); + goto fail; + } + return true; + + fail: + if (!module) + wasm_runtime_unload(module); + + return false; + } + + bool init_exec_env() + { + if (!(module_inst = + wasm_runtime_instantiate(module, stack_size, heap_size, + error_buf, sizeof(error_buf)))) { + printf("Instantiate wasm module failed. error: %s\n", error_buf); + goto fail; + } + if (!(exec_env = + wasm_runtime_create_exec_env(module_inst, stack_size))) { + printf("Create wasm execution environment failed.\n"); + goto fail; + } + return true; + + fail: + if (exec_env) + wasm_runtime_destroy_exec_env(exec_env); + if (module_inst) + wasm_runtime_unload(module); + return false; + } + + void destory_exec_env() + { + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + } + + protected: + void run_wasm_basic( + char *filename, bool in_default_running_mode, + RunningMode running_mode = static_cast(Mode_Default)) + { + bool ret; + uint32_t wasm_argv[2]; + ret = load_wasm_file(filename); + ASSERT_TRUE(ret); + ret = init_exec_env(); + ASSERT_TRUE(ret); + + if (!in_default_running_mode) { + ret = wasm_runtime_set_running_mode(module_inst, running_mode); + ASSERT_TRUE(ret); + ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst)); + } + + wasm_function_inst_t echo2xback_func = + wasm_runtime_lookup_function(module_inst, "echo"); + ASSERT_TRUE(echo2xback_func != NULL); + + wasm_argv[0] = 5; + ret = wasm_runtime_call_wasm(exec_env, echo2xback_func, 1, wasm_argv); + ASSERT_TRUE(ret); + ASSERT_EQ(10, wasm_argv[0]); + + destory_exec_env(); + } + + void run_wasm_complex(char *filename1, char *filename2, + RunningMode default_running_mode, + RunningMode running_mode) + { + bool ret; + uint32_t wasm_argv[2]; + + /* run wasm file 1 in default running mode */ + wasm_runtime_set_default_running_mode(default_running_mode); + ret = load_wasm_file(filename1); + ASSERT_TRUE(ret); + ret = init_exec_env(); + ASSERT_TRUE(ret); + + uint8_t *buffer, *buffer2; + wasm_function_inst_t echo2xback_func, main; + + ASSERT_EQ(default_running_mode, + wasm_runtime_get_running_mode(module_inst)); + echo2xback_func = wasm_runtime_lookup_function(module_inst, "echo"); + ASSERT_TRUE(echo2xback_func != NULL); + wasm_argv[0] = 5; + ret = wasm_runtime_call_wasm(exec_env, echo2xback_func, 1, wasm_argv); + ASSERT_TRUE(ret); + ASSERT_EQ(10, wasm_argv[0]); + + destory_exec_env(); + + /* run wasm file 2 in running_mode */ + ret = load_wasm_file(filename2); + ASSERT_TRUE(ret); + ret = init_exec_env(); + ASSERT_TRUE(ret); + + ret = wasm_runtime_set_running_mode(module_inst, running_mode); + ASSERT_TRUE(ret); + ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst)); + main = wasm_runtime_lookup_function(module_inst, "__main_argc_argv"); + ASSERT_TRUE(main != NULL); + ret = wasm_runtime_call_wasm(exec_env, main, 2, wasm_argv); + ASSERT_TRUE(ret); + + destory_exec_env(); + } + + public: + // If your test fixture defines SetUpTestSuite() or TearDownTestSuite() + // they must be declared public rather than protected in order to use + // TEST_P. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() + { + CWD = get_binary_path(); + WASM_FILE_1 = strdup((CWD + TEST_WASM1).c_str()); + WASM_FILE_2 = strdup((CWD + TEST_WASM2).c_str()); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + + cleanup = true; + } + + static void SetUpTestCase() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() + { + if (cleanup) { + wasm_runtime_destroy(); + cleanup = false; + } + free(WASM_FILE_1); + free(WASM_FILE_2); + } + + static void TearDownTestCase() {} + + std::string CWD; + RuntimeInitArgs init_args; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_exec_env_t exec_env = NULL; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + uint32_t stack_size = 8092, heap_size = 8092; + bool cleanup = true; +}; + +TEST_F(wasm_running_modes_test_suite, wasm_runtime_is_running_mode_supported) +{ + // normal situation + ASSERT_EQ(true, wasm_runtime_is_running_mode_supported( + static_cast(Mode_Default))); + for (auto running_mode : running_mode_supportted) { + ASSERT_EQ(true, wasm_runtime_is_running_mode_supported(running_mode)); + } + + // abnormal situation + ASSERT_EQ(false, wasm_runtime_is_running_mode_supported( + static_cast(-1))); + ASSERT_EQ(false, wasm_runtime_is_running_mode_supported( + static_cast(5))); + ASSERT_EQ(false, wasm_runtime_is_running_mode_supported( + static_cast(0xFF))); +} + +TEST_F(wasm_running_modes_test_suite, wasm_runtime_set_default_running_mode) +{ + // normal situation: only set up + ASSERT_EQ(true, wasm_runtime_set_default_running_mode( + static_cast(Mode_Default))); + for (auto running_mode : running_mode_supportted) { + ASSERT_EQ(true, wasm_runtime_set_default_running_mode(running_mode)); + } + + // abnormal situation + ASSERT_EQ(false, wasm_runtime_set_default_running_mode( + static_cast(-1))); + ASSERT_EQ(false, wasm_runtime_set_default_running_mode( + static_cast(5))); + ASSERT_EQ(false, wasm_runtime_set_default_running_mode( + static_cast(0xFF))); +} + +TEST_P(wasm_running_modes_test_suite, + wasm_runtime_set_default_running_mode_basic) +{ + RunningMode running_mode = GetParam(); + ASSERT_EQ(true, wasm_runtime_set_default_running_mode(running_mode)); + run_wasm_basic(WASM_FILE_1, true); +} + +TEST_P(wasm_running_modes_test_suite, + wasm_runtime_set_and_get_running_mode_basic) +{ + RunningMode running_mode = GetParam(); + run_wasm_basic(WASM_FILE_1, false, running_mode); +} + +TEST_P(wasm_running_modes_test_suite, + wasm_runtime_set_and_get_running_mode_complex) +{ + RunningMode default_running_mode = GetParam(); + for (auto running_mode : running_mode_supportted) { + run_wasm_complex(WASM_FILE_1, WASM_FILE_2, default_running_mode, + running_mode); + } +} + +INSTANTIATE_TEST_CASE_P(RunningMode, wasm_running_modes_test_suite, + testing::ValuesIn(running_mode_supportted)); + +} \ No newline at end of file diff --git a/tests/unit/runtime-common/CMakeLists.txt b/tests/unit/runtime-common/CMakeLists.txt new file mode 100644 index 0000000000..f737569151 --- /dev/null +++ b/tests/unit/runtime-common/CMakeLists.txt @@ -0,0 +1,73 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project(test-runtime-common) + +add_definitions(-DRUN_ON_LINUX) + +set(WAMR_BUILD_LIBC_WASI 0) +set(WAMR_BUILD_APP_FRAMEWORK 0) + +include(../unit_common.cmake) + +set(LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") + +if(NOT EXISTS "${LLVM_SRC_ROOT}/build") + message(FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif() + +set(CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +file(GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set(UNIT_SOURCE ${source_all}) + +aux_source_directory(. SRC_LIST) + +set(unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} +) + +add_executable(runtime_common_test ${unit_test_sources}) + +target_link_libraries(runtime_common_test ${LLVM_AVAILABLE_LIBS} gtest_main) + +# Ensure that aot compiled is completed before linear_memory_test_aot is built +set(dummy_output "${CMAKE_CURRENT_BINARY_DIR}/dummy_output") + +add_custom_command(OUTPUT ${dummy_output} + COMMAND ./build_aot.sh + COMMAND ${CMAKE_COMMAND} -E touch ${dummy_output} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/build_aot.sh + COMMENT "Executing script to compile aot files" + VERBATIM +) + +add_custom_target( + BuildAot ALL + DEPENDS ${dummy_output} +) + +add_dependencies(runtime_common_test BuildAot) + +add_custom_command(TARGET runtime_common_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/main.wasm ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/main.aot + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copy main.wasm and main.aot to the directory: build/runtime-common." +) + +gtest_discover_tests(runtime_common_test) diff --git a/tests/unit/runtime-common/build_aot.sh b/tests/unit/runtime-common/build_aot.sh new file mode 100755 index 0000000000..441d441b55 --- /dev/null +++ b/tests/unit/runtime-common/build_aot.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +# Define a list of .wasm files +file_names=("main") + +WORKDIR="$PWD" +WAMRC_ROOT_DIR="${WORKDIR}/../../../wamr-compiler" +WAMRC="${WAMRC_ROOT_DIR}/build/wamrc" +WAST2WASM="/opt/wabt/bin/wat2wasm" + +# build wamrc if not exist +if [ ! -s "$WAMRC" ]; then + cd $WAMRC_ROOT_DIR + if [ -d "$WAMRC/build" ]; then + rm -r build + fi + cmake -B build && cmake --build build -j $(nproc) + cd $WORKDIR +fi + +# Iterate over the files array +for file_name in "${file_names[@]}"; do + # compile wasm to aot + $WAMRC -o "wasm-apps/${file_name}.aot" "wasm-apps/${file_name}.wasm" +done + diff --git a/tests/unit/runtime-common/wasm-apps/main.aot b/tests/unit/runtime-common/wasm-apps/main.aot new file mode 100644 index 0000000000..79319145a9 Binary files /dev/null and b/tests/unit/runtime-common/wasm-apps/main.aot differ diff --git a/tests/unit/runtime-common/wasm-apps/main.wasm b/tests/unit/runtime-common/wasm-apps/main.wasm new file mode 100644 index 0000000000..28af80e405 Binary files /dev/null and b/tests/unit/runtime-common/wasm-apps/main.wasm differ diff --git a/tests/unit/runtime-common/wasm_exec_env_test.cc b/tests/unit/runtime-common/wasm_exec_env_test.cc new file mode 100644 index 0000000000..06c162b623 --- /dev/null +++ b/tests/unit/runtime-common/wasm_exec_env_test.cc @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "wasm_exec_env.h" + +class wasm_exec_env_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} +}; + +TEST_F(wasm_exec_env_test_suite, wasm_exec_env_create) +{ + EXPECT_EQ(nullptr, wasm_exec_env_create(nullptr, 0)); +} + +TEST_F(wasm_exec_env_test_suite, wasm_exec_env_create_internal) +{ + EXPECT_EQ(nullptr, wasm_exec_env_create_internal(nullptr, UINT32_MAX)); +} + +TEST_F(wasm_exec_env_test_suite, wasm_exec_env_pop_jmpbuf) +{ + WASMExecEnv exec_env; + + exec_env.jmpbuf_stack_top = nullptr; + EXPECT_EQ(nullptr, wasm_exec_env_pop_jmpbuf(&exec_env)); +} diff --git a/tests/unit/runtime-common/wasm_runtime_common_test.cc b/tests/unit/runtime-common/wasm_runtime_common_test.cc new file mode 100644 index 0000000000..978b540227 --- /dev/null +++ b/tests/unit/runtime-common/wasm_runtime_common_test.cc @@ -0,0 +1,682 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "platform_common.h" +#include "wasm_runtime_common.h" +#include "bh_read_file.h" +#include "wasm_runtime.h" +#include "bh_platform.h" +#include "wasm_export.h" +#include "aot_runtime.h" + +using namespace std; + +extern "C" { +uint32 +wasm_runtime_module_realloc(WASMModuleInstanceCommon *module_inst, uint32 ptr, + uint32 size, void **p_native_addr); +bool +wasm_runtime_create_exec_env_and_call_wasm( + WASMModuleInstanceCommon *module_inst, WASMFunctionInstanceCommon *function, + uint32 argc, uint32 argv[]); +} + +static bh_list loading_module_list_head; +static bh_list *const loading_module_list = &loading_module_list_head; +static korp_mutex loading_module_list_lock; + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static std::string MAIN_AOT = "/main.aot"; +static char *WASM_FILE_1; +static char *AOT_FILE_1; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class wasm_runtime_common_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE_1 = strdup((CWD + MAIN_WASM).c_str()); + AOT_FILE_1 = strdup((CWD + MAIN_AOT).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() + { + free(WASM_FILE_1); + free(AOT_FILE_1); + } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_destroy) +{ + wasm_runtime_init(); + wasm_runtime_destroy(); +} + +static bool +reader_test(package_type_t module_type, const char *module_name, + uint8 **p_buffer, uint32 *p_size) +{ + return true; +} + +static void +destroyer_test(uint8 *buffer, uint32 size) +{} + +TEST_F(wasm_runtime_common_test_suite, + set_module_reader_get_module_reader_get_module_destroyer) +{ + wasm_runtime_set_module_reader(reader_test, destroyer_test); + EXPECT_EQ((module_reader)reader_test, wasm_runtime_get_module_reader()); + EXPECT_EQ((module_destroyer)destroyer_test, + wasm_runtime_get_module_destroyer()); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_register_module) +{ + const char *wasm_file = WASM_FILE_1; + wasm_module_t wasm_module = nullptr; + unsigned char *wasm_file_buf = nullptr; + unsigned int wasm_file_size = 0; + char error_buf[128] = { 0 }; + char module_name[] = "module_test"; + char module_name_1[] = "module_test_1"; + + // Normal situation. + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + EXPECT_NE(false, + wasm_runtime_register_module("module_test", wasm_module, + error_buf, sizeof(error_buf))); + + // Abnormal situation. + EXPECT_EQ(false, + wasm_runtime_register_module(nullptr, nullptr, nullptr, 0)); + EXPECT_EQ(false, wasm_runtime_register_module( + "module_test", nullptr, error_buf, sizeof(error_buf))); + EXPECT_EQ(false, wasm_runtime_register_module("module_test", wasm_module, + nullptr, sizeof(error_buf))); + EXPECT_EQ(false, wasm_runtime_register_module("module_test", wasm_module, + error_buf, 0)); + EXPECT_EQ(false, wasm_runtime_register_module( + nullptr, wasm_module, error_buf, sizeof(error_buf))); + EXPECT_EQ(false, wasm_runtime_register_module(nullptr, nullptr, error_buf, + sizeof(error_buf))); + + EXPECT_EQ(true, wasm_runtime_register_module(module_name, wasm_module, + error_buf, sizeof(error_buf))); + EXPECT_EQ(false, wasm_runtime_register_module_internal(nullptr, wasm_module, + NULL, 0, error_buf, + sizeof(error_buf))); + EXPECT_EQ(false, wasm_runtime_register_module_internal( + module_name_1, wasm_module, NULL, 0, error_buf, + sizeof(error_buf))); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_unregister_module) +{ + wasm_runtime_unregister_module(nullptr); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_find_module_registered) +{ + EXPECT_EQ(nullptr, wasm_runtime_find_module_registered("module_test")); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_is_module_registered) +{ + EXPECT_EQ(nullptr, wasm_runtime_find_module_registered("")); +} + +/* TODO: add thread safety test. */ +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_add_loading_module) +{ + EXPECT_EQ(true, wasm_runtime_add_loading_module(nullptr, nullptr, 0)); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_destroy_loading_module_list) +{ + os_mutex_init(&loading_module_list_lock); + wasm_runtime_destroy_loading_module_list(); + os_mutex_destroy(&loading_module_list_lock); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_is_built_in_module) +{ + EXPECT_EQ(true, wasm_runtime_is_built_in_module("env")); + EXPECT_EQ(true, wasm_runtime_is_built_in_module("wasi_unstable")); + EXPECT_EQ(true, wasm_runtime_is_built_in_module("wasi_snapshot_preview1")); + EXPECT_EQ(true, wasm_runtime_is_built_in_module("")); + EXPECT_EQ(false, wasm_runtime_is_built_in_module("test")); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_read_v128) +{ + unsigned char buf[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + unsigned char ret1[8] = { 0 }; + unsigned char ret2[8] = { 0 }; + + wasm_runtime_read_v128((const uint8 *)buf, (uint64 *)ret1, (uint64 *)ret2); + EXPECT_EQ(0, strncmp("01234567", (const char *)ret1, 8)); + EXPECT_EQ(0, strncmp("89ABCDEF", (const char *)ret2, 8)); +} + +TEST_F(wasm_runtime_common_test_suite, + wasm_runtime_show_app_heap_corrupted_prompt) +{ + wasm_runtime_show_app_heap_corrupted_prompt(); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_is_xip_file) +{ + // WASM file. + const char *wasm_file = WASM_FILE_1; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + EXPECT_EQ(false, wasm_runtime_is_xip_file(wasm_file_buf, wasm_file_size)); + + // AoT file. + const char *aot_file = AOT_FILE_1; + unsigned int aot_file_size = 0; + unsigned char *aot_file_buf = nullptr; + + aot_file_buf = + (unsigned char *)bh_read_file_to_buffer(aot_file, &aot_file_size); + EXPECT_NE(aot_file_buf, nullptr); + EXPECT_EQ(false, wasm_runtime_is_xip_file(aot_file_buf, aot_file_size)); +} + +TEST_F(wasm_runtime_common_test_suite, get_package_type) +{ + const char *wasm_file = WASM_FILE_1; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + + // WASM file. + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + EXPECT_EQ(Wasm_Module_Bytecode, + get_package_type(wasm_file_buf, wasm_file_size)); + + // WASM file. Abnormally. + wasm_file_buf[3] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[2] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[1] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[0] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + + EXPECT_EQ(Package_Type_Unknown, get_package_type(wasm_file_buf, 0)); + EXPECT_EQ(Package_Type_Unknown, get_package_type(nullptr, 0)); + + // AoT file. + const char *wasm_file_aot = AOT_FILE_1; + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file_aot, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + EXPECT_EQ(Wasm_Module_AoT, get_package_type(wasm_file_buf, wasm_file_size)); + + // AoT file. Abnormally. + wasm_file_buf[3] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[2] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[1] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[0] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + + EXPECT_EQ(Package_Type_Unknown, get_package_type(wasm_file_buf, 0)); + EXPECT_EQ(Package_Type_Unknown, get_package_type(nullptr, 0)); +} + +TEST_F(wasm_runtime_common_test_suite, functions_on_wasm_module) +{ + const char *wasm_file = WASM_FILE_1; + wasm_module_inst_t wasm_module_inst = nullptr; + wasm_module_t wasm_module = nullptr; + wasm_exec_env_t exec_env = nullptr; + wasm_exec_env_t exec_env_1 = nullptr; + unsigned char *wasm_file_buf = nullptr; + WASMFunctionInstanceCommon *func = nullptr; + const char *user_data = "test"; + unsigned int wasm_file_size = 0; + unsigned int stack_size = 16 * 1024, heap_size = 16 * 1024; + char error_buf[128] = { 0 }; + unsigned int argv[2] = { 0 }; + WASMType *func_type = nullptr; + wasm_val_t arguments[1]; + char str_test[] = "This is a test."; + char str_exception[] = "Exception: "; + char str_tmp[60] = { 0 }; + void *ptr_tmp = nullptr; + unsigned int offset_tmp = 0; + unsigned int tmp = 0; + unsigned char *p_native_start_addr = nullptr; + unsigned char *p_native_end_addr = nullptr; + NativeSymbol *native_symbols; + uint32 n_native_symbols; + const char *exception_test = nullptr; + + arguments[0].kind = WASM_I32; + arguments[0].of.i32 = 0; + + // Create exec_env. + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + wasm_module_inst = wasm_runtime_instantiate( + wasm_module, stack_size, heap_size, error_buf, sizeof(error_buf)); + EXPECT_NE(wasm_module_inst, nullptr); + exec_env = wasm_runtime_create_exec_env(wasm_module_inst, stack_size); + EXPECT_NE(exec_env, nullptr); + + // Operations on exec_env. + EXPECT_EQ(true, wasm_runtime_register_module_internal("test", wasm_module, + nullptr, 0, error_buf, + sizeof(error_buf))); + EXPECT_NE(nullptr, wasm_runtime_find_module_registered("test")); + EXPECT_EQ(wasm_module_inst, wasm_runtime_get_module_inst(exec_env)); + EXPECT_EQ(exec_env->attachment, + wasm_runtime_get_function_attachment(exec_env)); + EXPECT_EQ(wasm_module, wasm_exec_env_get_module(exec_env)); + + wasm_runtime_set_user_data(exec_env, (void *)user_data); + EXPECT_EQ((void *)user_data, wasm_runtime_get_user_data(exec_env)); + + func = wasm_runtime_lookup_function(wasm_module_inst, "on_timer_event"); + func_type = + wasm_runtime_get_function_type(func, wasm_module_inst->module_type); + EXPECT_NE(func_type, nullptr); + EXPECT_EQ(false, wasm_runtime_call_wasm(exec_env, func, 0, argv)); + exception_test = wasm_runtime_get_exception(wasm_module_inst); + EXPECT_NE(nullptr, exception_test); + + EXPECT_EQ(false, wasm_runtime_call_wasm_a(exec_env, func, 0, nullptr, 1, + arguments)); + exception_test = wasm_runtime_get_exception(wasm_module_inst); + EXPECT_NE(nullptr, exception_test); + + WASMFunctionInstance func_test_1; + WASMFunction wasm_func_test; + WASMType wasm_type_test; + wasm_func_test.func_type = &wasm_type_test; + func_test_1.u.func = &wasm_func_test; + func_test_1.u.func->func_type->param_count = 1; + func_test_1.u.func->func_type->param_cell_num = 2; + func_test_1.u.func->func_type->types[0] = VALUE_TYPE_I64; + func_test_1.u.func->max_stack_cell_num = 10; + EXPECT_EQ(false, wasm_runtime_call_wasm_v( + exec_env, (WASMFunctionInstanceCommon *)(&func_test_1), + 0, nullptr, 1, arguments)); + func_test_1.u.func->func_type->types[0] = VALUE_TYPE_F32; + EXPECT_EQ(false, wasm_runtime_call_wasm_v( + exec_env, (WASMFunctionInstanceCommon *)(&func_test_1), + 0, nullptr, 1, arguments)); + func_test_1.u.func->func_type->types[0] = VALUE_TYPE_F64; + EXPECT_EQ(false, wasm_runtime_call_wasm_v( + exec_env, (WASMFunctionInstanceCommon *)(&func_test_1), + 0, nullptr, 1, arguments)); + +#if 0 + WASMFunctionInstance func_test; + WASMFunctionImport func_import_test; + WASMType *func_type_1 = nullptr; + func_import_test.func_type = func_type; + func_test.u.func_import = &func_import_test; + func_test.is_import_func = true; + func_type_1 = wasm_runtime_get_function_type(&func_test, + wasm_module_inst->module_type); + EXPECT_NE(func_type_1, nullptr); +#endif + + EXPECT_EQ(true, wasm_runtime_create_exec_env_singleton(wasm_module_inst)); + EXPECT_NE(nullptr, wasm_runtime_get_exec_env_singleton(wasm_module_inst)); + + wasm_runtime_set_exception(wasm_module_inst, str_test); + sprintf(str_tmp, "%s%s", str_exception, str_test); + EXPECT_EQ(0, strcmp(str_tmp, wasm_runtime_get_exception(wasm_module_inst))); + wasm_runtime_clear_exception(wasm_module_inst); + EXPECT_EQ(nullptr, wasm_runtime_get_exception(wasm_module_inst)); + + wasm_runtime_set_custom_data(wasm_module_inst, (void *)user_data); + EXPECT_EQ((void *)user_data, + wasm_runtime_get_custom_data(wasm_module_inst)); + + offset_tmp = wasm_runtime_module_malloc(wasm_module_inst, 10, &ptr_tmp); + EXPECT_NE(0, offset_tmp); + EXPECT_EQ(true, + wasm_runtime_validate_app_addr(wasm_module_inst, offset_tmp, 10)); + EXPECT_EQ(ptr_tmp, + wasm_runtime_addr_app_to_native(wasm_module_inst, offset_tmp)); + EXPECT_EQ(true, + wasm_runtime_validate_native_addr(wasm_module_inst, ptr_tmp, 10)); + EXPECT_EQ(offset_tmp, + wasm_runtime_addr_native_to_app(wasm_module_inst, ptr_tmp)); + EXPECT_EQ(true, wasm_runtime_get_native_addr_range( + wasm_module_inst, (unsigned char *)ptr_tmp, + &p_native_start_addr, &p_native_end_addr)); + EXPECT_NE(0, wasm_runtime_module_realloc(wasm_module_inst, offset_tmp, 100, + &ptr_tmp)); + /* can't test like that since shrink size optimization will be applied */ + /* EXPECT_EQ(false, + wasm_enlarge_memory((WASMModuleInstance *)wasm_module_inst, 1)); + */ + EXPECT_EQ(offset_tmp, + wasm_runtime_addr_native_to_app(wasm_module_inst, ptr_tmp)); + EXPECT_EQ(true, wasm_runtime_get_native_addr_range( + wasm_module_inst, (unsigned char *)ptr_tmp, + &p_native_start_addr, &p_native_end_addr)); + + offset_tmp = wasm_runtime_module_dup_data(wasm_module_inst, str_test, + sizeof(str_test)); + EXPECT_EQ(0, strcmp(str_test, (char *)wasm_runtime_addr_app_to_native( + wasm_module_inst, offset_tmp))); + EXPECT_EQ(true, + wasm_runtime_validate_app_str_addr(wasm_module_inst, offset_tmp)); + + ((WASMModuleInstance *)wasm_module_inst)->exec_env_singleton = nullptr; + EXPECT_NE(nullptr, wasm_runtime_get_exec_env_singleton(wasm_module_inst)); + + EXPECT_EQ(false, wasm_runtime_call_wasm(nullptr, func, 0, argv)); + wasm_runtime_set_exception(wasm_module_inst, str_test); + EXPECT_EQ(false, wasm_runtime_call_wasm(exec_env, func, 0, argv)); + wasm_runtime_clear_exception(wasm_module_inst); + + EXPECT_EQ(false, wasm_runtime_call_wasm_a(exec_env, func, 0, nullptr, 2, + arguments)); + WASMFunctionInstance *func_test_call_wasm_a_ptr = + (WASMFunctionInstance *)func; + func_test_call_wasm_a_ptr->u.func->func_type->ret_cell_num = 10; + EXPECT_EQ(true, wasm_runtime_call_wasm_a(exec_env, func, 0, nullptr, 1, + arguments)); + + // Destroy. + wasm_runtime_module_free(wasm_module_inst, offset_tmp); + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(wasm_module_inst); + wasm_runtime_unload(wasm_module); + if (wasm_file_buf) { + wasm_runtime_free(wasm_file_buf); + } +} + +TEST_F(wasm_runtime_common_test_suite, functions_on_aot_module) +{ + const char *wasm_file = AOT_FILE_1; + wasm_module_inst_t wasm_module_inst = nullptr; + wasm_module_t wasm_module = nullptr; + wasm_exec_env_t exec_env = nullptr; + wasm_exec_env_t exec_env_1 = nullptr; + unsigned char *wasm_file_buf = nullptr; + WASMFunctionInstanceCommon *func = nullptr; + const char *user_data = "test"; + unsigned int wasm_file_size = 0; + unsigned int stack_size = 16 * 1024, heap_size = 16 * 1024; + char error_buf[128] = { 0 }; + unsigned int argv[2] = { 0 }; + WASMType *func_type = nullptr; + wasm_val_t arguments[1]; + char str_test[] = "This is a test."; + char str_exception[] = "Exception: "; + char str_tmp[60] = { 0 }; + void *ptr_tmp = nullptr; + unsigned int offset_tmp = 0; + unsigned int tmp = 0; + unsigned char *p_native_start_addr = nullptr; + unsigned char *p_native_end_addr = nullptr; + NativeSymbol *native_symbols; + uint32 n_native_symbols; + const char *exception_test = nullptr; + + arguments[0].kind = WASM_I32; + arguments[0].of.i32 = 0; + + // Create exec_env. + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + wasm_module_inst = wasm_runtime_instantiate( + wasm_module, stack_size, heap_size, error_buf, sizeof(error_buf)); + EXPECT_NE(wasm_module_inst, nullptr); + exec_env = wasm_runtime_create_exec_env(wasm_module_inst, stack_size); + EXPECT_NE(exec_env, nullptr); + + // Operations on exec_env. + EXPECT_EQ(true, wasm_runtime_register_module_internal("test", wasm_module, + nullptr, 0, error_buf, + sizeof(error_buf))); + EXPECT_NE(nullptr, wasm_runtime_find_module_registered("test")); + EXPECT_EQ(wasm_module_inst, wasm_runtime_get_module_inst(exec_env)); + EXPECT_EQ(exec_env->attachment, + wasm_runtime_get_function_attachment(exec_env)); + EXPECT_EQ(wasm_module, wasm_exec_env_get_module(exec_env)); + + wasm_runtime_set_user_data(exec_env, (void *)user_data); + EXPECT_EQ((void *)user_data, wasm_runtime_get_user_data(exec_env)); + + func = wasm_runtime_lookup_function(wasm_module_inst, "on_timer_event"); + func_type = + wasm_runtime_get_function_type(func, wasm_module_inst->module_type); + EXPECT_NE(func_type, nullptr); + + EXPECT_EQ(false, wasm_runtime_call_wasm(exec_env, func, 0, argv)); + exception_test = wasm_runtime_get_exception(wasm_module_inst); + EXPECT_NE(nullptr, exception_test); + + EXPECT_EQ(false, wasm_runtime_call_wasm_a(exec_env, func, 0, nullptr, 1, + arguments)); + exception_test = wasm_runtime_get_exception(wasm_module_inst); + EXPECT_NE(nullptr, exception_test); + EXPECT_EQ(false, wasm_runtime_call_wasm_v(exec_env, func, 0, nullptr, 1, + arguments)); + exception_test = wasm_runtime_get_exception(wasm_module_inst); + EXPECT_NE(nullptr, exception_test); + + AOTFunctionInstance func_test; + AOTImportFunc func_import_test; + func_test.u.func_import = &func_import_test; + func_import_test.func_type = (AOTFuncType *)func_type; + func_test.is_import_func = true; + EXPECT_NE(nullptr, wasm_runtime_get_function_type( + &func_test, wasm_module_inst->module_type)); + + EXPECT_EQ(true, wasm_runtime_create_exec_env_singleton(wasm_module_inst)); + EXPECT_NE(nullptr, wasm_runtime_get_exec_env_singleton(wasm_module_inst)); + + wasm_runtime_set_exception(wasm_module_inst, str_test); + sprintf(str_tmp, "%s%s", str_exception, str_test); + EXPECT_EQ(0, strcmp(str_tmp, wasm_runtime_get_exception(wasm_module_inst))); + wasm_runtime_clear_exception(wasm_module_inst); + EXPECT_EQ(nullptr, wasm_runtime_get_exception(wasm_module_inst)); + + wasm_runtime_set_custom_data(wasm_module_inst, (void *)user_data); + EXPECT_EQ((void *)user_data, + wasm_runtime_get_custom_data(wasm_module_inst)); + + offset_tmp = wasm_runtime_module_malloc(wasm_module_inst, 10, &ptr_tmp); + EXPECT_NE(0, offset_tmp); + EXPECT_EQ(true, + wasm_runtime_validate_app_addr(wasm_module_inst, offset_tmp, 10)); + EXPECT_EQ(ptr_tmp, + wasm_runtime_addr_app_to_native(wasm_module_inst, offset_tmp)); + EXPECT_EQ(true, + wasm_runtime_validate_native_addr(wasm_module_inst, ptr_tmp, 10)); + EXPECT_EQ(offset_tmp, + wasm_runtime_addr_native_to_app(wasm_module_inst, ptr_tmp)); + EXPECT_EQ(true, wasm_runtime_get_native_addr_range( + wasm_module_inst, (unsigned char *)ptr_tmp, + &p_native_start_addr, &p_native_end_addr)); + EXPECT_NE(0, wasm_runtime_module_realloc(wasm_module_inst, offset_tmp, 100, + &ptr_tmp)); + + /* can't test like that since shrink size optimization will be applied */ + /* EXPECT_EQ(false, + wasm_enlarge_memory((WASMModuleInstance *)wasm_module_inst, 1)); + */ + + offset_tmp = wasm_runtime_module_dup_data(wasm_module_inst, str_test, + sizeof(str_test)); + EXPECT_EQ(0, strcmp(str_test, (char *)wasm_runtime_addr_app_to_native( + wasm_module_inst, offset_tmp))); + EXPECT_EQ(true, + wasm_runtime_validate_app_str_addr(wasm_module_inst, offset_tmp)); + + ((WASMModuleInstance *)wasm_module_inst)->exec_env_singleton = nullptr; + EXPECT_NE(nullptr, wasm_runtime_get_exec_env_singleton(wasm_module_inst)); + + // Destroy. + wasm_runtime_module_free(wasm_module_inst, offset_tmp); + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(wasm_module_inst); + wasm_runtime_unload(wasm_module); + if (wasm_file_buf) { + wasm_runtime_free(wasm_file_buf); + } +} + +TEST_F(wasm_runtime_common_test_suite, functions_on_module_type_unknown) +{ + const char *wasm_file = AOT_FILE_1; + wasm_module_inst_t wasm_module_inst = nullptr; + wasm_module_t wasm_module = nullptr; + wasm_exec_env_t exec_env = nullptr; + wasm_exec_env_t exec_env_1 = nullptr; + unsigned char *wasm_file_buf = nullptr; + WASMFunctionInstanceCommon *func = nullptr; + const char *user_data = "test"; + unsigned int wasm_file_size = 0; + unsigned int stack_size = 16 * 1024, heap_size = 16 * 1024; + char error_buf[128] = { 0 }; + unsigned int argv[2] = { 0 }; + WASMType *func_type = nullptr; + wasm_val_t arguments[1]; + char str_test[] = "This is a test."; + char str_exception[] = "Exception: "; + char str_tmp[60] = { 0 }; + void *ptr_tmp = nullptr; + unsigned int offset_tmp = 0; + unsigned int tmp = 0; + unsigned char *p_native_start_addr = nullptr; + unsigned char *p_native_end_addr = nullptr; + const char *exception_test = nullptr; + + arguments[0].kind = WASM_I32; + arguments[0].of.i32 = 0; + + // Create exec_env. + wasm_runtime_unregister_module(wasm_module); + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + wasm_module_inst = wasm_runtime_instantiate( + wasm_module, stack_size, heap_size, error_buf, sizeof(error_buf)); + EXPECT_NE(wasm_module_inst, nullptr); + exec_env = wasm_runtime_create_exec_env(wasm_module_inst, stack_size); + EXPECT_NE(exec_env, nullptr); + + // wasm_module_inst->module_type = Package_Type_Unknown. + wasm_module_inst->module_type = Package_Type_Unknown; + EXPECT_DEATH(wasm_exec_env_get_module(exec_env), ""); + EXPECT_DEATH( + wasm_runtime_validate_app_str_addr(wasm_module_inst, offset_tmp), ""); + + // wasm_module->module_type = Package_Type_Unknown. + wasm_module->module_type = Package_Type_Unknown; + EXPECT_EQ(nullptr, + wasm_runtime_instantiate(wasm_module, stack_size, heap_size, + error_buf, sizeof(error_buf))); + + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + /* Reload unmodified buffer should be valid now */ + EXPECT_NE(wasm_module, nullptr); + wasm_file_buf[3] = -1; + wasm_file_buf[2] = -1; + wasm_file_buf[1] = -1; + wasm_file_buf[0] = -1; + wasm_module = + wasm_runtime_load(wasm_file_buf, 0, error_buf, sizeof(error_buf)); + EXPECT_EQ(wasm_module, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_EQ(wasm_module, nullptr); + + // Destroy. + wasm_runtime_module_free(wasm_module_inst, offset_tmp); + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(wasm_module_inst); + wasm_runtime_unload(wasm_module); + if (wasm_file_buf) { + wasm_runtime_free(wasm_file_buf); + } +} diff --git a/tests/unit/runtime-common/wasm_runtime_init_test.cc b/tests/unit/runtime-common/wasm_runtime_init_test.cc new file mode 100644 index 0000000000..30e44cea31 --- /dev/null +++ b/tests/unit/runtime-common/wasm_runtime_init_test.cc @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "platform_common.h" +#include "wasm_runtime_common.h" +#include "bh_read_file.h" +#include "wasm_runtime.h" +#include "bh_platform.h" +#include "wasm_export.h" + +using namespace std; + +extern "C" { +uint32 +wasm_runtime_module_realloc(WASMModuleInstanceCommon *module_inst, uint32 ptr, + uint32 size, void **p_native_addr); +bool +wasm_runtime_create_exec_env_and_call_wasm( + WASMModuleInstanceCommon *module_inst, WASMFunctionInstanceCommon *function, + uint32 argc, uint32 argv[]); +} + +static char global_heap_buf[100 * 1024 * 1024] = { 0 }; + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static std::string MAIN_AOT = "/main.aot"; +static char *WASM_FILE_1; +static char *AOT_FILE_1; + +static int +foo(int a, int b); + +static int +foo_native(wasm_exec_env_t exec_env, int a, int b) +{ + return a + b; +} + +static NativeSymbol native_symbols[] = { { + "foo", // the name of WASM function name + (void *)foo_native, // the native function pointer + "(ii)i" // the function prototype signature +} }; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class wasm_runtime_init_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE_1 = strdup((CWD + MAIN_WASM).c_str()); + AOT_FILE_1 = strdup((CWD + MAIN_AOT).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() + { + free(WASM_FILE_1); + free(AOT_FILE_1); + } +}; + +TEST_F(wasm_runtime_init_test_suite, init_and_register_natives) +{ + EXPECT_EQ(true, wasm_runtime_init()); + int n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); + EXPECT_EQ(true, wasm_runtime_register_natives("env", native_symbols, + n_native_symbols)); + EXPECT_EQ(true, wasm_runtime_register_natives_raw("env", native_symbols, + n_native_symbols)); + wasm_runtime_destroy(); +} + +TEST_F(wasm_runtime_init_test_suite, init_thread_env_destroy_thread_env) +{ + EXPECT_EQ(true, wasm_runtime_init_thread_env()); + wasm_runtime_destroy_thread_env(); +} + +TEST_F(wasm_runtime_init_test_suite, wasm_runtime_full_init) +{ + RuntimeInitArgs init_args; + unsigned char *wasm_file_buf; + uint32 wasm_file_size; + wasm_module_t module = nullptr; + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + EXPECT_EQ(true, wasm_runtime_full_init(&init_args)); + wasm_runtime_destroy(); + init_args.n_native_symbols = 1; + EXPECT_EQ(true, wasm_runtime_full_init(&init_args)); + wasm_runtime_destroy(); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = (void *)malloc; + init_args.mem_alloc_option.allocator.realloc_func = (void *)realloc; + init_args.mem_alloc_option.allocator.free_func = (void *)free; + EXPECT_EQ(true, wasm_runtime_full_init(&init_args)); + wasm_runtime_destroy(); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = (void *)os_malloc; + init_args.mem_alloc_option.allocator.realloc_func = (void *)os_realloc; + init_args.mem_alloc_option.allocator.free_func = (void *)os_free; + EXPECT_EQ(true, wasm_runtime_full_init(&init_args)); + /* Use valid module, and runtime need to be proper inited */ + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(WASM_FILE_1, &wasm_file_size); + EXPECT_NE(nullptr, wasm_file_buf); + module = wasm_runtime_load(wasm_file_buf, wasm_file_size, nullptr, 0); + EXPECT_NE(nullptr, module); + EXPECT_EQ(true, wasm_runtime_register_module_internal( + "module", module, wasm_file_buf, wasm_file_size, nullptr, 0)); + wasm_runtime_destroy(); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = NULL; + init_args.mem_alloc_option.pool.heap_size = 0; + EXPECT_EQ(false, wasm_runtime_full_init(&init_args)); +} diff --git a/tests/unit/shared-utils/CMakeLists.txt b/tests/unit/shared-utils/CMakeLists.txt new file mode 100644 index 0000000000..c5a43dd0e0 --- /dev/null +++ b/tests/unit/shared-utils/CMakeLists.txt @@ -0,0 +1,30 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-shared-utils) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} +) + +add_executable (shared_utils_test ${unit_test_sources}) + +target_link_libraries (shared_utils_test gtest_main) + +gtest_discover_tests(shared_utils_test) diff --git a/tests/unit/shared-utils/bh_assert_test.cc b/tests/unit/shared-utils/bh_assert_test.cc new file mode 100644 index 0000000000..faa7a807b9 --- /dev/null +++ b/tests/unit/shared-utils/bh_assert_test.cc @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_assert.h" + +class bh_assert_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} +}; + +TEST_F(bh_assert_test_suite, bh_assert_internal) +{ + bh_assert_internal(6, "file_name_test", 6, "expr_string_test"); + + // Test abnormal cases. + EXPECT_DEATH(bh_assert_internal(0, "file_name_test", 1, "expr_string_test"), + ""); + EXPECT_DEATH(bh_assert_internal(0, nullptr, 2, "expr_string_test"), ""); + EXPECT_DEATH(bh_assert_internal(0, "file_name_test", 3, nullptr), ""); +} diff --git a/tests/unit/shared-utils/bh_common_test.cc b/tests/unit/shared-utils/bh_common_test.cc new file mode 100644 index 0000000000..1d1cb528d7 --- /dev/null +++ b/tests/unit/shared-utils/bh_common_test.cc @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_common.h" + +class bh_common_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +#define STR_TEST "test" + +TEST_F(bh_common_test_suite, wa_strdup) +{ + EXPECT_EQ(nullptr, wa_strdup(nullptr)); + EXPECT_NE(nullptr, wa_strdup(STR_TEST)); +} + +TEST_F(bh_common_test_suite, b_strcpy_s) +{ + char dest[10] = { 0 }; + + EXPECT_EQ(0, b_strcpy_s(dest, sizeof(dest), STR_TEST)); + + // Test abnormal cases. + EXPECT_EQ(-1, b_strcpy_s(nullptr, 0, nullptr)); + EXPECT_EQ(-1, b_strcpy_s(dest, sizeof(dest), nullptr)); + EXPECT_EQ(-1, b_strcpy_s(dest, 0, STR_TEST)); +} + +TEST_F(bh_common_test_suite, b_strcat_s) +{ + char dest[10] = { 0 }; + + EXPECT_EQ(0, b_strcat_s(dest, sizeof(dest), STR_TEST)); + + // Test abnormal cases. + EXPECT_EQ(-1, b_strcat_s(nullptr, 0, nullptr)); + EXPECT_EQ(-1, b_strcat_s(dest, sizeof(dest), nullptr)); + EXPECT_EQ(-1, b_strcat_s(dest, 0, STR_TEST)); +} + +TEST_F(bh_common_test_suite, bh_strdup) +{ + EXPECT_NE(nullptr, bh_strdup(STR_TEST)); + EXPECT_EQ(nullptr, bh_strdup(nullptr)); +} + +TEST_F(bh_common_test_suite, b_memmove_s) +{ + char dest[10] = { 0 }; + + EXPECT_EQ(0, b_memmove_s(dest, sizeof(dest), STR_TEST, sizeof(STR_TEST))); + + // Test abnormal cases. + EXPECT_EQ(0, b_memmove_s(dest, sizeof(dest), STR_TEST, 0)); + EXPECT_EQ(0, b_memmove_s(nullptr, sizeof(dest), STR_TEST, 0)); + + EXPECT_EQ(0, b_memmove_s(dest, sizeof(dest), nullptr, 0)); + EXPECT_EQ(-1, b_memmove_s(dest, sizeof(dest), STR_TEST, sizeof(dest) + 1)); +} + +TEST_F(bh_common_test_suite, b_memcpy_s) +{ + char dest[10] = { 0 }; + + EXPECT_EQ(0, b_memcpy_s(dest, sizeof(dest), STR_TEST, sizeof(STR_TEST))); + + // Test abnormal cases. + EXPECT_EQ(0, b_memcpy_s(dest, sizeof(dest), STR_TEST, 0)); + EXPECT_EQ(-1, + b_memcpy_s(nullptr, sizeof(dest), STR_TEST, sizeof(STR_TEST))); + EXPECT_EQ(-1, b_memcpy_s(dest, sizeof(dest), nullptr, sizeof(STR_TEST))); + EXPECT_EQ(-1, b_memcpy_s(dest, sizeof(dest), STR_TEST, sizeof(dest) + 1)); +} diff --git a/tests/unit/shared-utils/bh_hashmap_test.cc b/tests/unit/shared-utils/bh_hashmap_test.cc new file mode 100644 index 0000000000..4b651ef177 --- /dev/null +++ b/tests/unit/shared-utils/bh_hashmap_test.cc @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" +#include "test_helper.h" +#include "gtest/gtest.h" +#include "bh_hashmap.h" +#include "wasm.h" +#include "wasm_export.h" + +#include + +typedef struct HashMapElem { + void *key; + void *value; + struct HashMapElem *next; +} HashMapElem; + +struct HashMap { + /* size of element array */ + uint32 size; + /* lock for elements */ + korp_mutex *lock; + /* hash function of key */ + HashFunc hash_func; + /* key equal function */ + KeyEqualFunc key_equal_func; + KeyDestroyFunc key_destroy_func; + ValueDestroyFunc value_destroy_func; + HashMapElem *elements[1]; +}; + +int DESTROY_NUM = 0; +char TRAVERSE_KEY[] = "key_1"; +char TRAVERSE_VAL[] = "val_1"; +int TRAVERSE_COMP_RES = 0; + +class bh_hashmap_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(bh_hashmap_test_suite, bh_hash_map_create) +{ + // Normally. + EXPECT_NE((HashMap *)nullptr, + bh_hash_map_create(32, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free)); + + // Illegal parameters. + EXPECT_EQ((HashMap *)nullptr, + bh_hash_map_create(65537, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free)); + EXPECT_EQ((HashMap *)nullptr, + bh_hash_map_create(65536, true, nullptr, nullptr, nullptr, + wasm_runtime_free)); + EXPECT_EQ((HashMap *)nullptr, + bh_hash_map_create(65536, true, (HashFunc)wasm_string_hash, + nullptr, nullptr, wasm_runtime_free)); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_insert) +{ + HashMap *test_hash_map = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + nullptr, wasm_runtime_free); + int num = 0; + void **p_old_key = nullptr; + void **p_old_value = nullptr; + + // Normally. + EXPECT_EQ(true, bh_hash_map_insert(test_hash_map, (void *)"key_1", + (void *)"val_1")); + num++; + // Illegal parameters. + EXPECT_EQ(false, bh_hash_map_insert(nullptr, nullptr, (void *)"val_2")); + + // Execute fail: more than 32. + for (; num <= 32; num++) { + bh_hash_map_insert(test_hash_map, (void *)&num, (void *)"val"); + } + EXPECT_EQ(false, + bh_hash_map_insert(test_hash_map, (void *)&num, (void *)"val")); + + // Remove one, insert one. + bh_hash_map_remove(test_hash_map, (void *)"key_1", p_old_key, p_old_value); + EXPECT_EQ(true, bh_hash_map_insert(test_hash_map, (void *)"key_1", + (void *)"val_1")); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_find) +{ + HashMap *test_hash_map = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + nullptr, wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + + // Normally. use_lock is false. + EXPECT_NE((void *)nullptr, + bh_hash_map_find(test_hash_map, (void *)"key_1")); + + // Execute fail. + EXPECT_EQ((void *)nullptr, + bh_hash_map_find(test_hash_map, (void *)"KEY_1")); + + // Illegal parameters. + EXPECT_EQ((void *)nullptr, bh_hash_map_find(nullptr, nullptr)); + EXPECT_EQ((void *)nullptr, bh_hash_map_find(test_hash_map, nullptr)); + + // Normally. use_lock is true. + test_hash_map = bh_hash_map_create(32, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + EXPECT_EQ((void *)nullptr, + bh_hash_map_find(test_hash_map, (void *)"KEY_1")); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_update) +{ + char old_value[10] = { 0 }; + void **p_old_value = (void **)(&old_value); + HashMap *test_hash_map = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + nullptr, wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + + // test_hash_map->lock == nullptr. Normally. + EXPECT_EQ(true, bh_hash_map_update(test_hash_map, (void *)"key_1", + (void *)"val_2", p_old_value)); + // test_hash_map->lock == nullptr. Illegal parameters. + EXPECT_EQ(false, bh_hash_map_update(nullptr, nullptr, (void *)"val_2", + p_old_value)); + EXPECT_EQ(false, bh_hash_map_update(test_hash_map, nullptr, (void *)"val_2", + p_old_value)); + EXPECT_EQ(false, + bh_hash_map_update(nullptr, nullptr, (void *)"val_2", nullptr)); + + // test_hash_map->lock == nullptr. Update non-existent elements. + EXPECT_EQ(false, bh_hash_map_update(test_hash_map, (void *)"key", + (void *)"val", p_old_value)); + + test_hash_map = bh_hash_map_create(32, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + + // test_hash_map->lock == no nullptr. Normally. + EXPECT_EQ(true, bh_hash_map_update(test_hash_map, (void *)"key_1", + (void *)"val_2", p_old_value)); + // test_hash_map->lock == no nullptr. Illegal parameters. + EXPECT_EQ(false, bh_hash_map_update(nullptr, nullptr, (void *)"val_2", + p_old_value)); + EXPECT_EQ(false, bh_hash_map_update(test_hash_map, nullptr, (void *)"val_2", + p_old_value)); +} + +void +trav_callback_fun(void *key, void *value, void *user_data) +{ + if (!strncmp(TRAVERSE_VAL, (const char *)value, 5)) { + TRAVERSE_COMP_RES = 1; + } + else { + TRAVERSE_COMP_RES = 0; + } +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_traverse) +{ + void **p_old_value = nullptr; + HashMap *test_hash_map = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + nullptr, wasm_runtime_free); + + // Normally: TRAVERSE_COMP_RES = 1. + bh_hash_map_insert(test_hash_map, (void *)TRAVERSE_KEY, + (void *)TRAVERSE_VAL); + EXPECT_EQ(true, + bh_hash_map_traverse(test_hash_map, trav_callback_fun, nullptr)); + EXPECT_EQ(1, TRAVERSE_COMP_RES); + + // Normally: TRAVERSE_COMP_RES = 0. + bh_hash_map_update(test_hash_map, (void *)TRAVERSE_KEY, (void *)"val", + p_old_value); + EXPECT_EQ(true, + bh_hash_map_traverse(test_hash_map, trav_callback_fun, nullptr)); + EXPECT_EQ(0, TRAVERSE_COMP_RES); + // Illegal parameters. + EXPECT_EQ(false, bh_hash_map_traverse(nullptr, trav_callback_fun, nullptr)); + EXPECT_EQ(false, bh_hash_map_traverse(test_hash_map, nullptr, nullptr)); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_remove) +{ + void **p_old_key = nullptr; + void **p_old_value = nullptr; + + HashMap *test_hash_map = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + nullptr, wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + bh_hash_map_insert(test_hash_map, (void *)"key_2", (void *)"val_2"); + + // test_hash_map->lock == nullptr. Normally. + EXPECT_EQ(true, bh_hash_map_remove(test_hash_map, (void *)"key_1", + p_old_key, p_old_value)); + // test_hash_map->lock == nullptr. Remove non-existent elements. + EXPECT_EQ(false, bh_hash_map_remove(test_hash_map, (void *)"key_1", + p_old_key, p_old_value)); + // test_hash_map->lock == nullptr. Illegal parameters. + EXPECT_EQ(false, bh_hash_map_remove(nullptr, (void *)"key_2", p_old_key, + p_old_value)); + EXPECT_EQ(false, bh_hash_map_remove(test_hash_map, nullptr, p_old_key, + p_old_value)); + + test_hash_map = bh_hash_map_create(32, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + bh_hash_map_insert(test_hash_map, (void *)"key_2", (void *)"val_2"); + + // test_hash_map->lock == no nullptr. Normally. + EXPECT_EQ(true, bh_hash_map_remove(test_hash_map, (void *)"key_1", + p_old_key, p_old_value)); + // test_hash_map->lock == no nullptr. Illegal parameters. + EXPECT_EQ(false, bh_hash_map_remove(nullptr, (void *)"key_2", p_old_key, + p_old_value)); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_get_struct_size) +{ + HashMap *test_hash_map = nullptr; + uint32 size = 0; + + // No lock. + test_hash_map = bh_hash_map_create(32, false, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + size = (size_t)(&((HashMap *)0)->elements) + + (uint32)sizeof(HashMapElem *) * test_hash_map->size; + EXPECT_EQ(size, bh_hash_map_get_struct_size(test_hash_map)); + + // Has lock. + test_hash_map = bh_hash_map_create(32, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + size = (size_t)(&((HashMap *)0)->elements) + + (uint32)sizeof(HashMapElem *) * test_hash_map->size; + size += (uint32)sizeof(korp_mutex); + EXPECT_EQ(size, bh_hash_map_get_struct_size(test_hash_map)); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_get_elem_struct_size) +{ + EXPECT_EQ((uint32)sizeof(HashMapElem), bh_hash_map_get_elem_struct_size()); +} + +void +destroy_func_test(void *key) +{ + DESTROY_NUM++; +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_destroy) +{ + HashMap *test_hash_map = bh_hash_map_create( + 32, true, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + destroy_func_test, wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + bh_hash_map_insert(test_hash_map, (void *)"key_2", (void *)"val_2"); + + // test_hash_map->lock == no nullptr. Normally. + EXPECT_EQ(true, bh_hash_map_destroy(test_hash_map)); + // key_destroy_func must be called 2 times. + EXPECT_EQ(2, DESTROY_NUM); + + test_hash_map = bh_hash_map_create(32, false, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, + destroy_func_test, wasm_runtime_free); + + // test_hash_map->lock == no nullptr. Illegal parameters. + EXPECT_EQ(false, bh_hash_map_destroy(nullptr)); + // test_hash_map->lock == nullptr. + EXPECT_EQ(true, bh_hash_map_destroy(test_hash_map)); + + // key_destroy_func and value_destroy_func is nullptr. + test_hash_map = + bh_hash_map_create(32, false, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, nullptr); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + bh_hash_map_insert(test_hash_map, (void *)"key_2", (void *)"val_2"); + EXPECT_EQ(true, bh_hash_map_destroy(test_hash_map)); +} + +// This fun allows inserting the same keys. +bool +string_equal_test(const char *s1, const char *s2) +{ + return false; +} + +int COUNT_ELEM = 0; + +void +fun_count_elem(void *key, void *value, void *user_data) +{ + COUNT_ELEM++; +} + +TEST_F(bh_hashmap_test_suite, bh_hashmap_thread_safety) +{ + HashMap *test_hash_map = bh_hash_map_create( + 32, true, (HashFunc)wasm_string_hash, (KeyEqualFunc)string_equal_test, + destroy_func_test, wasm_runtime_free); + int32_t i = 0; + std::vector> threads; + + // Creat 8 threads. In every thread, run the codes in brackets of + // std::async. + for (i = 0; i < 8; i++) { + threads.push_back(std::async([&] { + for (int j = 0; j < 25; j++) { + bh_hash_map_insert(test_hash_map, (void *)"key_1", + (void *)"val_1"); + } + })); + } + + // Wait all 8 threads finished. + for (auto &t : threads) { + t.wait(); + } + + // Count hash map elements. + bh_hash_map_traverse(test_hash_map, fun_count_elem, nullptr); + + EXPECT_EQ(200, COUNT_ELEM); + EXPECT_EQ(true, bh_hash_map_destroy(test_hash_map)); +} \ No newline at end of file diff --git a/tests/unit/shared-utils/bh_list_test.cc b/tests/unit/shared-utils/bh_list_test.cc new file mode 100644 index 0000000000..981c52f253 --- /dev/null +++ b/tests/unit/shared-utils/bh_list_test.cc @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" + +#include "test_helper.h" +#include "gtest/gtest.h" + +class bh_list_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(bh_list_test_suite, bh_list_init) +{ + bh_list list_test; + + // Normally. + EXPECT_EQ(BH_LIST_SUCCESS, bh_list_init(&list_test)); + + // Illegal parameters. + EXPECT_EQ(BH_LIST_ERROR, bh_list_init(nullptr)); +} + +TEST_F(bh_list_test_suite, bh_list_insert) +{ + bh_list list_test; + bh_list_link elem_insert; + + // Normally. + bh_list_init(&list_test); + EXPECT_EQ(BH_LIST_SUCCESS, bh_list_insert(&list_test, &elem_insert)); + + // Illegal parameters. + EXPECT_EQ(BH_LIST_ERROR, bh_list_insert(nullptr, nullptr)); + EXPECT_EQ(BH_LIST_ERROR, bh_list_insert(&list_test, nullptr)); +} + +TEST_F(bh_list_test_suite, bh_list_remove) +{ + bh_list list_test; + bh_list_link elem_insert_1; + bh_list_link elem_insert_2; + bh_list_link elem_insert_3; + bh_list_link elem_insert_4; + + // Normally. + bh_list_init(&list_test); + bh_list_insert(&list_test, &elem_insert_1); + bh_list_insert(&list_test, &elem_insert_2); + bh_list_insert(&list_test, &elem_insert_3); + bh_list_insert(&list_test, &elem_insert_4); + EXPECT_EQ(BH_LIST_SUCCESS, bh_list_remove(&list_test, &elem_insert_1)); + + // The elem specified by prameter is not in the list. + EXPECT_EQ(BH_LIST_ERROR, bh_list_remove(&list_test, &elem_insert_1)); + + // Illegal parameters. + EXPECT_EQ(BH_LIST_ERROR, bh_list_remove(&list_test, nullptr)); + EXPECT_EQ(BH_LIST_ERROR, bh_list_remove(nullptr, nullptr)); + EXPECT_EQ(BH_LIST_ERROR, bh_list_remove(nullptr, &elem_insert_1)); +} + +TEST_F(bh_list_test_suite, bh_list_length) +{ + bh_list list_test; + bh_list_link elem_insert_1; + bh_list_link elem_insert_2; + + bh_list_init(&list_test); + + // The length is 0. + EXPECT_EQ(0, bh_list_length(&list_test)); + + // The length is 2. + bh_list_insert(&list_test, &elem_insert_1); + bh_list_insert(&list_test, &elem_insert_2); + EXPECT_EQ(2, bh_list_length(&list_test)); + + // Illegal parameters. + EXPECT_EQ(0, bh_list_length(nullptr)); +} + +TEST_F(bh_list_test_suite, bh_list_first_elem) +{ + bh_list list_test; + bh_list_link elem_insert_1; + bh_list_link elem_insert_2; + + bh_list_init(&list_test); + + // There is no element in the list. + EXPECT_EQ(nullptr, bh_list_first_elem(&list_test)); + + // There are 2 elements in the list. + bh_list_insert(&list_test, &elem_insert_1); + bh_list_insert(&list_test, &elem_insert_2); + EXPECT_EQ(&elem_insert_2, bh_list_first_elem(&list_test)); + + // Illegal parameters. + EXPECT_EQ(nullptr, bh_list_first_elem(nullptr)); +} + +TEST_F(bh_list_test_suite, bh_list_elem_next) +{ + bh_list list_test; + bh_list_link elem_insert_1; + bh_list_link elem_insert_2; + + bh_list_init(&list_test); + bh_list_insert(&list_test, &elem_insert_1); + bh_list_insert(&list_test, &elem_insert_2); + + // Normally. + EXPECT_EQ(&elem_insert_1, bh_list_elem_next(&elem_insert_2)); + + // Illegal parameters. + EXPECT_EQ(nullptr, bh_list_elem_next(nullptr)); +} diff --git a/tests/unit/shared-utils/bh_log_test.cc b/tests/unit/shared-utils/bh_log_test.cc new file mode 100644 index 0000000000..250fb79268 --- /dev/null +++ b/tests/unit/shared-utils/bh_log_test.cc @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_log.h" +#include "stdio.h" + +class bh_log_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} +}; + +#define TEST_STR "This is a test." + +TEST_F(bh_log_test_suite, bh_log_set_verbose_level) +{ + bh_log_set_verbose_level(BH_LOG_LEVEL_DEBUG); +} + +TEST_F(bh_log_test_suite, bh_print_time) +{ + std::string captured; + + bh_log_set_verbose_level(BH_LOG_LEVEL_WARNING); + bh_print_time(TEST_STR); + + bh_log_set_verbose_level(BH_LOG_LEVEL_DEBUG); + testing::internal::CaptureStdout(); + bh_print_time(TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_EQ(0, strncmp(TEST_STR, captured.c_str(), strlen(TEST_STR))); + + testing::internal::CaptureStdout(); + bh_print_time(TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_EQ(0, strncmp(TEST_STR, captured.c_str(), strlen(TEST_STR))); +} + +TEST_F(bh_log_test_suite, bh_log) +{ + std::string captured; + + bh_log_set_verbose_level(BH_LOG_LEVEL_DEBUG); + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_FATAL, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, TEST_STR, captured); + + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_ERROR, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, TEST_STR, captured); + + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_WARNING, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, TEST_STR, captured); + + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_DEBUG, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, TEST_STR, captured); + + // log_verbose_level == BH_LOG_LEVEL_DEBUG, so BH_LOG_LEVEL_VERBOSE is not + // printed. + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_VERBOSE, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_EQ(nullptr, strstr(captured.c_str(), TEST_STR)); + + // After set log_verbose_level = BH_LOG_LEVEL_VERBOSE, BH_LOG_LEVEL_VERBOSE + // can be printed. + bh_log_set_verbose_level(BH_LOG_LEVEL_VERBOSE); + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_VERBOSE, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, TEST_STR, captured); +} diff --git a/tests/unit/shared-utils/bh_queue_test.cc b/tests/unit/shared-utils/bh_queue_test.cc new file mode 100644 index 0000000000..c540d8f36c --- /dev/null +++ b/tests/unit/shared-utils/bh_queue_test.cc @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_platform.h" + +class bh_queue_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +typedef struct bh_queue_node { + struct bh_queue_node *next; + struct bh_queue_node *prev; + unsigned short tag; + unsigned int len; + void *body; + bh_msg_cleaner msg_cleaner; +} bh_queue_node; + +struct bh_queue { + bh_queue_mutex queue_lock; + bh_queue_cond queue_wait_cond; + unsigned int cnt; + unsigned int max; + unsigned int drops; + bh_queue_node *head; + bh_queue_node *tail; + + bool exit_loop_run; +}; + +typedef enum LINK_MSG_TYPE { + COAP_TCP_RAW = 0, + COAP_UDP_RAW = 1, + REQUEST_PACKET, + RESPONSE_PACKET, + INSTALL_WASM_APP, + CBOR_GENERIC = 30, + + LINK_MSG_TYPE_MAX = 50 +} LINK_MSG_TYPE; + +typedef enum QUEUE_MSG_TYPE { + COAP_PARSED = LINK_MSG_TYPE_MAX + 1, + RESTFUL_REQUEST, + RESTFUL_RESPONSE, + TIMER_EVENT = 5, + SENSOR_EVENT = 6, + GPIO_INTERRUPT_EVENT = 7, + BLE_EVENT = 8, + JDWP_REQUEST = 9, + WD_TIMEOUT = 10, + BASE_EVENT_MAX = 100 + +} QUEUE_MSG_TYPE; + +enum { + WASM_Msg_Start = BASE_EVENT_MAX, + TIMER_EVENT_WASM, + SENSOR_EVENT_WASM, + CONNECTION_EVENT_WASM, + WIDGET_EVENT_WASM, + WASM_Msg_End = WASM_Msg_Start + 100 +}; + +// If RES_CMP == 1, the function bh_queue_enter_loop_run run error. +int RES_CMP = 0; + +TEST_F(bh_queue_test_suite, bh_queue_create) +{ + EXPECT_NE(nullptr, bh_queue_create()); +} + +TEST_F(bh_queue_test_suite, bh_queue_destroy) +{ + bh_message_t msg_ptr; + bh_queue *queue_ptr = bh_queue_create(); + + // Normally. + msg_ptr = bh_new_msg(RESTFUL_REQUEST, nullptr, 0, nullptr); + bh_post_msg2(queue_ptr, msg_ptr); + bh_queue_destroy(queue_ptr); + EXPECT_EQ(nullptr, queue_ptr->head); + + // Illegal parameters. + bh_queue_destroy(nullptr); +} + +TEST_F(bh_queue_test_suite, bh_message_payload) +{ + bh_message_t msg_ptr; + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + EXPECT_EQ("test_msg_body", bh_message_payload(msg_ptr)); +} + +TEST_F(bh_queue_test_suite, bh_message_payload_len) +{ + bh_message_t msg_ptr; + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + EXPECT_EQ(sizeof("test_msg_body"), bh_message_payload_len(msg_ptr)); +} + +TEST_F(bh_queue_test_suite, bh_message_type) +{ + bh_message_t msg_ptr; + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + EXPECT_EQ(RESTFUL_REQUEST, bh_message_type(msg_ptr)); +} + +TEST_F(bh_queue_test_suite, bh_new_msg) +{ + EXPECT_NE(nullptr, bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr)); +} + +void +msg_cleaner_test(void *) +{ + return; +} + +TEST_F(bh_queue_test_suite, bh_free_msg) +{ + bh_message_t msg_ptr; + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), (void *)msg_cleaner_test); + bh_free_msg(msg_ptr); + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + bh_free_msg(msg_ptr); + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)(uintptr_t)100, 0, nullptr); + bh_free_msg(msg_ptr); +} + +TEST_F(bh_queue_test_suite, bh_post_msg) +{ + int i = 0; + bh_queue *queue_ptr = bh_queue_create(); + bh_message_t msg_ptr; + + EXPECT_EQ(true, bh_post_msg(queue_ptr, TIMER_EVENT_WASM, nullptr, 0)); + EXPECT_EQ(1, queue_ptr->cnt); + + // queue_ptr->cnt >= queue_ptr->max. + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + for (i = 1; i <= 50; i++) { + bh_post_msg2(queue_ptr, msg_ptr); + } + EXPECT_EQ(false, bh_post_msg(queue_ptr, TIMER_EVENT_WASM, nullptr, 0)); +} + +TEST_F(bh_queue_test_suite, bh_post_msg2) +{ + bh_message_t msg_ptr; + bh_queue *queue_ptr = bh_queue_create(); + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, nullptr, 0, nullptr); + EXPECT_EQ(true, bh_post_msg2(queue_ptr, msg_ptr)); + EXPECT_EQ(1, queue_ptr->cnt); +} + +TEST_F(bh_queue_test_suite, bh_get_msg) +{ + bh_message_t msg_ptr; + bh_queue *queue_ptr = bh_queue_create(); + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + + // queue->cnt == 0, timeout_us == 0. + EXPECT_EQ(nullptr, bh_get_msg(queue_ptr, 0)); + // queue->cnt == 0, timeout_us != 0. + bh_get_msg(queue_ptr, 1); + + bh_post_msg2(queue_ptr, msg_ptr); + EXPECT_EQ(1, queue_ptr->cnt); + bh_get_msg(queue_ptr, -1); + EXPECT_EQ(0, queue_ptr->cnt); +} + +TEST_F(bh_queue_test_suite, bh_queue_get_message_count) +{ + int i = 0, j = 0; + bh_message_t msg_ptr; + bh_queue *queue_ptr = bh_queue_create(); + + // Normally. + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + for (i = 1; i <= 20; i++) { + bh_post_msg2(queue_ptr, msg_ptr); + } + i = i - 1; + // The count of msg is less than queue_ptr->max. + EXPECT_EQ(i, bh_queue_get_message_count(queue_ptr)); + + // The count of msg is more than queue_ptr->max. + for (j = 1; j <= 60; j++) { + bh_post_msg2(queue_ptr, msg_ptr); + } + j = j - 1; + EXPECT_EQ(queue_ptr->max, bh_queue_get_message_count(queue_ptr)); + EXPECT_EQ(j + i - queue_ptr->max, queue_ptr->drops); + + // Illegal parameters. + EXPECT_EQ(0, bh_queue_get_message_count(nullptr)); +} + +void +bh_queue_enter_loop_run_test_fun(void *message, void *arg) +{ + static int count = 0; + RES_CMP = + strncmp("test_queue_loop", (char *)((bh_message_t)message)->body, 15); + + count++; + if (2 == count) { + bh_queue_exit_loop_run((bh_queue *)arg); + } +} + +TEST_F(bh_queue_test_suite, bh_queue_enter_loop_run) +{ + bh_queue *queue_ptr = bh_queue_create(); + bh_message_t msg_ptr1 = + bh_new_msg(RESTFUL_REQUEST, (void *)"test_queue_loop", + sizeof("test_queue_loop"), nullptr); + bh_message_t msg_ptr2 = + bh_new_msg(RESTFUL_REQUEST, (void *)"test_queue_loop", + sizeof("test_queue_loop"), nullptr); + + bh_post_msg2(queue_ptr, msg_ptr1); + bh_post_msg2(queue_ptr, msg_ptr2); + bh_queue_enter_loop_run(queue_ptr, bh_queue_enter_loop_run_test_fun, + queue_ptr); + EXPECT_EQ(0, RES_CMP); + + // Illegal parameters. + bh_queue_enter_loop_run(nullptr, bh_queue_enter_loop_run_test_fun, + queue_ptr); +} + +TEST_F(bh_queue_test_suite, bh_queue_exit_loop_run) +{ + // Illegal parameters. + bh_queue_exit_loop_run(nullptr); +} \ No newline at end of file diff --git a/tests/unit/shared-utils/bh_vector_test.cc b/tests/unit/shared-utils/bh_vector_test.cc new file mode 100644 index 0000000000..3da9fba5d7 --- /dev/null +++ b/tests/unit/shared-utils/bh_vector_test.cc @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" +#include "bh_platform.h" + +#include + +class bh_vector_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +static inline void * +malloc_internal(uint64 size); + +TEST_F(bh_vector_test_suite, bh_vector_init) +{ + Vector *vector_ptr = nullptr; + + // Normally. use_lock is true. + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + EXPECT_EQ(true, bh_vector_init(vector_ptr, 6, sizeof(Vector *), true)); + // use_lock is false. + EXPECT_EQ(true, bh_vector_init(vector_ptr, 6, sizeof(Vector *), false)); + // init_length == 0. + EXPECT_EQ(true, bh_vector_init(vector_ptr, 0, sizeof(Vector *), false)); + // size_elem > UINT32_MAX. + EXPECT_EQ(true, bh_vector_init(vector_ptr, 6, UINT32_MAX + 1, false)); + // init_length > UINT32_MAX. + EXPECT_EQ(true, bh_vector_init(vector_ptr, UINT32_MAX + 1, sizeof(Vector *), + false)); + + // Illegal parameters. + EXPECT_EQ(false, bh_vector_init(nullptr, 6, sizeof(Vector *), true)); +} + +TEST_F(bh_vector_test_suite, bh_vector_set) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, "test"); + + // Normally. use_lock is true. + EXPECT_EQ(true, bh_vector_set(vector_ptr, 0, elem_buf)); + + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_set(nullptr, 0, nullptr)); + EXPECT_EQ(false, bh_vector_set(vector_ptr, 0, nullptr)); + // Illegal parameters: index >= vector->num_elems. + EXPECT_EQ(false, bh_vector_set(vector_ptr, 1, elem_buf)); + + // Normally. use_lock is false. + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), false); + bh_vector_append(vector_ptr, "test"); + EXPECT_EQ(true, bh_vector_set(vector_ptr, 0, elem_buf)); +} + +TEST_F(bh_vector_test_suite, bh_vector_get) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + char get_elem[12] = { 0 }; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, elem_buf); + + // Normally. use_lock is true. + EXPECT_EQ(true, bh_vector_get(vector_ptr, 0, get_elem)); + EXPECT_EQ(0, strncmp(elem_buf, get_elem, 11)); + + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_get(nullptr, 0, nullptr)); + EXPECT_EQ(false, bh_vector_get(vector_ptr, 0, nullptr)); + // Illegal parameters: index >= vector->num_elems. + EXPECT_EQ(false, bh_vector_get(vector_ptr, 1, get_elem)); + + // Normally. use_lock is false. + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), false); + bh_vector_append(vector_ptr, elem_buf); + EXPECT_EQ(true, bh_vector_get(vector_ptr, 0, get_elem)); + EXPECT_EQ(0, strncmp(elem_buf, get_elem, 11)); +} + +TEST_F(bh_vector_test_suite, bh_vector_insert) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + char get_elem[12] = { 0 }; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, "test"); + bh_vector_append(vector_ptr, "test"); + bh_vector_append(vector_ptr, "test"); + bh_vector_append(vector_ptr, "test"); + + // Normally. + EXPECT_EQ(true, bh_vector_insert(vector_ptr, 0, elem_buf)); + bh_vector_get(vector_ptr, 1, get_elem); + EXPECT_EQ(0, strncmp(elem_buf, get_elem, 11)); + + EXPECT_EQ(true, bh_vector_insert(vector_ptr, 2, elem_buf)); + EXPECT_EQ(true, bh_vector_insert(vector_ptr, 5, elem_buf)); + + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_insert(nullptr, 0, nullptr)); + EXPECT_EQ(false, bh_vector_insert(vector_ptr, 0, nullptr)); + EXPECT_EQ(0, strncmp(elem_buf, get_elem, 0)); + // Illegal parameters: index >= vector->num_elems. + EXPECT_EQ(false, bh_vector_insert(vector_ptr, 10, elem_buf)); + + // "if (!extend_vector(vector, vector->num_elems + 1))" == true. + vector_ptr->num_elems = UINT32_MAX + 1; + EXPECT_EQ(false, bh_vector_insert(vector_ptr, 2, elem_buf)); + + // use_lock is false. + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), false); + bh_vector_append(vector_ptr, "test"); + EXPECT_EQ(true, bh_vector_insert(vector_ptr, 0, elem_buf)); +} + +TEST_F(bh_vector_test_suite, bh_vector_append) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + char get_elem[12] = { 0 }; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + + // Normally. + EXPECT_EQ(true, bh_vector_append(vector_ptr, elem_buf)); + bh_vector_get(vector_ptr, 0, get_elem); + EXPECT_EQ(0, strncmp(elem_buf, get_elem, 11)); + + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_append(nullptr, nullptr)); + EXPECT_EQ(false, bh_vector_append(vector_ptr, nullptr)); +} + +TEST_F(bh_vector_test_suite, bh_vector_remove) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + char old_elem[12] = { 0 }; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, elem_buf); + bh_vector_append(vector_ptr, elem_buf); + bh_vector_append(vector_ptr, elem_buf); + bh_vector_append(vector_ptr, elem_buf); + + // Normally. + // Remove the first one. + EXPECT_EQ(true, bh_vector_remove(vector_ptr, 0, old_elem)); + // Remove the middle one. + EXPECT_EQ(true, bh_vector_remove(vector_ptr, 2, old_elem)); + // Remove the last one. + EXPECT_EQ(true, bh_vector_remove(vector_ptr, 1, old_elem)); + + EXPECT_EQ(true, bh_vector_remove(vector_ptr, 0, nullptr)); + + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_remove(nullptr, 0, nullptr)); + EXPECT_EQ(false, bh_vector_remove(vector_ptr, 0, nullptr)); + // Illegal parameters: index >= vector->num_elems. + EXPECT_EQ(false, bh_vector_remove(vector_ptr, 1, old_elem)); + + // use_lock is false. + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), false); + bh_vector_append(vector_ptr, elem_buf); + EXPECT_EQ(true, bh_vector_remove(vector_ptr, 0, old_elem)); +} + +TEST_F(bh_vector_test_suite, bh_vector_size) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, elem_buf); + + EXPECT_EQ(1, bh_vector_size(vector_ptr)); + EXPECT_EQ(0, bh_vector_size(nullptr)); +} + +TEST_F(bh_vector_test_suite, bh_vector_destroy) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, elem_buf); + + // Normally. + EXPECT_EQ(true, bh_vector_destroy(vector_ptr)); + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_destroy(nullptr)); + + // use_lock is false. + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), false); + bh_vector_append(vector_ptr, elem_buf); + EXPECT_EQ(true, bh_vector_destroy(vector_ptr)); +} + +TEST_F(bh_vector_test_suite, bh_vector_thread_safety) +{ + Vector *vector_ptr = nullptr; + char elem; + int32_t i = 0; + std::vector> threads; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem), true); + + for (i = 0; i < 8; i++) { + threads.push_back(std::async([&] { + for (int j = 0; j < 25; j++) { + bh_vector_append(vector_ptr, (void *)&elem); + } + })); + } + + for (auto &t : threads) { + t.wait(); + } + + EXPECT_EQ(bh_vector_size(vector_ptr), 200); + + // Normally. + EXPECT_EQ(true, bh_vector_destroy(vector_ptr)); +} diff --git a/tests/unit/shared-utils/shared_utils_test.cc b/tests/unit/shared-utils/shared_utils_test.cc new file mode 100644 index 0000000000..82bedf32fa --- /dev/null +++ b/tests/unit/shared-utils/shared_utils_test.cc @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" +#include "test_helper.h" +#include "gtest/gtest.h" + +/* Test APIs under wamr/core/shared/utils */ + +class SharedUtilsTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(SharedUtilsTest, bh_list) {} diff --git a/tests/unit/tid-allocator/CMakeLists.txt b/tests/unit/tid-allocator/CMakeLists.txt new file mode 100644 index 0000000000..be62340a3c --- /dev/null +++ b/tests/unit/tid-allocator/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) + +project (tid_allocator_tests) + +if (NOT DEFINED WAMR_BUILD_LIB_WASI_THREADS) + set (WAMR_BUILD_LIB_WASI_THREADS 1) +endif () + +if (NOT DEFINED WAMR_BUILD_INTERP) + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_PLATFORM) + string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +endif () + +include (../unit_common.cmake) + +add_library (tid_allocator_vmlib ${WAMR_RUNTIME_LIB_SOURCE}) +add_library (wamr_gtest_main main.cpp) +target_link_libraries (wamr_gtest_main PUBLIC gtest tid_allocator_vmlib) + +function (create_wamr_unit_test test_name) + set (sources ${ARGN}) + add_executable (${test_name} ${sources}) + target_link_libraries ( + ${test_name} + wamr_gtest_main + tid_allocator_vmlib + ${LLVM_AVAILABLE_LIBS} + ) + gtest_discover_tests (${test_name}) + endfunction () + +include (${IWASM_DIR}/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake) + diff --git a/tests/unit/main.cpp b/tests/unit/tid-allocator/main.cpp similarity index 99% rename from tests/unit/main.cpp rename to tests/unit/tid-allocator/main.cpp index 63695d9ee7..081676a1b9 100644 --- a/tests/unit/main.cpp +++ b/tests/unit/tid-allocator/main.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ + #include #include "wasm_runtime_common.h" diff --git a/tests/unit/unit_common.cmake b/tests/unit/unit_common.cmake new file mode 100644 index 0000000000..90ea2eb7cd --- /dev/null +++ b/tests/unit/unit_common.cmake @@ -0,0 +1,105 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +if (NOT DEFINED WAMR_BUILD_PLATFORM) + set (WAMR_BUILD_PLATFORM "linux") +endif () + +set (UNIT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}) + +include_directories(${UNIT_ROOT_DIR}) + +enable_language (ASM) + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Debug) +endif () + +if (NOT DEFINED WAMR_BUILD_INTERP) + # Enable Interpreter by default + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_AOT) + # Enable AOT by default. + set (WAMR_BUILD_AOT 1) +endif () + +if (NOT DEFINED WAMR_BUILD_JIT) + # Disable JIT by default. + set (WAMR_BUILD_JIT 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) + # Enable libc builtin support by default + set (WAMR_BUILD_LIBC_BUILTIN 1) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_WASI) + # Enable libc wasi support by default + set (WAMR_BUILD_LIBC_WASI 1) +endif () + +if (NOT DEFINED WAMR_BUILD_MULTI_MODULE) + set (WAMR_BUILD_MULTI_MODULE 1) +endif() + +if (NOT DEFINED WAMR_BUILD_APP_FRAMEWORK) + set (WAMR_BUILD_APP_FRAMEWORK 1) +endif () + +if (COLLECT_CODE_COVERAGE EQUAL 1) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") +endif () + +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -ffunction-sections -fdata-sections \ + -Wall -Wno-unused-parameter -Wno-pedantic") + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) + +# include the build config template file +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +include_directories (${SHARED_DIR}/include + ${IWASM_DIR}/include) + +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +if (NOT (GOOGLETEST_INCLUDED EQUAL 1)) +# Prevent overriding the parent project's compiler/linker +# settings on Windows +set (gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +# Fetch Google test +include (FetchContent) +FetchContent_Declare ( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) +FetchContent_MakeAvailable (googletest) + +endif() + +# Add helper classes +include_directories(${CMAKE_CURRENT_LIST_DIR}/common) + +message ("unit_common.cmake included") + diff --git a/tests/unit/wasm-c-api/CMakeLists.txt b/tests/unit/wasm-c-api/CMakeLists.txt new file mode 100644 index 0000000000..3b8884e111 --- /dev/null +++ b/tests/unit/wasm-c-api/CMakeLists.txt @@ -0,0 +1,62 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 2.9) +project (wasm_c_api_test) + +################ runtime settings ################ +set(CMAKE_BUILD_TYPE Debug) +set(WAMR_BUILD_PLATFORM "linux") + +# Resetdefault linker flags +set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# WAMR features switch +set(WAMR_BUILD_TARGET "X86_64") +set(WAMR_BUILD_INTERP 1) +set(WAMR_BUILD_AOT 0) +set(WAMR_BUILD_JIT 0) +set(WAMR_BUILD_LIBC_BUILTIN 1) +set(WAMR_BUILD_LIBC_WASI 0) +set(WAMR_BUILD_FAST_INTERP 0) + +# compiling and linking flags +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -pie -fPIE") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security -mindirect-branch-register") + +# build out vmlib +# hard code path here +set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..) +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +add_library(vmlib STATIC ${WAMR_RUNTIME_LIB_SOURCE}) +################################################ + +################ unit test related ################ +# Add googletest directly to our build. This defines +# the gtest and gtest_main targets. + +if (NOT (GOOGLETEST_INCLUDED EQUAL 1)) +# Prevent overriding the parent project's compiler/linker +# settings on Windows +set (gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +# Fetch Google test +include (FetchContent) +FetchContent_Declare ( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) +FetchContent_MakeAvailable (googletest) +endif() + +enable_testing() + +add_executable(wasm_c_api_test + basic.cc +) + +target_link_libraries(wasm_c_api_test vmlib gtest_main) + +gtest_discover_tests(wasm_c_api_test) diff --git a/tests/unit/wasm-c-api/basic.cc b/tests/unit/wasm-c-api/basic.cc new file mode 100644 index 0000000000..34d837dd92 --- /dev/null +++ b/tests/unit/wasm-c-api/basic.cc @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +#include "bh_platform.h" +#include "wasm_c_api.h" +#include "wasm_c_api_internal.h" + +#ifndef own +#define own +#endif + +class CApiTests : public ::testing::Test +{ + protected: + void SetUp() + { + bh_log_set_verbose_level(5); + engine = nullptr; + engine = wasm_engine_new(); + ASSERT_NE(nullptr, engine); + } + + void TearDown() { wasm_engine_delete(engine); } + + wasm_engine_t *engine; +}; + +TEST_F(CApiTests, empty) {} + +TEST_F(CApiTests, wasm_engine_t) +{ + wasm_engine_t *engine1 = wasm_engine_new(); + wasm_engine_t *engine2 = wasm_engine_new(); + EXPECT_EQ(engine1, engine2); + /* TearDown() will delete it */ +} + +TEST_F(CApiTests, wasm_store_t) +{ + wasm_engine_t *engine = wasm_engine_new(); + wasm_store_t *store1 = wasm_store_new(engine); + EXPECT_NE(nullptr, store1); + EXPECT_NE(nullptr, store1->modules->data); + + wasm_store_t *store2 = wasm_store_new(engine); + EXPECT_NE(store1, store2); + EXPECT_NE(store1->modules->data, store2->modules->data); + + wasm_store_delete(store1); + wasm_store_delete(store2); + + store1 = wasm_store_new(engine); + EXPECT_NE(nullptr, store1); + wasm_store_delete(store1); +} + +TEST_F(CApiTests, wasm_byte_vec_t) +{ + wasm_byte_vec_t byte_vec = { 0 }; + wasm_byte_vec_new_uninitialized(&byte_vec, 10); + EXPECT_NE(nullptr, byte_vec.data); + EXPECT_EQ(10, byte_vec.size); + + byte_vec.data[0] = (wasm_byte_t)'a'; + byte_vec.data[1] = (wasm_byte_t)'b'; + byte_vec.data[2] = (wasm_byte_t)'c'; + EXPECT_STREQ("abc", (char *)byte_vec.data); + + byte_vec.data[5] = (wasm_byte_t)'d'; + byte_vec.data[6] = (wasm_byte_t)'e'; + byte_vec.data[7] = (wasm_byte_t)'f'; + EXPECT_STREQ("def", (char *)(byte_vec.data + 5)); + + wasm_byte_vec_delete(&byte_vec); + EXPECT_EQ(nullptr, byte_vec.data); + EXPECT_EQ(0, byte_vec.size); +} + +TEST_F(CApiTests, wasm_valtype_vec_t) +{ + wasm_valtype_vec_t tuple1 = { 0 }; + wasm_valtype_vec_new_uninitialized(&tuple1, 128); + EXPECT_NE(nullptr, tuple1.data); + EXPECT_EQ(128, tuple1.size); + + wasm_valtype_t *val_type_1 = wasm_valtype_new_i32(); + tuple1.data[0] = val_type_1; + EXPECT_EQ(WASM_I32, wasm_valtype_kind(*(tuple1.data + 0))); + wasm_valtype_vec_delete(&tuple1); + wasm_valtype_delete(val_type_1); + + wasm_valtype_t *val_types[5] = { + wasm_valtype_new_i32(), wasm_valtype_new_i64(), wasm_valtype_new_f32(), + wasm_valtype_new_f64(), wasm_valtype_new_funcref() + }; + + wasm_valtype_vec_t tuple2 = { 0 }; + wasm_valtype_vec_new(&tuple2, 5, val_types); + EXPECT_NE(nullptr, tuple2.data); + EXPECT_EQ(WASM_F32, wasm_valtype_kind(*(tuple2.data + 2))); + EXPECT_EQ(WASM_FUNCREF, wasm_valtype_kind(*(tuple2.data + 4))); + + wasm_valtype_vec_t tuple3 = { 0 }; + wasm_valtype_vec_copy(&tuple3, &tuple2); + + wasm_valtype_vec_delete(&tuple2); + + EXPECT_EQ(WASM_I64, wasm_valtype_kind(*(tuple3.data + 1))); + EXPECT_EQ(WASM_F64, wasm_valtype_kind(*(tuple3.data + 3))); + wasm_valtype_vec_delete(&tuple3); +} + +TEST_F(CApiTests, wasm_functype_t) +{ + wasm_functype_t *callback_type = wasm_functype_new_1_1( + wasm_valtype_new(WASM_EXTERNREF), wasm_valtype_new(WASM_FUNCREF)); + EXPECT_EQ(WASM_EXTERNREF, + wasm_valtype_kind(*(wasm_functype_params(callback_type)->data))); + wasm_functype_delete(callback_type); + + callback_type = wasm_functype_new_0_0(); + wasm_functype_delete(callback_type); + + callback_type = wasm_functype_new_0_1(wasm_valtype_new(WASM_EXTERNREF)); + const wasm_valtype_vec_t *results = wasm_functype_results(callback_type); + EXPECT_EQ(WASM_EXTERNREF, wasm_valtype_kind(*(results->data))); + wasm_functype_delete(callback_type); + + callback_type = wasm_functype_new_1_0(wasm_valtype_new(WASM_EXTERNREF)); + EXPECT_EQ(WASM_EXTERNREF, + wasm_valtype_kind(*(wasm_functype_params(callback_type)->data))); + wasm_functype_delete(callback_type); + + wasm_functype_t *func_type1 = wasm_functype_new_2_2( + wasm_valtype_new(WASM_I32), wasm_valtype_new(WASM_I64), + wasm_valtype_new(WASM_I32), wasm_valtype_new(WASM_I64)); + wasm_functype_t *func_type2 = wasm_functype_copy(func_type1); + wasm_functype_delete(func_type1); + + EXPECT_EQ(WASM_I64, wasm_valtype_kind( + *(wasm_functype_results(func_type2)->data + 1))); + wasm_functype_delete(func_type2); +} + +TEST_F(CApiTests, wasm_globaltype_t) +{ + wasm_globaltype_t *const_f32_type = + wasm_globaltype_new(wasm_valtype_new(WASM_F32), WASM_CONST); + EXPECT_EQ(WASM_F32, + wasm_valtype_kind(wasm_globaltype_content(const_f32_type))); + + wasm_globaltype_t *cloned = wasm_globaltype_copy(const_f32_type); + wasm_globaltype_delete(const_f32_type); + + EXPECT_EQ(WASM_F32, wasm_valtype_kind(wasm_globaltype_content(cloned))); + + wasm_globaltype_delete(cloned); +} + +static wasm_trap_t * +test_func(const wasm_val_vec_t *args, own wasm_val_vec_t *results) +{ + return NULL; +} + +TEST_F(CApiTests, wasm_func_t) +{ + wasm_valtype_t *types[4] = { wasm_valtype_new_i32(), wasm_valtype_new_i64(), + wasm_valtype_new_i64(), + wasm_valtype_new_i32() }; + wasm_valtype_vec_t tuple1 = { 0 }, tuple2 = { 0 }; + wasm_valtype_vec_new(&tuple1, 4, types); + wasm_valtype_vec_copy(&tuple2, &tuple1); + wasm_functype_t *callback_type = wasm_functype_new(&tuple1, &tuple2); + + wasm_store_t *store = wasm_store_new(engine); + wasm_func_t *callback_func = wasm_func_new(store, callback_type, test_func); + wasm_functype_delete(callback_type); + + callback_type = callback_func->type; + EXPECT_EQ(WASM_I32, wasm_valtype_kind( + *(wasm_functype_params(callback_type)->data + 0))); + EXPECT_EQ(WASM_I32, wasm_valtype_kind( + *(wasm_functype_results(callback_type)->data + 3))); + wasm_func_delete(callback_func); + wasm_store_delete(store); +} diff --git a/tests/unit/wasm-c-api/run.sh b/tests/unit/wasm-c-api/run.sh new file mode 100755 index 0000000000..1b0d88e367 --- /dev/null +++ b/tests/unit/wasm-c-api/run.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# ./c_api_unit_test --gtest_list_tests + +function run_one() +{ + local case=$1 + valgrind --tool=memcheck --leak-check=yes -v \ + ./c_api_unit_test --gtest_filter=CApiTests.${case} +} + +function run() +{ + valgrind --tool=memcheck --leak-check=yes -v \ + ./c_api_unit_test +} + +[[ $# -gt 0 ]] && $@ || run diff --git a/tests/unit/wasm-vm/.gitignore b/tests/unit/wasm-vm/.gitignore new file mode 100644 index 0000000000..aa3883989b --- /dev/null +++ b/tests/unit/wasm-vm/.gitignore @@ -0,0 +1,2 @@ +wasm-apps/app[123]/*.wat +wasm-apps/app[123]/*.wasm \ No newline at end of file diff --git a/tests/unit/wasm-vm/CMakeLists.txt b/tests/unit/wasm-vm/CMakeLists.txt new file mode 100644 index 0000000000..d13d65aac5 --- /dev/null +++ b/tests/unit/wasm-vm/CMakeLists.txt @@ -0,0 +1,53 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-wasm-vm) + +add_definitions (-DRUN_ON_LINUX) + +add_definitions (-Dattr_container_malloc=malloc) +add_definitions (-Dattr_container_free=free) + +set (WAMR_BUILD_APP_FRAMEWORK 1) +set (CMAKE_BUILD_TYPE Release) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${LIB_HOST_AGENT_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${LIBC_WASI_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} + ${UNCOMMON_SHARED_SOURCE} + ) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable(wasm_vm_test ${unit_test_sources}) + +target_link_libraries(wasm_vm_test ${LLVM_AVAILABLE_LIBS} gtest_main) + +add_custom_command(TARGET wasm_vm_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps/app4/*.wasm + ${PROJECT_BINARY_DIR}/ + COMMENT "Copy wasm files to the output directory" +) + +gtest_discover_tests(wasm_vm_test) diff --git a/tests/unit/wasm-vm/wasm-apps/app1.wast b/tests/unit/wasm-vm/wasm-apps/app1.wast new file mode 100644 index 0000000000..aea3a87928 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app1.wast @@ -0,0 +1,106 @@ +(module + (type $0 (func (param i32) (result i32))) + (type $1 (func (param i32 i32) (result i32))) + (type $2 (func (param i32))) + (type $3 (func (param i32 i32 i32) (result i32))) + (type $4 (func)) + (type $5 (func (result i32))) + (import "env" "malloc" (func $13 (param i32) (result i32))) + (import "env" "calloc" (func $14 (param i32 i32) (result i32))) + (import "env" "free" (func $15 (param i32))) + (import "env" "memcpy" (func $16 (param i32 i32 i32) (result i32))) + (import "env" "strdup" (func $17 (param i32) (result i32))) + (memory $6 1) + (global $7 i32 (i32.const 1024)) + (global $8 i32 (i32.const 1024)) + (global $9 i32 (i32.const 1024)) + (global $10 i32 (i32.const 5120)) + (global $11 i32 (i32.const 0)) + (global $12 i32 (i32.const 1)) + (export "memory" (memory $6)) + (export "__wasm_call_ctors" (func $18)) + (export "on_init" (func $18)) + (export "my_sqrt" (func $19)) + (export "null_pointer" (func $20)) + (export "my_malloc" (func $21)) + (export "my_calloc" (func $22)) + (export "my_free" (func $23)) + (export "my_memcpy" (func $24)) + (export "my_strdup" (func $25)) + (export "__dso_handle" (global $7)) + (export "__data_end" (global $8)) + (export "__global_base" (global $9)) + (export "__heap_base" (global $10)) + (export "__memory_base" (global $11)) + (export "__table_base" (global $12)) + + (func $18 (type $4) + nop + ) + + (func $19 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $1 + local.get $1 + i32.mul + local.get $0 + local.get $0 + i32.mul + i32.add + ) + + (func $20 (type $5) + (result i32) + i32.const 0 + ) + + (func $21 (type $0) + (param $0 i32) + (result i32) + local.get $0 + call $13 + ) + + (func $22 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $0 + local.get $1 + call $14 + ) + + (func $23 (type $2) + (param $0 i32) + local.get $0 + call $15 + ) + + (func $24 (type $3) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $16 + ) + + (func $25 (type $0) + (param $0 i32) + (result i32) + local.get $0 + call $17 + ) + + ;;(custom_section "producers" + ;; (after code) + ;; "\01\0cprocessed-by\01\05clangV11.0.0 (ht" + ;; "tps://github.com/llvm/llvm-proje" + ;; "ct 176249bd6732a8044d457092ed932" + ;; "768724a6f06)") + + ) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/app1/main.c b/tests/unit/wasm-vm/wasm-apps/app1/main.c new file mode 100644 index 0000000000..0090d105fd --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app1/main.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include + +void +on_init() +{} + +int +my_sqrt(int x, int y) +{ + return x * x + y * y; +} + +void * +null_pointer() +{ + void *ptr = NULL; + return ptr; +} + +void * +my_malloc(int size) +{ + return malloc(size); +} + +void * +my_calloc(int nmemb, int size) +{ + return calloc(nmemb, size); +} + +void +my_free(void *ptr) +{ + return free(ptr); +} + +void * +my_memcpy(void *dst, void *src, int size) +{ + return memcpy(dst, src, size); +} + +char * +my_strdup(const char *s) +{ + return strdup(s); +} diff --git a/tests/unit/wasm-vm/wasm-apps/app1_wasm.h b/tests/unit/wasm-vm/wasm-apps/app1_wasm.h new file mode 100644 index 0000000000..2b20b39f9a --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app1_wasm.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +unsigned char app1_wasm[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x1E, 0x06, 0x60, + 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x01, + 0x7F, 0x00, 0x60, 0x03, 0x7F, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x01, 0x7F, 0x02, 0x40, 0x05, 0x03, 0x65, 0x6E, 0x76, 0x06, + 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, + 0x06, 0x63, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x01, 0x03, 0x65, 0x6E, + 0x76, 0x04, 0x66, 0x72, 0x65, 0x65, 0x00, 0x02, 0x03, 0x65, 0x6E, 0x76, + 0x06, 0x6D, 0x65, 0x6D, 0x63, 0x70, 0x79, 0x00, 0x03, 0x03, 0x65, 0x6E, + 0x76, 0x06, 0x73, 0x74, 0x72, 0x64, 0x75, 0x70, 0x00, 0x00, 0x03, 0x09, + 0x08, 0x04, 0x01, 0x05, 0x00, 0x01, 0x02, 0x03, 0x00, 0x05, 0x03, 0x01, + 0x00, 0x01, 0x06, 0x23, 0x06, 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, + 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, + 0x00, 0x41, 0x80, 0x28, 0x0B, 0x7F, 0x00, 0x41, 0x00, 0x0B, 0x7F, 0x00, + 0x41, 0x01, 0x0B, 0x07, 0xD4, 0x01, 0x10, 0x06, 0x6D, 0x65, 0x6D, 0x6F, + 0x72, 0x79, 0x02, 0x00, 0x11, 0x5F, 0x5F, 0x77, 0x61, 0x73, 0x6D, 0x5F, + 0x63, 0x61, 0x6C, 0x6C, 0x5F, 0x63, 0x74, 0x6F, 0x72, 0x73, 0x00, 0x05, + 0x07, 0x6F, 0x6E, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x00, 0x05, 0x07, 0x6D, + 0x79, 0x5F, 0x73, 0x71, 0x72, 0x74, 0x00, 0x06, 0x0C, 0x6E, 0x75, 0x6C, + 0x6C, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x00, 0x07, 0x09, + 0x6D, 0x79, 0x5F, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x08, 0x09, + 0x6D, 0x79, 0x5F, 0x63, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x09, 0x07, + 0x6D, 0x79, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x00, 0x0A, 0x09, 0x6D, 0x79, + 0x5F, 0x6D, 0x65, 0x6D, 0x63, 0x70, 0x79, 0x00, 0x0B, 0x09, 0x6D, 0x79, + 0x5F, 0x73, 0x74, 0x72, 0x64, 0x75, 0x70, 0x00, 0x0C, 0x0C, 0x5F, 0x5F, + 0x64, 0x73, 0x6F, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x03, 0x00, + 0x0A, 0x5F, 0x5F, 0x64, 0x61, 0x74, 0x61, 0x5F, 0x65, 0x6E, 0x64, 0x03, + 0x01, 0x0D, 0x5F, 0x5F, 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x5F, 0x62, + 0x61, 0x73, 0x65, 0x03, 0x02, 0x0B, 0x5F, 0x5F, 0x68, 0x65, 0x61, 0x70, + 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x03, 0x0D, 0x5F, 0x5F, 0x6D, 0x65, + 0x6D, 0x6F, 0x72, 0x79, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x04, 0x0C, + 0x5F, 0x5F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x62, 0x61, 0x73, 0x65, + 0x03, 0x05, 0x0A, 0x41, 0x08, 0x03, 0x00, 0x01, 0x0B, 0x0D, 0x00, 0x20, + 0x01, 0x20, 0x01, 0x6C, 0x20, 0x00, 0x20, 0x00, 0x6C, 0x6A, 0x0B, 0x04, + 0x00, 0x41, 0x00, 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x00, 0x0B, 0x08, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, 0x01, 0x0B, 0x06, 0x00, 0x20, 0x00, + 0x10, 0x02, 0x0B, 0x0A, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, + 0x03, 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x04, 0x0B, 0x00, 0x76, 0x09, + 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x01, 0x0C, 0x70, + 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2D, 0x62, 0x79, 0x01, + 0x05, 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x56, 0x31, 0x31, 0x2E, 0x30, 0x2E, + 0x30, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x6C, 0x6C, + 0x76, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, 0x2D, 0x70, 0x72, 0x6F, 0x6A, + 0x65, 0x63, 0x74, 0x20, 0x31, 0x37, 0x36, 0x32, 0x34, 0x39, 0x62, 0x64, + 0x36, 0x37, 0x33, 0x32, 0x61, 0x38, 0x30, 0x34, 0x34, 0x64, 0x34, 0x35, + 0x37, 0x30, 0x39, 0x32, 0x65, 0x64, 0x39, 0x33, 0x32, 0x37, 0x36, 0x38, + 0x37, 0x32, 0x34, 0x61, 0x36, 0x66, 0x30, 0x36, 0x29 +}; diff --git a/tests/unit/wasm-vm/wasm-apps/app2.wast b/tests/unit/wasm-vm/wasm-apps/app2.wast new file mode 100644 index 0000000000..c5ea06eaac --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app2.wast @@ -0,0 +1,311 @@ +(module + (type $0 (func (param i32 i32 i32) (result i32))) + (type $1 (func (param i32 i32) (result i32))) + (type $2 (func (param i32) (result i32))) + (type $3 (func (param i32))) + (type $4 (func (param i32 i32 i32 i32) (result i32))) + (type $5 (func)) + (type $6 (func (result i32))) + (import "env" "malloc" (func $15 (param i32) (result i32))) + (import "env" "calloc" (func $16 (param i32 i32) (result i32))) + (import "env" "free" (func $17 (param i32))) + (import "env" "memcpy" (func $18 (param i32 i32 i32) (result i32))) + (import "env" "strdup" (func $19 (param i32) (result i32))) + (import "env" "memcmp" (func $20 (param i32 i32 i32) (result i32))) + (import "env" "printf" (func $21 (param i32 i32) (result i32))) + (import "env" "sprintf" (func $22 (param i32 i32 i32) (result i32))) + (import "env" "snprintf" (func $23 (param i32 i32 i32 i32) (result i32))) + (import "env" "puts" (func $24 (param i32) (result i32))) + (import "env" "putchar" (func $25 (param i32) (result i32))) + (import "env" "memmove" (func $26 (param i32 i32 i32) (result i32))) + (import "env" "memset" (func $27 (param i32 i32 i32) (result i32))) + (import "env" "strchr" (func $28 (param i32 i32) (result i32))) + (import "env" "strcmp" (func $29 (param i32 i32) (result i32))) + (import "env" "strcpy" (func $30 (param i32 i32) (result i32))) + (import "env" "strlen" (func $31 (param i32) (result i32))) + (import "env" "strncmp" (func $32 (param i32 i32 i32) (result i32))) + (import "env" "strncpy" (func $33 (param i32 i32 i32) (result i32))) + (memory $7 1) + (global $8 (mut i32) (i32.const 5120)) + (global $9 i32 (i32.const 1024)) + (global $10 i32 (i32.const 1024)) + (global $11 i32 (i32.const 1024)) + (global $12 i32 (i32.const 5120)) + (global $13 i32 (i32.const 0)) + (global $14 i32 (i32.const 1)) + (export "memory" (memory $7)) + (export "__wasm_call_ctors" (func $34)) + (export "on_init" (func $34)) + (export "my_sqrt" (func $35)) + (export "null_pointer" (func $36)) + (export "my_malloc" (func $37)) + (export "my_calloc" (func $38)) + (export "my_free" (func $39)) + (export "my_memcpy" (func $40)) + (export "my_strdup" (func $41)) + (export "my_memcmp" (func $42)) + (export "my_printf" (func $43)) + (export "my_sprintf" (func $44)) + (export "my_snprintf" (func $45)) + (export "my_puts" (func $46)) + (export "my_putchar" (func $47)) + (export "my_memmove" (func $48)) + (export "my_memset" (func $49)) + (export "my_strchr" (func $50)) + (export "my_strcmp" (func $51)) + (export "my_strcpy" (func $52)) + (export "my_strlen" (func $53)) + (export "my_strncmp" (func $54)) + (export "my_strncpy" (func $55)) + (export "__dso_handle" (global $9)) + (export "__data_end" (global $10)) + (export "__global_base" (global $11)) + (export "__heap_base" (global $12)) + (export "__memory_base" (global $13)) + (export "__table_base" (global $14)) + + (func $34 (type $5) + nop + ) + + (func $35 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $1 + local.get $1 + i32.mul + local.get $0 + local.get $0 + i32.mul + i32.add + ) + + (func $36 (type $6) + (result i32) + i32.const 0 + ) + + (func $37 (type $2) + (param $0 i32) + (result i32) + local.get $0 + call $15 + ) + + (func $38 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $0 + local.get $1 + call $16 + ) + + (func $39 (type $3) + (param $0 i32) + local.get $0 + call $17 + ) + + (func $40 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $18 + ) + + (func $41 (type $2) + (param $0 i32) + (result i32) + local.get $0 + call $19 + ) + + (func $42 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $20 + ) + + (func $43 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + (local $2 i32) + global.get $8 + i32.const 16 + i32.sub + local.tee $2 + global.set $8 + local.get $2 + local.get $1 + i32.store + local.get $0 + local.get $2 + call $21 + local.get $2 + i32.const 16 + i32.add + global.set $8 + ) + + (func $44 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + (local $3 i32) + global.get $8 + i32.const 16 + i32.sub + local.tee $3 + global.set $8 + local.get $3 + local.get $2 + i32.store + local.get $0 + local.get $1 + local.get $3 + call $22 + local.get $3 + i32.const 16 + i32.add + global.set $8 + ) + + (func $45 (type $4) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (param $3 i32) + (result i32) + (local $4 i32) + global.get $8 + i32.const 16 + i32.sub + local.tee $4 + global.set $8 + local.get $4 + local.get $3 + i32.store + local.get $0 + local.get $1 + local.get $2 + local.get $4 + call $23 + local.get $4 + i32.const 16 + i32.add + global.set $8 + ) + + (func $46 (type $2) + (param $0 i32) + (result i32) + local.get $0 + call $24 + ) + + (func $47 (type $2) + (param $0 i32) + (result i32) + local.get $0 + call $25 + ) + + (func $48 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $26 + ) + + (func $49 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $27 + ) + + (func $50 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $0 + local.get $1 + call $28 + ) + + (func $51 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $0 + local.get $1 + call $29 + ) + + (func $52 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $0 + local.get $1 + call $30 + ) + + (func $53 (type $2) + (param $0 i32) + (result i32) + local.get $0 + call $31 + ) + + (func $54 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $32 + ) + + (func $55 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $33 + ) + + ;;(custom_section "producers" + ;; (after code) + ;; "\01\0cprocessed-by\01\05clangV11.0.0 (ht" + ;; "tps://github.com/llvm/llvm-proje" + ;; "ct 176249bd6732a8044d457092ed932" + ;; "768724a6f06)") + + ) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/app2/main.c b/tests/unit/wasm-vm/wasm-apps/app2/main.c new file mode 100644 index 0000000000..160d834a50 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app2/main.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include + +void +on_init() +{} + +int +my_sqrt(int x, int y) +{ + return x * x + y * y; +} + +void * +null_pointer() +{ + void *ptr = NULL; + return ptr; +} + +void * +my_malloc(int size) +{ + return malloc(size); +} + +void * +my_calloc(int nmemb, int size) +{ + return calloc(nmemb, size); +} + +void +my_free(void *ptr) +{ + free(ptr); +} + +void * +my_memcpy(void *dst, void *src, int size) +{ + return memcpy(dst, src, size); +} + +char * +my_strdup(const char *s) +{ + return strdup(s); +} + +int +my_memcmp(const void *buf1, const void *buf2, int size) +{ + return memcmp(buf1, buf2, size); +} + +int +my_printf(const char *format, char *s) +{ + return printf(format, s); +} + +int +my_sprintf(char *buf1, const char *format, char *buf2) +{ + return sprintf(buf1, format, buf2); +} + +int +my_snprintf(char *buf1, int size, const char *format, char *buf2) +{ + return snprintf(buf1, size, format, buf2); +} + +int +my_puts(const char *s) +{ + return puts(s); +} + +int +my_putchar(int s) +{ + return putchar(s); +} + +void * +my_memmove(void *buf1, const void *buf2, int size) +{ + return memmove(buf1, buf2, size); +} + +void * +my_memset(void *buf, int c, int size) +{ + return memset(buf, c, size); +} + +char * +my_strchr(const char *s, int c) +{ + return strchr(s, c); +} + +int +my_strcmp(const char *buf1, const char *buf2) +{ + return strcmp(buf1, buf2); +} + +char * +my_strcpy(char *buf1, const char *buf2) +{ + return strcpy(buf1, buf2); +} + +int +my_strlen(const char *s) +{ + return (int)strlen(s); +} + +int +my_strncmp(const char *buf1, const char *buf2, int n) +{ + return strncmp(buf1, buf2, n); +} + +char * +my_strncpy(char *buf1, const char *buf2, int n) +{ + return strncpy(buf1, buf2, n); +} diff --git a/tests/unit/wasm-vm/wasm-apps/app2_wasm.h b/tests/unit/wasm-vm/wasm-apps/app2_wasm.h new file mode 100644 index 0000000000..d89f7e57da --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app2_wasm.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +unsigned char app2_wasm[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x26, 0x07, 0x60, + 0x03, 0x7F, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, + 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x00, 0x60, 0x04, 0x7F, + 0x7F, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x00, 0x00, 0x60, 0x00, 0x01, 0x7F, + 0x02, 0xFB, 0x01, 0x13, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, 0x61, 0x6C, + 0x6C, 0x6F, 0x63, 0x00, 0x02, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x63, 0x61, + 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x04, 0x66, + 0x72, 0x65, 0x65, 0x00, 0x03, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, 0x65, + 0x6D, 0x63, 0x70, 0x79, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x73, + 0x74, 0x72, 0x64, 0x75, 0x70, 0x00, 0x02, 0x03, 0x65, 0x6E, 0x76, 0x06, + 0x6D, 0x65, 0x6D, 0x63, 0x6D, 0x70, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, + 0x06, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x01, 0x03, 0x65, 0x6E, + 0x76, 0x07, 0x73, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x00, 0x03, + 0x65, 0x6E, 0x76, 0x08, 0x73, 0x6E, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, + 0x00, 0x04, 0x03, 0x65, 0x6E, 0x76, 0x04, 0x70, 0x75, 0x74, 0x73, 0x00, + 0x02, 0x03, 0x65, 0x6E, 0x76, 0x07, 0x70, 0x75, 0x74, 0x63, 0x68, 0x61, + 0x72, 0x00, 0x02, 0x03, 0x65, 0x6E, 0x76, 0x07, 0x6D, 0x65, 0x6D, 0x6D, + 0x6F, 0x76, 0x65, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, 0x65, + 0x6D, 0x73, 0x65, 0x74, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x73, + 0x74, 0x72, 0x63, 0x68, 0x72, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x06, + 0x73, 0x74, 0x72, 0x63, 0x6D, 0x70, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, + 0x06, 0x73, 0x74, 0x72, 0x63, 0x70, 0x79, 0x00, 0x01, 0x03, 0x65, 0x6E, + 0x76, 0x06, 0x73, 0x74, 0x72, 0x6C, 0x65, 0x6E, 0x00, 0x02, 0x03, 0x65, + 0x6E, 0x76, 0x07, 0x73, 0x74, 0x72, 0x6E, 0x63, 0x6D, 0x70, 0x00, 0x00, + 0x03, 0x65, 0x6E, 0x76, 0x07, 0x73, 0x74, 0x72, 0x6E, 0x63, 0x70, 0x79, + 0x00, 0x00, 0x03, 0x17, 0x16, 0x05, 0x01, 0x06, 0x02, 0x01, 0x03, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x04, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x02, 0x00, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x29, 0x07, 0x7F, + 0x01, 0x41, 0x80, 0x28, 0x0B, 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, + 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, + 0x00, 0x41, 0x80, 0x28, 0x0B, 0x7F, 0x00, 0x41, 0x00, 0x0B, 0x7F, 0x00, + 0x41, 0x01, 0x0B, 0x07, 0x81, 0x03, 0x1E, 0x06, 0x6D, 0x65, 0x6D, 0x6F, + 0x72, 0x79, 0x02, 0x00, 0x11, 0x5F, 0x5F, 0x77, 0x61, 0x73, 0x6D, 0x5F, + 0x63, 0x61, 0x6C, 0x6C, 0x5F, 0x63, 0x74, 0x6F, 0x72, 0x73, 0x00, 0x13, + 0x07, 0x6F, 0x6E, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x00, 0x13, 0x07, 0x6D, + 0x79, 0x5F, 0x73, 0x71, 0x72, 0x74, 0x00, 0x14, 0x0C, 0x6E, 0x75, 0x6C, + 0x6C, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x00, 0x15, 0x09, + 0x6D, 0x79, 0x5F, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x16, 0x09, + 0x6D, 0x79, 0x5F, 0x63, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x17, 0x07, + 0x6D, 0x79, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x00, 0x18, 0x09, 0x6D, 0x79, + 0x5F, 0x6D, 0x65, 0x6D, 0x63, 0x70, 0x79, 0x00, 0x19, 0x09, 0x6D, 0x79, + 0x5F, 0x73, 0x74, 0x72, 0x64, 0x75, 0x70, 0x00, 0x1A, 0x09, 0x6D, 0x79, + 0x5F, 0x6D, 0x65, 0x6D, 0x63, 0x6D, 0x70, 0x00, 0x1B, 0x09, 0x6D, 0x79, + 0x5F, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x1C, 0x0A, 0x6D, 0x79, + 0x5F, 0x73, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x1D, 0x0B, 0x6D, + 0x79, 0x5F, 0x73, 0x6E, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x1E, + 0x07, 0x6D, 0x79, 0x5F, 0x70, 0x75, 0x74, 0x73, 0x00, 0x1F, 0x0A, 0x6D, + 0x79, 0x5F, 0x70, 0x75, 0x74, 0x63, 0x68, 0x61, 0x72, 0x00, 0x20, 0x0A, + 0x6D, 0x79, 0x5F, 0x6D, 0x65, 0x6D, 0x6D, 0x6F, 0x76, 0x65, 0x00, 0x21, + 0x09, 0x6D, 0x79, 0x5F, 0x6D, 0x65, 0x6D, 0x73, 0x65, 0x74, 0x00, 0x22, + 0x09, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x63, 0x68, 0x72, 0x00, 0x23, + 0x09, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x63, 0x6D, 0x70, 0x00, 0x24, + 0x09, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x63, 0x70, 0x79, 0x00, 0x25, + 0x09, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x6C, 0x65, 0x6E, 0x00, 0x26, + 0x0A, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x6E, 0x63, 0x6D, 0x70, 0x00, + 0x27, 0x0A, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x6E, 0x63, 0x70, 0x79, + 0x00, 0x28, 0x0C, 0x5F, 0x5F, 0x64, 0x73, 0x6F, 0x5F, 0x68, 0x61, 0x6E, + 0x64, 0x6C, 0x65, 0x03, 0x01, 0x0A, 0x5F, 0x5F, 0x64, 0x61, 0x74, 0x61, + 0x5F, 0x65, 0x6E, 0x64, 0x03, 0x02, 0x0D, 0x5F, 0x5F, 0x67, 0x6C, 0x6F, + 0x62, 0x61, 0x6C, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x03, 0x0B, 0x5F, + 0x5F, 0x68, 0x65, 0x61, 0x70, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x04, + 0x0D, 0x5F, 0x5F, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x5F, 0x62, 0x61, + 0x73, 0x65, 0x03, 0x05, 0x0C, 0x5F, 0x5F, 0x74, 0x61, 0x62, 0x6C, 0x65, + 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x06, 0x0A, 0x94, 0x02, 0x16, 0x03, + 0x00, 0x01, 0x0B, 0x0D, 0x00, 0x20, 0x01, 0x20, 0x01, 0x6C, 0x20, 0x00, + 0x20, 0x00, 0x6C, 0x6A, 0x0B, 0x04, 0x00, 0x41, 0x00, 0x0B, 0x06, 0x00, + 0x20, 0x00, 0x10, 0x00, 0x0B, 0x08, 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, + 0x01, 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x02, 0x0B, 0x0A, 0x00, 0x20, + 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, 0x03, 0x0B, 0x06, 0x00, 0x20, 0x00, + 0x10, 0x04, 0x0B, 0x0A, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, + 0x05, 0x0B, 0x21, 0x01, 0x01, 0x7F, 0x23, 0x00, 0x41, 0x10, 0x6B, 0x22, + 0x02, 0x24, 0x00, 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x00, 0x20, 0x00, + 0x20, 0x02, 0x10, 0x06, 0x20, 0x02, 0x41, 0x10, 0x6A, 0x24, 0x00, 0x0B, + 0x23, 0x01, 0x01, 0x7F, 0x23, 0x00, 0x41, 0x10, 0x6B, 0x22, 0x03, 0x24, + 0x00, 0x20, 0x03, 0x20, 0x02, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x01, + 0x20, 0x03, 0x10, 0x07, 0x20, 0x03, 0x41, 0x10, 0x6A, 0x24, 0x00, 0x0B, + 0x25, 0x01, 0x01, 0x7F, 0x23, 0x00, 0x41, 0x10, 0x6B, 0x22, 0x04, 0x24, + 0x00, 0x20, 0x04, 0x20, 0x03, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x01, + 0x20, 0x02, 0x20, 0x04, 0x10, 0x08, 0x20, 0x04, 0x41, 0x10, 0x6A, 0x24, + 0x00, 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x09, 0x0B, 0x06, 0x00, 0x20, + 0x00, 0x10, 0x0A, 0x0B, 0x0A, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, + 0x10, 0x0B, 0x0B, 0x0A, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, + 0x0C, 0x0B, 0x08, 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, 0x0D, 0x0B, 0x08, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, 0x0E, 0x0B, 0x08, 0x00, 0x20, 0x00, + 0x20, 0x01, 0x10, 0x0F, 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x10, 0x0B, + 0x0A, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, 0x11, 0x0B, 0x0A, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, 0x12, 0x0B, 0x00, 0x76, + 0x09, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x01, 0x0C, + 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2D, 0x62, 0x79, + 0x01, 0x05, 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x56, 0x31, 0x31, 0x2E, 0x30, + 0x2E, 0x30, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x6C, + 0x6C, 0x76, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, 0x2D, 0x70, 0x72, 0x6F, + 0x6A, 0x65, 0x63, 0x74, 0x20, 0x31, 0x37, 0x36, 0x32, 0x34, 0x39, 0x62, + 0x64, 0x36, 0x37, 0x33, 0x32, 0x61, 0x38, 0x30, 0x34, 0x34, 0x64, 0x34, + 0x35, 0x37, 0x30, 0x39, 0x32, 0x65, 0x64, 0x39, 0x33, 0x32, 0x37, 0x36, + 0x38, 0x37, 0x32, 0x34, 0x61, 0x36, 0x66, 0x30, 0x36, 0x29 +}; diff --git a/tests/unit/wasm-vm/wasm-apps/app3.wast b/tests/unit/wasm-vm/wasm-apps/app3.wast new file mode 100644 index 0000000000..7c29ca5180 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app3.wast @@ -0,0 +1,63 @@ +(module + (type $0 (func (param i32) (result i32))) + (type $1 (func)) + (type $2 (func (result i32))) + (type $3 (func (param i32 i32) (result i32))) + (import "env" "malloc" (func $11 (param i32) (result i32))) + (memory $4 1) + (global $5 i32 (i32.const 1024)) + (global $6 i32 (i32.const 1024)) + (global $7 i32 (i32.const 1024)) + (global $8 i32 (i32.const 5120)) + (global $9 i32 (i32.const 0)) + (global $10 i32 (i32.const 1)) + (export "memory" (memory $4)) + (export "__wasm_call_ctors" (func $12)) + (export "on_init" (func $12)) + (export "my_sqrt" (func $13)) + (export "null_pointer" (func $14)) + (export "my_malloc" (func $15)) + (export "__dso_handle" (global $5)) + (export "__data_end" (global $6)) + (export "__global_base" (global $7)) + (export "__heap_base" (global $8)) + (export "__memory_base" (global $9)) + (export "__table_base" (global $10)) + + (func $12 (type $1) + nop + ) + + (func $13 (type $3) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $1 + local.get $1 + i32.mul + local.get $0 + local.get $0 + i32.mul + i32.add + ) + + (func $14 (type $2) + (result i32) + i32.const 0 + ) + + (func $15 (type $0) + (param $0 i32) + (result i32) + local.get $0 + call $11 + ) + + ;;(custom_section "producers" + ;; (after code) + ;; "\01\0cprocessed-by\01\05clangV11.0.0 (ht" + ;; "tps://github.com/llvm/llvm-proje" + ;; "ct 176249bd6732a8044d457092ed932" + ;; "768724a6f06)") + + ) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/app3/main.c b/tests/unit/wasm-vm/wasm-apps/app3/main.c new file mode 100644 index 0000000000..000331ee98 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app3/main.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include + +void +on_init() +{} + +int +my_sqrt(int x, int y) +{ + return x * x + y * y; +} + +void * +null_pointer() +{ + void *ptr = NULL; + return ptr; +} + +void * +my_malloc(int size) +{ + return malloc(size); +} diff --git a/tests/unit/wasm-vm/wasm-apps/app3_wasm.h b/tests/unit/wasm-vm/wasm-apps/app3_wasm.h new file mode 100644 index 0000000000..5c2ee5236b --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app3_wasm.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +unsigned char app3_wasm[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x13, 0x04, 0x60, + 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x00, 0x00, 0x60, 0x00, 0x01, 0x7F, 0x60, + 0x02, 0x7F, 0x7F, 0x01, 0x7F, 0x02, 0x0E, 0x01, 0x03, 0x65, 0x6E, 0x76, + 0x06, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x00, 0x03, 0x05, 0x04, + 0x01, 0x03, 0x02, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x23, 0x06, + 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, + 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, 0x00, 0x41, 0x80, 0x28, 0x0B, + 0x7F, 0x00, 0x41, 0x00, 0x0B, 0x7F, 0x00, 0x41, 0x01, 0x0B, 0x07, 0xA6, + 0x01, 0x0C, 0x06, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x11, + 0x5F, 0x5F, 0x77, 0x61, 0x73, 0x6D, 0x5F, 0x63, 0x61, 0x6C, 0x6C, 0x5F, + 0x63, 0x74, 0x6F, 0x72, 0x73, 0x00, 0x01, 0x07, 0x6F, 0x6E, 0x5F, 0x69, + 0x6E, 0x69, 0x74, 0x00, 0x01, 0x07, 0x6D, 0x79, 0x5F, 0x73, 0x71, 0x72, + 0x74, 0x00, 0x02, 0x0C, 0x6E, 0x75, 0x6C, 0x6C, 0x5F, 0x70, 0x6F, 0x69, + 0x6E, 0x74, 0x65, 0x72, 0x00, 0x03, 0x09, 0x6D, 0x79, 0x5F, 0x6D, 0x61, + 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x04, 0x0C, 0x5F, 0x5F, 0x64, 0x73, 0x6F, + 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x03, 0x00, 0x0A, 0x5F, 0x5F, + 0x64, 0x61, 0x74, 0x61, 0x5F, 0x65, 0x6E, 0x64, 0x03, 0x01, 0x0D, 0x5F, + 0x5F, 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x5F, 0x62, 0x61, 0x73, 0x65, + 0x03, 0x02, 0x0B, 0x5F, 0x5F, 0x68, 0x65, 0x61, 0x70, 0x5F, 0x62, 0x61, + 0x73, 0x65, 0x03, 0x03, 0x0D, 0x5F, 0x5F, 0x6D, 0x65, 0x6D, 0x6F, 0x72, + 0x79, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x04, 0x0C, 0x5F, 0x5F, 0x74, + 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x05, 0x0A, + 0x1F, 0x04, 0x03, 0x00, 0x01, 0x0B, 0x0D, 0x00, 0x20, 0x01, 0x20, 0x01, + 0x6C, 0x20, 0x00, 0x20, 0x00, 0x6C, 0x6A, 0x0B, 0x04, 0x00, 0x41, 0x00, + 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x00, 0x0B, 0x00, 0x76, 0x09, 0x70, + 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x01, 0x0C, 0x70, 0x72, + 0x6F, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2D, 0x62, 0x79, 0x01, 0x05, + 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x56, 0x31, 0x31, 0x2E, 0x30, 0x2E, 0x30, + 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, + 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, 0x2D, 0x70, 0x72, 0x6F, 0x6A, 0x65, + 0x63, 0x74, 0x20, 0x31, 0x37, 0x36, 0x32, 0x34, 0x39, 0x62, 0x64, 0x36, + 0x37, 0x33, 0x32, 0x61, 0x38, 0x30, 0x34, 0x34, 0x64, 0x34, 0x35, 0x37, + 0x30, 0x39, 0x32, 0x65, 0x64, 0x39, 0x33, 0x32, 0x37, 0x36, 0x38, 0x37, + 0x32, 0x34, 0x61, 0x36, 0x66, 0x30, 0x36, 0x29 +}; diff --git a/tests/unit/wasm-vm/wasm-apps/app4/m1.wasm b/tests/unit/wasm-vm/wasm-apps/app4/m1.wasm new file mode 100644 index 0000000000..6979e1801e Binary files /dev/null and b/tests/unit/wasm-vm/wasm-apps/app4/m1.wasm differ diff --git a/tests/unit/wasm-vm/wasm-apps/app4/m1.wat b/tests/unit/wasm-vm/wasm-apps/app4/m1.wat new file mode 100644 index 0000000000..2b97af8ec3 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app4/m1.wat @@ -0,0 +1,14 @@ +(module + (func $f1 (export "f1") (result i32) (i32.const 1)) + + (memory $m1 1 2) + (table $t1 0 funcref) + (global $g1 i32 (i32.const 1)) + + (export "m1" (memory $m1)) + (export "m1_alias" (memory $m1)) + (export "t1" (table $t1)) + (export "t1_alias" (table $t1)) + (export "g1" (global $g1)) + (export "g1_alias" (global $g1)) +) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/app4/m2.wasm b/tests/unit/wasm-vm/wasm-apps/app4/m2.wasm new file mode 100644 index 0000000000..e1a3059b35 Binary files /dev/null and b/tests/unit/wasm-vm/wasm-apps/app4/m2.wasm differ diff --git a/tests/unit/wasm-vm/wasm-apps/app4/m2.wat b/tests/unit/wasm-vm/wasm-apps/app4/m2.wat new file mode 100644 index 0000000000..340a3436bc --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app4/m2.wat @@ -0,0 +1,24 @@ +(module + (import "m1" "f1" (func $m1-f1 (result i32))) + (export "m1-f1" (func $m1-f1)) + + (import "m1" "m1" (memory $m1-m1 1 2)) + (import "m1" "t1" (table $m1-t1 0 funcref)) + (import "m1" "g1" (global $m1-g1 i32)) + + (func $f2 (export "f2") (param i32) (result i32) + (i32.add (call $m1-f1) (local.get 0)) + ) + + (func $f4 (result i32) (i32.const 3)) + + (func $f3 (export "f3") (param i32 i32) (result i32) + (i32.add + (call $m1-f1) + (i32.add + (call $f4) + (call $f2 (local.get 0)) + ) + ) + ) +) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/app4/m3.wasm b/tests/unit/wasm-vm/wasm-apps/app4/m3.wasm new file mode 100644 index 0000000000..ecbff3d7b6 Binary files /dev/null and b/tests/unit/wasm-vm/wasm-apps/app4/m3.wasm differ diff --git a/tests/unit/wasm-vm/wasm-apps/app4/m3.wat b/tests/unit/wasm-vm/wasm-apps/app4/m3.wat new file mode 100644 index 0000000000..e300121ef5 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app4/m3.wat @@ -0,0 +1,7 @@ +(module + (import "m1" "f1" (func $m1-f1 (result i32))) + (import "m1" "m1_alias" (memory $m1-m1 1 2)) + (import "m1" "t1_alias" (table $m1-t1 0 funcref)) + (import "m1" "g1_alias" (global $m1-g1 i32)) + (import "m2" "f2" (func $m2-f2 (param i32) (result i32))) +) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/binarydump b/tests/unit/wasm-vm/wasm-apps/binarydump new file mode 100755 index 0000000000..e7c4d2a1da Binary files /dev/null and b/tests/unit/wasm-vm/wasm-apps/binarydump differ diff --git a/tests/unit/wasm-vm/wasm-apps/build.sh b/tests/unit/wasm-vm/wasm-apps/build.sh new file mode 100755 index 0000000000..dbf062ae7a --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/build.sh @@ -0,0 +1,32 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +## build app1 +/opt/wasi-sdk/bin/clang -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -o app1/app1.wasm app1/main.c -Wl,--export-all \ + -Wl,--export=__heap_base,--export=__data_end \ + -Wl,--no-entry -nostdlib -Wl,--allow-undefined +./binarydump -o app1_wasm.h -n app1_wasm app1/app1.wasm +wavm disassemble app1/app1.wasm app1.wast +rm -f app1/app1.wasm + +## build app2 +/opt/wasi-sdk/bin/clang -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -o app2/app2.wasm app2/main.c -Wl,--export-all \ + -Wl,--export=__heap_base,--export=__data_end \ + -Wl,--no-entry -nostdlib -Wl,--allow-undefined +./binarydump -o app2_wasm.h -n app2_wasm app2/app2.wasm +wavm disassemble app2/app2.wasm app2.wast +rm -f app2/app2.wasm + +## build app3 +/opt/wasi-sdk/bin/clang -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -o app3/app3.wasm app3/main.c -Wl,--export-all \ + -Wl,--export=__heap_base,--export=__data_end \ + -Wl,--no-entry -nostdlib -Wl,--allow-undefined +./binarydump -o app3_wasm.h -n app3_wasm app3/app3.wasm +wavm disassemble app3/app3.wasm app3.wast +rm -f app3/app3.wasm diff --git a/tests/unit/wasm-vm/wasm_vm.cc b/tests/unit/wasm-vm/wasm_vm.cc new file mode 100644 index 0000000000..f4f5a834d1 --- /dev/null +++ b/tests/unit/wasm-vm/wasm_vm.cc @@ -0,0 +1,716 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "bh_platform.h" +#include "bh_read_file.h" +#include "wasm_export.h" +#if WASM_ENABLE_MULTI_MODULE != 0 +#include "wasm.h" +#include "wasm_runtime.h" +#endif +#include "wasm-apps/app1_wasm.h" +#include "wasm-apps/app2_wasm.h" +#include "wasm-apps/app3_wasm.h" + +#define EightK (8 * 1024) +// To use a test fixture, derive a class from testing::Test. +class WasmVMTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + + // bh_log_set_verbose_level(5); + + clean = true; + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + void TearDown() + { + if (clean) { + wasm_runtime_destroy(); + } + } + + public: + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_function_inst_t func_inst = NULL; + wasm_exec_env_t exec_env = NULL; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + RuntimeInitArgs init_args; + bool clean = true; +}; + +TEST_F(WasmVMTest, Test_app1) +{ + unsigned argv[10]; + + ASSERT_TRUE(app1_wasm != NULL); + + /* Load module */ + module = wasm_runtime_load(app1_wasm, sizeof(app1_wasm), error_buf, + sizeof(error_buf)); + if (module == nullptr) { + printf("error: %s\n", error_buf); + } + + ASSERT_TRUE(module != NULL); + + /* Initiate module */ + module_inst = wasm_runtime_instantiate(module, 8 * 1024, 8 * 1024, + error_buf, sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + /* _on_init() function doesn't exist */ + func_inst = wasm_runtime_lookup_function(module_inst, "_on_init"); + ASSERT_TRUE(func_inst == NULL); + + /* on_init() function exists */ + func_inst = wasm_runtime_lookup_function(module_inst, "on_init"); + ASSERT_TRUE(func_inst != NULL); + + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_inst, 0, NULL) == true); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* call my_malloc */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_malloc"); + ASSERT_TRUE(func_inst != NULL); + + /* malloc with very large size */ + argv[0] = 10 * 1024; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + wasm_runtime_clear_exception(module_inst); + ASSERT_EQ(argv[0], 0); + + /* malloc 1K, should success */ + argv[0] = 1024; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* convert to native address */ + ASSERT_TRUE(wasm_runtime_validate_app_addr(module_inst, argv[0], 1)); + char *buf = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf != NULL); + + ASSERT_EQ(wasm_runtime_addr_native_to_app(module_inst, buf), argv[0]); + int32 buf_offset = argv[0]; + + /* call memcpy */ + char *buf1 = buf + 100; + memcpy(buf1, "123456", 7); + func_inst = wasm_runtime_lookup_function(module_inst, "my_memcpy"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = buf_offset + 100; + argv[2] = 7; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + ASSERT_TRUE(strcmp(buf, buf1) == 0); + + /* call strdup */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_strdup"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + + int32 buf_offset1 = argv[0]; + ASSERT_NE(buf_offset, buf_offset1); + + buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, buf_offset1); + ASSERT_TRUE(strcmp(buf, buf1) == 0); + + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + wasm_runtime_destroy_exec_env(exec_env); +} + +TEST_F(WasmVMTest, Test_app2) +{ + unsigned argv[10]; + + /* Load module */ + module = wasm_runtime_load(app2_wasm, sizeof(app2_wasm), error_buf, + sizeof(error_buf)); + + ASSERT_TRUE(module != NULL); + + /* Initiate module */ + module_inst = wasm_runtime_instantiate(module, 8 * 1024, 8 * 1024, + error_buf, sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + /* _on_init() function doesn't exist */ + func_inst = wasm_runtime_lookup_function(module_inst, "_on_init"); + ASSERT_TRUE(func_inst == NULL); + + /* on_init() function exists */ + func_inst = wasm_runtime_lookup_function(module_inst, "on_init"); + ASSERT_TRUE(func_inst != NULL); + + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_inst, 0, NULL) == true); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* call my_malloc */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_malloc"); + ASSERT_TRUE(func_inst != NULL); + + /* malloc 1K, should success */ + argv[0] = 1024; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* convert to native address */ + ASSERT_TRUE(wasm_runtime_validate_app_addr(module_inst, argv[0], 1)); + char *buf = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf != NULL); + + ASSERT_EQ(wasm_runtime_addr_native_to_app(module_inst, buf), argv[0]); + int32 buf_offset = argv[0]; + + /* call memcpy */ + char *buf1 = buf + 100; + memcpy(buf1, "123456", 7); + func_inst = wasm_runtime_lookup_function(module_inst, "my_memcpy"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = buf_offset + 100; + argv[2] = 7; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + ASSERT_TRUE(strcmp(buf, buf1) == 0); + + /* call memcmp */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_memcmp"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = buf_offset + 100; + argv[2] = 7; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + ASSERT_TRUE(argv[0] == 0); + + /* call printf */ + char *format = buf + 200; + memcpy(format, "string0 is %s", 13); + func_inst = wasm_runtime_lookup_function(module_inst, "my_printf"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = wasm_runtime_addr_native_to_app(module_inst, format); + argv[1] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(argv[0] == 17); + + /* call sprintf */ + memcpy(format, "string1 is %s", 13); + func_inst = wasm_runtime_lookup_function(module_inst, "my_sprintf"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 300; + int32 argv0_tmp = argv[0]; + argv[1] = wasm_runtime_addr_native_to_app(module_inst, format); + argv[2] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + ASSERT_TRUE( + memcmp((char *)wasm_runtime_addr_app_to_native(module_inst, argv0_tmp), + "string1 is 123456", 17) + == 0); + ASSERT_TRUE(argv[0] == 17); + + /* call snprintf */ + memcpy(format, "string2 is %s", 13); + func_inst = wasm_runtime_lookup_function(module_inst, "my_snprintf"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 400; + argv0_tmp = argv[0]; + argv[1] = 3; + argv[2] = wasm_runtime_addr_native_to_app(module_inst, format); + argv[3] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 4, argv); + + ASSERT_TRUE( + memcmp((char *)wasm_runtime_addr_app_to_native(module_inst, argv0_tmp), + "st\0", 3) + == 0); + ASSERT_TRUE(argv[0] == 17); + + /* call puts */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_puts"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + + ASSERT_TRUE(argv[0] != EOF); + + /* call putchar */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_putchar"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + + ASSERT_TRUE(argv[0] != EOF); + + /* call memmove without memory coverage*/ + func_inst = wasm_runtime_lookup_function(module_inst, "my_memmove"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 10; + argv[1] = buf_offset + 100; + argv[2] = 6; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(strcmp(buf + 100, buf1) == 0); + ASSERT_TRUE(memcmp(buf1, "123456", 6) == 0); + + /* call memmove with memory coverage*/ + func_inst = wasm_runtime_lookup_function(module_inst, "my_memmove"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 95; + argv[1] = buf_offset + 100; + argv[2] = 6; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(strcmp(buf + 100, buf1) != 0); + ASSERT_TRUE(memcmp(buf1, "123456", 6) == 0); + ASSERT_TRUE(memcmp(buf + 100, "623456", 6) == 0); + + /* call memset*/ + func_inst = wasm_runtime_lookup_function(module_inst, "my_memset"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 100; + argv[1] = 48; + argv[2] = 4; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + ASSERT_TRUE(memcmp(buf + 100, "000056", 6) == 0); + + /* call strchr*/ + func_inst = wasm_runtime_lookup_function(module_inst, "my_strchr"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = 49; // asc2 for char "1" + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + + buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf1 - buf == 0); + + /* call strcmp */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_strcmp"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + + ASSERT_TRUE(argv[0] == 0); + + argv[0] = buf_offset; + argv[1] = buf_offset + 1; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + + ASSERT_TRUE(argv[0] != 0); + + /* call strcpy */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_strcpy"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 110; + argv[1] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(memcmp(buf + 110, "123456", 6) == 0); + + /* call strlen */ + buf1 = buf + 110; + memcpy(buf1, "123456\0", 7); + func_inst = wasm_runtime_lookup_function(module_inst, "my_strlen"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 110; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + + ASSERT_TRUE(argv[0] == 6); + + /* call strncmp */ + buf1 = buf + 110; + memcpy(buf1, "123457", 6); + func_inst = wasm_runtime_lookup_function(module_inst, "my_strncmp"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = buf_offset + 110; + argv[2] = 5; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + ASSERT_TRUE(argv[0] == 0); + + argv[0] = buf_offset; + argv[1] = buf_offset + 110; + argv[2] = 6; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + ASSERT_TRUE(argv[0] != 0); + + /* call strncpy */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_strncpy"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 130; + argv[1] = buf_offset; + argv[2] = 5; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(memcmp(buf, buf1, 5) == 0); + ASSERT_TRUE(memcmp(buf, buf1, 6) != 0); + + /* call _my_calloc */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_calloc"); + ASSERT_TRUE(func_inst != NULL); + /* calloc, should success */ + argv[0] = 10; + argv[1] = 4; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* convert to native address */ + ASSERT_TRUE(wasm_runtime_validate_app_addr(module_inst, argv[0], 40)); + char *buf2 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf2 != NULL); + + ASSERT_EQ(wasm_runtime_addr_native_to_app(module_inst, buf2), argv[0]); + int32 buf_offset1 = argv[0]; + + /* call _my_free */ + memcpy(buf2, "123456", 6); + func_inst = wasm_runtime_lookup_function(module_inst, "my_free"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset1; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + + ASSERT_TRUE(memcmp(buf2, "123456", 6) != 0); + + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + wasm_runtime_destroy_exec_env(exec_env); +} + +TEST_F(WasmVMTest, Test_app3) +{ + unsigned argv[10]; + + /* Load module */ + module = wasm_runtime_load(app3_wasm, sizeof(app3_wasm), error_buf, + sizeof(error_buf)); + + ASSERT_TRUE(module != NULL); + + /* Initiate module */ + module_inst = wasm_runtime_instantiate(module, 8 * 1024, 8 * 1024, + error_buf, sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + /* _on_init() function doesn't exist */ + func_inst = wasm_runtime_lookup_function(module_inst, "_on_init"); + ASSERT_TRUE(func_inst == NULL); + + /* on_init() function exists */ + func_inst = wasm_runtime_lookup_function(module_inst, "on_init"); + ASSERT_TRUE(func_inst != NULL); + + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_inst, 0, NULL) == true); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* call my_malloc */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_malloc"); + ASSERT_TRUE(func_inst != NULL); + + /* malloc with very large size */ + argv[0] = 10 * 1024; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + wasm_runtime_clear_exception(module_inst); + ASSERT_EQ(argv[0], 0); + + /* malloc 1K, should success */ + argv[0] = 1024; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* convert to native address */ + ASSERT_TRUE(wasm_runtime_validate_app_addr(module_inst, argv[0], 1)); + char *buf = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf != NULL); + + ASSERT_EQ(wasm_runtime_addr_native_to_app(module_inst, buf), argv[0]); + int32 buf_offset = argv[0]; + + /* call my_malloc */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_malloc"); + ASSERT_TRUE(func_inst != NULL); + + /* malloc, should success */ + argv[0] = 10; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* convert to native address */ + ASSERT_TRUE(wasm_runtime_validate_app_addr(module_inst, argv[0], 1)); + char *buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf1 != NULL); + + ASSERT_EQ(wasm_runtime_addr_native_to_app(module_inst, buf1), argv[0]); + int32 buf_offset1 = argv[0]; + + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + wasm_runtime_destroy_exec_env(exec_env); +} + +#if WASM_ENABLE_MULTI_MODULE != 0 +static const char *module_search_path = "."; +static bool call_destroyer = false; +static bool +module_reader_callback(package_type_t module_type, const char *module_name, + uint8 **p_buffer, uint32 *p_size) +{ + const char *format = "%s/%s.wasm"; + int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) + + strlen(".wasm") + 1; + char *wasm_file_name = (char *)BH_MALLOC(sz); + if (!wasm_file_name) { + return false; + } + + snprintf(wasm_file_name, sz, format, module_search_path, module_name); + printf("going to open %s\n", wasm_file_name); + + call_destroyer = false; + *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size); + + BH_FREE(wasm_file_name); + return *p_buffer != NULL; +} + +static void +module_destroyer_callback(uint8 *buffer, uint32 size) +{ + wasm_runtime_free(buffer); + call_destroyer = true; +} + +TEST_F(WasmVMTest, Test_app4_single) +{ + uint8 *buffer = NULL; + uint32 buffer_size = 0; + bool ret = false; + unsigned argv[10]; + + wasm_runtime_set_module_reader(&module_reader_callback, + &module_destroyer_callback); + + /* m1 only */ + ret = module_reader_callback(Wasm_Module_Bytecode, "m1", &buffer, + &buffer_size); + ASSERT_TRUE(ret); + ASSERT_TRUE(buffer_size > 0); + ASSERT_TRUE(buffer != NULL); + + module = + wasm_runtime_load(buffer, buffer_size, error_buf, sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + ASSERT_FALSE(wasm_runtime_find_module_registered("m1")); + + wasm_runtime_register_module("m1", module, error_buf, sizeof(error_buf)); + + ASSERT_TRUE(wasm_runtime_find_module_registered("m1")); + + module_inst = wasm_runtime_instantiate(module, EightK, EightK, error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, EightK); + ASSERT_TRUE(exec_env != NULL); + + func_inst = wasm_runtime_lookup_function(module_inst, "f1"); + ASSERT_TRUE(func_inst != NULL); + ASSERT_FALSE(((WASMFunctionInstance *)func_inst)->is_import_func); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->param_cell_num == 0); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->ret_cell_num == 1); + + wasm_runtime_call_wasm(exec_env, func_inst, 0, argv); + printf("exception is %s", wasm_runtime_get_exception(module_inst)); + + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + ASSERT_TRUE(argv[0] == 1); + + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + + // call destroyer and without exception + ASSERT_FALSE(call_destroyer); + module_destroyer_callback(buffer, buffer_size); + + clean = false; + wasm_runtime_destroy(); +} + +TEST_F(WasmVMTest, Test_app4_plus_one) +{ + uint8 *buffer = NULL; + uint32 buffer_size = 0; + bool ret = false; + uint32_t argv[10] = { 0 }; + + wasm_runtime_set_module_reader(&module_reader_callback, + &module_destroyer_callback); + + /* m2 -> m1 */ + ret = module_reader_callback(Wasm_Module_Bytecode, "m2", &buffer, + &buffer_size); + ASSERT_TRUE(ret); + ASSERT_TRUE(buffer_size > 0); + ASSERT_TRUE(buffer != NULL); + + module = + wasm_runtime_load(buffer, buffer_size, error_buf, sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + module_inst = wasm_runtime_instantiate(module, EightK, EightK, error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, EightK); + ASSERT_TRUE(exec_env != NULL); + + printf("------------------- m1-f1 ---------------------\n"); + func_inst = wasm_runtime_lookup_function(module_inst, "m1-f1"); + ASSERT_TRUE(func_inst != NULL); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->is_import_func); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->param_cell_num == 0); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->ret_cell_num == 1); + + wasm_runtime_call_wasm(exec_env, func_inst, 0, argv); + printf("exception is %s\n", wasm_runtime_get_exception(module_inst)); + + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + ASSERT_TRUE(argv[0] == 1); + + printf("------------------- f2 ---------------------\n"); + func_inst = wasm_runtime_lookup_function(module_inst, "f2"); + ASSERT_TRUE(func_inst != NULL); + ASSERT_FALSE(((WASMFunctionInstance *)func_inst)->is_import_func); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->param_cell_num == 1); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->ret_cell_num == 1); + + argv[0] = 2; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + printf("exception is %s\n", wasm_runtime_get_exception(module_inst)); + + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + ASSERT_TRUE(argv[0] == 3); + + printf("------------------- f3 ---------------------\n"); + func_inst = wasm_runtime_lookup_function(module_inst, "f3"); + ASSERT_TRUE(func_inst != NULL); + ASSERT_FALSE(((WASMFunctionInstance *)func_inst)->is_import_func); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->param_cell_num == 2); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->ret_cell_num == 1); + + argv[0] = 4; + argv[1] = 9; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + printf("exception is %s\n", wasm_runtime_get_exception(module_inst)); + + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + ASSERT_TRUE(argv[0] == 9); + + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + + wasm_runtime_unload(module); + ASSERT_FALSE(call_destroyer); +} + +TEST_F(WasmVMTest, Test_app4_family) +{ + uint8 *buffer = NULL; + uint32 buffer_size = 0; + bool ret = false; + + wasm_runtime_set_module_reader(&module_reader_callback, + &module_destroyer_callback); + + /* m3 -> m2[->m1], m1 */ + ret = module_reader_callback(Wasm_Module_Bytecode, "m3", &buffer, + &buffer_size); + ASSERT_TRUE(ret); + ASSERT_TRUE(buffer_size > 0); + ASSERT_TRUE(buffer != NULL); + module = + wasm_runtime_load(buffer, buffer_size, error_buf, sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + wasm_runtime_unload(module); + ASSERT_FALSE(call_destroyer); +} + +static const WASMModule * +search_sub_module(const WASMModule *parent_module, const char *sub_module_name) +{ + WASMRegisteredModule *node = (WASMRegisteredModule *)bh_list_first_elem( + parent_module->import_module_list); + while (node && strcmp(node->module_name, sub_module_name)) { + node = (WASMRegisteredModule *)bh_list_elem_next(node); + } + return node ? (WASMModule *)node->module : NULL; +} + +TEST_F(WasmVMTest, Test_app4_reuse) +{ + uint8 *buffer = NULL; + uint32 buffer_size = 0; + bool ret = false; + + wasm_runtime_set_module_reader(&module_reader_callback, + &module_destroyer_callback); + + /* m3 -> m2[->m1], m1 */ + ret = module_reader_callback(Wasm_Module_Bytecode, "m3", &buffer, + &buffer_size); + ASSERT_TRUE(buffer != NULL); + + WASMModule *m3 = (WASMModule *)wasm_runtime_load( + buffer, buffer_size, error_buf, sizeof(error_buf)); + ASSERT_TRUE(m3 != NULL); + + const WASMModule *m2 = search_sub_module(m3, "m2"); + const WASMModule *m1_in_m2 = search_sub_module(m2, "m1"); + const WASMModule *m1_in_m3 = search_sub_module(m3, "m1"); + ASSERT_EQ(m1_in_m2, m1_in_m3); +} +#endif /* WASM_ENABLE_MULTI_MODULE */