From 01e85144f4063db9809464fb40c0a95b16f83562 Mon Sep 17 00:00:00 2001 From: wenyongh Date: Tue, 24 Mar 2020 19:04:29 +0800 Subject: [PATCH] Enable aarch64 support, add component test framework and test suite (#211) and refine aot call indirect op --- README.md | 1 + build-scripts/config_common.cmake | 5 +- build-scripts/runtime_lib.cmake | 2 +- core/config.h | 3 + core/iwasm/aot/aot_loader.c | 2 + core/iwasm/aot/aot_reloc.h | 3 +- core/iwasm/aot/aot_runtime.c | 84 ++- core/iwasm/aot/aot_runtime.h | 7 +- core/iwasm/aot/arch/aot_reloc_aarch64.c | 238 +++++++++ core/iwasm/aot/arch/aot_reloc_arm.c | 6 +- core/iwasm/aot/arch/aot_reloc_thumb.c | 4 - core/iwasm/aot/iwasm_aot.cmake | 2 + core/iwasm/common/arch/invokeNative_aarch64.s | 76 +++ core/iwasm/common/iwasm_common.cmake | 2 + core/iwasm/common/wasm_runtime_common.c | 14 +- core/iwasm/compilation/aot_emit_function.c | 496 +++++++++--------- core/iwasm/compilation/aot_llvm.c | 16 + doc/build_wamr.md | 11 +- product-mini/platforms/android/CMakeLists.txt | 2 +- product-mini/platforms/linux/CMakeLists.txt | 2 +- .../platforms/zephyr/simple/CMakeLists.txt | 2 +- product-mini/platforms/zephyr/simple/build.sh | 10 +- .../zephyr/simple/prj_qemu_cortex_a53.conf | 7 + .../zephyr-build/CMakeLists.txt | 3 + .../src/platform/linux/iwasm_main.c | 2 +- .../zephyr-build/CMakeLists.txt | 3 + test-tools/component_test/README.md | 56 ++ test-tools/component_test/__init__.py | 11 + .../component_test/framework/__init__.py | 11 + .../component_test/framework/case_base.py | 29 + test-tools/component_test/framework/engine.py | 38 ++ .../component_test/framework/framework.py | 287 ++++++++++ test-tools/component_test/framework/suite.py | 40 ++ .../component_test/framework/test_api.py | 98 ++++ .../component_test/framework/test_utils.py | 70 +++ test-tools/component_test/harness/__init__.py | 0 .../component_test/harness/harness_api.py | 150 ++++++ .../host-clients/src/host_app_sample.c | 285 ++++++++++ .../component_test/host-clients/src/makefile | 44 ++ test-tools/component_test/set_dev_env.sh | 7 + test-tools/component_test/start.py | 151 ++++++ .../suites/01-life-cycle/__init__.py | 0 .../cases/01-install/__init__.py | 0 .../01-life-cycle/cases/01-install/case.py | 94 ++++ .../cases/02-request/__init__.py | 0 .../01-life-cycle/cases/02-request/case.py | 73 +++ .../01-life-cycle/cases/03-event/__init__.py | 0 .../01-life-cycle/cases/03-event/case.py | 67 +++ .../cases/04-request-internal/__init__.py | 0 .../cases/04-request-internal/case.py | 80 +++ .../cases/05-event-internal/__init__.py | 0 .../cases/05-event-internal/case.py | 70 +++ .../01-life-cycle/cases/06-timer/__init__.py | 0 .../01-life-cycle/cases/06-timer/case.py | 70 +++ .../01-life-cycle/cases/07-sensor/__init__.py | 0 .../01-life-cycle/cases/07-sensor/case.py | 65 +++ .../cases/08-on-destroy/__init__.py | 0 .../01-life-cycle/cases/08-on-destroy/case.py | 78 +++ .../suites/01-life-cycle/cases/__init__.py | 0 .../suites/01-life-cycle/suite_setup.py | 56 ++ .../01-life-cycle/test-app/01_install.c | 16 + .../01-life-cycle/test-app/02_request.c | 62 +++ .../suites/01-life-cycle/test-app/03_event.c | 53 ++ .../test-app/04_request_internal_req.c | 66 +++ .../test-app/04_request_internal_resp.c | 52 ++ .../test-app/05_event_internal_provider.c | 53 ++ .../test-app/05_event_internal_subscriber.c | 50 ++ .../suites/01-life-cycle/test-app/06_timer.c | 76 +++ .../suites/01-life-cycle/test-app/07_sensor.c | 69 +++ .../01-life-cycle/test-app/08_on_destroy.c | 67 +++ .../suites/01-life-cycle/test-app/build.sh | 39 ++ .../01-life-cycle/tools/product/start.sh | 10 + .../01-life-cycle/tools/product/stop.sh | 9 + test-tools/component_test/suites/__init__.py | 0 test-tools/component_test/suites/readme.txt | 19 + wamr-compiler/CMakeLists.txt | 5 +- wamr-compiler/main.c | 2 +- 77 files changed, 3293 insertions(+), 288 deletions(-) create mode 100644 core/iwasm/aot/arch/aot_reloc_aarch64.c create mode 100644 core/iwasm/common/arch/invokeNative_aarch64.s create mode 100644 product-mini/platforms/zephyr/simple/prj_qemu_cortex_a53.conf create mode 100644 test-tools/component_test/README.md create mode 100644 test-tools/component_test/__init__.py create mode 100644 test-tools/component_test/framework/__init__.py create mode 100644 test-tools/component_test/framework/case_base.py create mode 100644 test-tools/component_test/framework/engine.py create mode 100644 test-tools/component_test/framework/framework.py create mode 100644 test-tools/component_test/framework/suite.py create mode 100644 test-tools/component_test/framework/test_api.py create mode 100644 test-tools/component_test/framework/test_utils.py create mode 100644 test-tools/component_test/harness/__init__.py create mode 100644 test-tools/component_test/harness/harness_api.py create mode 100644 test-tools/component_test/host-clients/src/host_app_sample.c create mode 100644 test-tools/component_test/host-clients/src/makefile create mode 100755 test-tools/component_test/set_dev_env.sh create mode 100755 test-tools/component_test/start.py create mode 100644 test-tools/component_test/suites/01-life-cycle/__init__.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/01-install/__init__.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/01-install/case.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/02-request/__init__.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/02-request/case.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/03-event/__init__.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/03-event/case.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/__init__.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/case.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/__init__.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/case.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/06-timer/__init__.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/06-timer/case.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/07-sensor/__init__.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/07-sensor/case.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/__init__.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/case.py create mode 100644 test-tools/component_test/suites/01-life-cycle/cases/__init__.py create mode 100644 test-tools/component_test/suites/01-life-cycle/suite_setup.py create mode 100644 test-tools/component_test/suites/01-life-cycle/test-app/01_install.c create mode 100644 test-tools/component_test/suites/01-life-cycle/test-app/02_request.c create mode 100644 test-tools/component_test/suites/01-life-cycle/test-app/03_event.c create mode 100644 test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_req.c create mode 100644 test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_resp.c create mode 100644 test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_provider.c create mode 100644 test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_subscriber.c create mode 100644 test-tools/component_test/suites/01-life-cycle/test-app/06_timer.c create mode 100644 test-tools/component_test/suites/01-life-cycle/test-app/07_sensor.c create mode 100644 test-tools/component_test/suites/01-life-cycle/test-app/08_on_destroy.c create mode 100755 test-tools/component_test/suites/01-life-cycle/test-app/build.sh create mode 100755 test-tools/component_test/suites/01-life-cycle/tools/product/start.sh create mode 100755 test-tools/component_test/suites/01-life-cycle/tools/product/stop.sh create mode 100644 test-tools/component_test/suites/__init__.py create mode 100644 test-tools/component_test/suites/readme.txt diff --git a/README.md b/README.md index af9a8cd8..4f89bb76 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ The iwasm supports the following architectures: - X86-64, X86-32 - ARM, THUMB (ARMV7 Cortex-M7 and Cortex-A15 are tested) +- AArch64 (Cortex-A57 and Cortex-A53 are tested) - MIPS - XTENSA diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index 1513b70a..572e8aec 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -27,6 +27,9 @@ elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*") add_definitions(-DBUILD_TARGET_THUMB) add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}") endif () +elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*") + add_definitions(-DBUILD_TARGET_AARCH64) + add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}") elseif (WAMR_BUILD_TARGET STREQUAL "MIPS") add_definitions(-DBUILD_TARGET_MIPS) elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA") @@ -40,7 +43,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug") endif () if (CMAKE_SIZEOF_VOID_P EQUAL 8) - if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*") # Add -fPIC flag if build as 64-bit set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC") diff --git a/build-scripts/runtime_lib.cmake b/build-scripts/runtime_lib.cmake index e60a53b8..128f44ea 100644 --- a/build-scripts/runtime_lib.cmake +++ b/build-scripts/runtime_lib.cmake @@ -31,7 +31,7 @@ endif () # Set default options # Set WAMR_BUILD_TARGET, currently values supported: -# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" if (NOT DEFINED WAMR_BUILD_TARGET) if (CMAKE_SIZEOF_VOID_P EQUAL 8) # Build as X86_64 by default in 64-bit platform diff --git a/core/config.h b/core/config.h index 79806761..30ceda32 100644 --- a/core/config.h +++ b/core/config.h @@ -8,6 +8,7 @@ #if !defined(BUILD_TARGET_X86_64) \ && !defined(BUILD_TARGET_AMD_64) \ + && !defined(BUILD_TARGET_AARCH64) \ && !defined(BUILD_TARGET_X86_32) \ && !defined(BUILD_TARGET_ARM) \ && !defined(BUILD_TARGET_ARM_VFP) \ @@ -19,6 +20,8 @@ #define BUILD_TARGET_X86_64 #elif defined(__amd64__) || defined(__amd64) #define BUILD_TARGET_AMD_64 +#elif defined(__aarch64__) +#define BUILD_TARGET_AARCH64 #elif defined(__i386__) || defined(__i386) || defined(i386) #define BUILD_TARGET_X86_32 #elif defined(__thumb__) diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c index 7759612a..5ce4d2aa 100644 --- a/core/iwasm/aot/aot_loader.c +++ b/core/iwasm/aot/aot_loader.c @@ -140,6 +140,7 @@ GET_U64_FROM_ADDR(uint32 *addr) #define E_MACHINE_MIPS 8 /* MIPS R3000 big-endian */ #define E_MACHINE_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ #define E_MACHINE_ARM 40 /* ARM/Thumb */ +#define E_MACHINE_AARCH64 183 /* AArch64 */ #define E_MACHINE_ARC 45 /* Argonaut RISC Core */ #define E_MACHINE_IA_64 50 /* Intel Merced */ #define E_MACHINE_MIPS_X 51 /* Stanford MIPS-X */ @@ -196,6 +197,7 @@ get_aot_file_target(AOTTargetInfo *target_info, machine_type = "i386"; break; case E_MACHINE_ARM: + case E_MACHINE_AARCH64: machine_type = target_info->arch; break; case E_MACHINE_MIPS: diff --git a/core/iwasm/aot/aot_reloc.h b/core/iwasm/aot/aot_reloc.h index 02931dd2..c98a58e2 100644 --- a/core/iwasm/aot/aot_reloc.h +++ b/core/iwasm/aot/aot_reloc.h @@ -14,9 +14,8 @@ typedef struct { #define REG_COMMON_SYMBOLS \ REG_SYM(aot_set_exception_with_id), \ - REG_SYM(aot_get_exception), \ - REG_SYM(aot_is_wasm_type_equal), \ REG_SYM(aot_invoke_native), \ + REG_SYM(aot_call_indirect), \ REG_SYM(wasm_runtime_enlarge_memory), \ REG_SYM(wasm_runtime_set_exception), \ REG_SYM(fmin), \ diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 2d121a8d..082d9a6c 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -811,7 +811,7 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst, return wasm_type_equal(type1, type2); } -void +bool aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 *frame_lp, uint32 argc, uint32 *argv_ret) { @@ -827,18 +827,76 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, const char *signature = NULL; char buf[128]; - if (func_idx < aot_module->import_func_count) { - import_func = aot_module->import_funcs + func_idx; - if (!func_ptr) { - snprintf(buf, sizeof(buf), - "fail to call unlinked import function (%s, %s)", - import_func->module_name, import_func->func_name); - aot_set_exception(module_inst, buf); - return; - } - signature = import_func->signature; + bh_assert(func_idx < aot_module->import_func_count); + + import_func = aot_module->import_funcs + func_idx; + if (!func_ptr) { + snprintf(buf, sizeof(buf), + "fail to call unlinked import function (%s, %s)", + import_func->module_name, import_func->func_name); + aot_set_exception(module_inst, buf); + return false; } - wasm_runtime_invoke_native(exec_env, func_ptr, - func_type, signature, frame_lp, argc, argv_ret); + + signature = import_func->signature; + return wasm_runtime_invoke_native(exec_env, func_ptr, + func_type, signature, + frame_lp, argc, argv_ret); +} + +bool +aot_call_indirect(WASMExecEnv *exec_env, + uint32 func_type_idx, uint32 table_elem_idx, + uint32 *frame_lp, uint32 argc, uint32 *argv_ret) +{ + AOTModuleInstance *module_inst = (AOTModuleInstance*) + wasm_runtime_get_module_inst(exec_env); + AOTModule *aot_module = (AOTModule*)module_inst->aot_module.ptr; + uint32 *func_type_indexes = (uint32*)module_inst->func_type_indexes.ptr; + uint32 *table_data = (uint32*)module_inst->table_data.ptr; + AOTFuncType *func_type = aot_module->func_types[func_type_idx];; + void **func_ptrs = (void**)module_inst->func_ptrs.ptr, *func_ptr; + uint32 table_size = module_inst->table_size; + uint32 func_idx, func_type_idx1; + AOTImportFunc *import_func; + const char *signature = NULL; + char buf[128]; + + if (table_elem_idx >= table_size) { + aot_set_exception_with_id(module_inst, EXCE_UNDEFINED_ELEMENT); + return false; + } + + func_idx = table_data[table_elem_idx]; + if (func_idx == (uint32)-1) { + aot_set_exception_with_id(module_inst, EXCE_UNINITIALIZED_ELEMENT); + return false; + } + + func_type_idx1 = func_type_indexes[func_idx]; + if (!aot_is_wasm_type_equal(module_inst, func_type_idx, func_type_idx1)) { + aot_set_exception_with_id(module_inst, EXCE_INVALID_FUNCTION_TYPE_INDEX); + return false; + } + + if (func_idx < aot_module->import_func_count) { + /* Call native function */ + import_func = aot_module->import_funcs + func_idx; + signature = import_func->signature; + } + + if (!(func_ptr = func_ptrs[func_idx])) { + bh_assert(func_idx < aot_module->import_func_count); + import_func = aot_module->import_funcs + func_idx; + snprintf(buf, sizeof(buf), + "fail to call unlinked import function (%s, %s)", + import_func->module_name, import_func->func_name); + aot_set_exception(module_inst, buf); + return false; + } + + return wasm_runtime_invoke_native(exec_env, func_ptr, + func_type, signature, + frame_lp, argc, argv_ret); } diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h index 977d3ec9..32d80602 100644 --- a/core/iwasm/aot/aot_runtime.h +++ b/core/iwasm/aot/aot_runtime.h @@ -435,10 +435,15 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst, /** * Invoke native function from aot code */ -void +bool aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 *frame_lp, uint32 argc, uint32 *argv_ret); +bool +aot_call_indirect(WASMExecEnv *exec_env, + uint32 func_type_idx, uint32 table_elem_idx, + uint32 *frame_lp, uint32 argc, uint32 *argv_ret); + uint32 aot_get_plt_table_size(); diff --git a/core/iwasm/aot/arch/aot_reloc_aarch64.c b/core/iwasm/aot/arch/aot_reloc_aarch64.c new file mode 100644 index 00000000..b2e25065 --- /dev/null +++ b/core/iwasm/aot/arch/aot_reloc_aarch64.c @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_reloc.h" + +#define R_AARCH64_ADR_PREL_PG_HI21 275 +#define R_AARCH64_ADD_ABS_LO12_NC 277 +#define R_AARCH64_CALL26 283 + +static SymbolMap target_sym_map[] = { + REG_COMMON_SYMBOLS +}; + +static void +set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) +{ + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, "%s", string); +} + +SymbolMap * +get_target_symbol_map(uint32 *sym_num) +{ + *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap); + return target_sym_map; +} + +void +get_current_target(char *target_buf, uint32 target_buf_size) +{ + char *build_target = BUILD_TARGET; + char *p = target_buf, *p_end; + snprintf(target_buf, target_buf_size, "%s", build_target); + p_end = p + strlen(target_buf); + while (p < p_end) { + if (*p >= 'A' && *p <= 'Z') + *p++ += 'a' - 'A'; + else + p++; + } + if (!strcmp(target_buf, "aarch64")) + snprintf(target_buf, target_buf_size, "aarch64v8"); +} + +static uint32 +get_plt_item_size() +{ + /* 8*4 bytes instructions and 8 bytes symbol address */ + return 40; +} + +void +init_plt_table(uint8 *plt) +{ + uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap); + for (i = 0; i < num; i++) { + uint32 *p = (uint32*)plt; + *p++ = 0xd10023ff; /* sub sp, sp, #0x8 */ + *p++ = 0xf90003fe; /* str x30, [sp] */ + *p++ = 0x100000de; /* adr x30, #24 */ + *p++ = 0xf94003de; /* ldr x30, [x30] */ + *p++ = 0xd63f03c0; /* blr x30 */ + *p++ = 0xf94003fe; /* ldr x30, [sp] */ + *p++ = 0x910023ff; /* add sp, sp, #0x8 */ + *p++ = 0xd61f03c0; /* br x30 */ + /* symbol addr */ + *(uint64*)p = (uint64)(uintptr_t)target_sym_map[i].symbol_addr; + p += 2; + plt += get_plt_item_size(); + } +} + +uint32 +get_plt_table_size() +{ + return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap)); +} + +#define SIGN_EXTEND_TO_INT64(val, bits, val_ext) do { \ + int64 m = ((int64)1 << (bits - 1)); \ + val_ext = ((int64)val ^ m) - m; \ +} while (0) + +#define Page(expr) ((expr) & ~0xFFF) + +static bool +check_reloc_offset(uint32 target_section_size, + uint64 reloc_offset, uint32 reloc_data_size, + char *error_buf, uint32 error_buf_size) +{ + if (!(reloc_offset < (uint64)target_section_size + && reloc_offset + reloc_data_size <= (uint64)target_section_size)) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: invalid relocation offset."); + return false; + } + return true; +} + +bool +apply_relocation(AOTModule *module, + uint8 *target_section_addr, uint32 target_section_size, + uint64 reloc_offset, uint64 reloc_addend, + uint32 reloc_type, void *symbol_addr, int32 symbol_index, + char *error_buf, uint32 error_buf_size) +{ + switch (reloc_type) { + case R_AARCH64_CALL26: + { + void *S, *P = (void*)(target_section_addr + reloc_offset); + int64 X, A, initial_addend; + int32 insn, imm26; + + CHECK_RELOC_OFFSET(sizeof(int32)); + + insn = *(int32*)P; + imm26 = insn & 0x3FFFFFF; + SIGN_EXTEND_TO_INT64(imm26 << 2, 28, initial_addend); + A = initial_addend; + A += (int64)reloc_addend; + + if (symbol_index < 0) { + /* Symbol address itself is an AOT function. + * Apply relocation with the symbol directly. + * Suppose the symbol address is in +-128MB relative + * to the relocation address. + */ + S = symbol_addr; + } + else { + uint8 *plt; + if (reloc_addend > 0) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: relocate to plt table " + "with reloc addend larger than 0 is unsupported."); + return false; + } + /* Symbol address is not an AOT function, + * but a function of runtime or native. Its address is + * beyond of the +-128MB space. Apply relocation with + * the PLT which branch to the target symbol address. + */ + S = plt = (uint8*)module->code + module->code_size + - get_plt_table_size() + + get_plt_item_size() * symbol_index; + } + + /* S + A - P */ + X = (int64)S + A - (int64)P; + + /* Check overflow: +-128MB */ + if (X > (128 * BH_MB) || X < (-128 * BH_MB)) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "target address out of range."); + return false; + } + + /* write the imm26 back to instruction */ + *(int32*)P = (insn & 0xFC000000) | ((int32)((X >> 2) & 0x3FFFFFF)); + break; + } + + case R_AARCH64_ADR_PREL_PG_HI21: + { + void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset); + int64 X, A, initial_addend; + int32 insn, immhi19, immlo2, imm21; + + CHECK_RELOC_OFFSET(sizeof(int32)); + + insn = *(int32*)P; + immhi19 = (insn >> 5) & 0x7FFFF; + immlo2 = (insn >> 29) & 0x3; + imm21 = (immhi19 << 2) | immlo2; + + SIGN_EXTEND_TO_INT64(imm21 << 12, 33, initial_addend); + A = initial_addend; + A += (int64)reloc_addend; + + /* Page(S+A) - Page(P) */ + X = Page((int64)S + A) - Page((int64)P); + + /* Check overflow: +-4GB */ + if (X > ((int64)4 * BH_GB) || X < ((int64)-4 * BH_GB)) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "target address out of range."); + return false; + } + + /* write the imm21 back to instruction */ + immhi19 = (int32)(((X >> 12) >> 2) & 0x7FFFF); + immlo2 = (int32)((X >> 12) & 0x3); + *(int32*)P = (insn & 0x9F00001F) | (immlo2 << 29) | (immhi19 << 5); + + break; + } + + case R_AARCH64_ADD_ABS_LO12_NC: + { + void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset); + int64 X, A, initial_addend; + int32 insn, imm12; + + CHECK_RELOC_OFFSET(sizeof(int32)); + + insn = *(int32*)P; + imm12 = (insn >> 10) & 0xFFF; + + SIGN_EXTEND_TO_INT64(imm12, 12, initial_addend); + A = initial_addend; + A += (int64)reloc_addend; + + /* S + A */ + X = (int64)S + A; + + /* No need to check overflow for this reloction type */ + + /* write the imm12 back to instruction */ + *(int32*)P = (insn & 0xFFC003FF) | ((int32)((X & 0xFFF) << 10)); + break; + } + + default: + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, + "Load relocation section failed: " + "invalid relocation type %d.", + reloc_type); + return false; + } + + return true; +} + diff --git a/core/iwasm/aot/arch/aot_reloc_arm.c b/core/iwasm/aot/arch/aot_reloc_arm.c index 16ea56b1..c73f9324 100644 --- a/core/iwasm/aot/arch/aot_reloc_arm.c +++ b/core/iwasm/aot/arch/aot_reloc_arm.c @@ -9,10 +9,6 @@ #define R_ARM_JMP24 29 /* PC relative 24 bit (B/BL). */ #define R_ARM_ABS32 2 /* Direct 32 bit */ -#ifndef BH_MB -#define BH_MB 1024 * 1024 -#endif - void __divdi3(); void __udivdi3(); void __moddi3(); @@ -163,7 +159,7 @@ init_plt_table(uint8 *plt) /* nop */ *p++ = 0xe1a00000; /* symbol addr */ - *p++ = (uint32)(uintptr_t)target_sym_map[i].symbol_addr;; + *p++ = (uint32)(uintptr_t)target_sym_map[i].symbol_addr; plt += get_plt_item_size(); } } diff --git a/core/iwasm/aot/arch/aot_reloc_thumb.c b/core/iwasm/aot/arch/aot_reloc_thumb.c index af0c99d9..134f7abe 100644 --- a/core/iwasm/aot/arch/aot_reloc_thumb.c +++ b/core/iwasm/aot/arch/aot_reloc_thumb.c @@ -8,10 +8,6 @@ #define R_ARM_THM_CALL 10 /* PC relative (Thumb BL and ARMv5 Thumb BLX). */ #define R_ARM_THM_JMP24 30 /* B.W */ -#ifndef BH_MB -#define BH_MB 1024 * 1024 -#endif - void __divdi3(); void __udivdi3(); void __moddi3(); diff --git a/core/iwasm/aot/iwasm_aot.cmake b/core/iwasm/aot/iwasm_aot.cmake index 4166efb3..db26357e 100644 --- a/core/iwasm/aot/iwasm_aot.cmake +++ b/core/iwasm/aot/iwasm_aot.cmake @@ -13,6 +13,8 @@ if (${WAMR_BUILD_TARGET} STREQUAL "X86_64" OR ${WAMR_BUILD_TARGET} STREQUAL "AMD set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_64.c) elseif (${WAMR_BUILD_TARGET} STREQUAL "X86_32") set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_32.c) +elseif (${WAMR_BUILD_TARGET} MATCHES "AARCH64.*") + set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_aarch64.c) elseif (${WAMR_BUILD_TARGET} MATCHES "ARM.*") set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_arm.c) elseif (${WAMR_BUILD_TARGET} MATCHES "THUMB.*") diff --git a/core/iwasm/common/arch/invokeNative_aarch64.s b/core/iwasm/common/arch/invokeNative_aarch64.s new file mode 100644 index 00000000..7204a958 --- /dev/null +++ b/core/iwasm/common/arch/invokeNative_aarch64.s @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + .text + .align 2 + .global invokeNative + .type invokeNative,function + +/* + * Arguments passed in: + * + * x0 function ptr + * x1 argv + * x2 nstacks + */ + +invokeNative: + sub sp, sp, #0x30 + stp x19, x20, [sp, #0x20] /* save the registers */ + stp x21, x22, [sp, #0x10] + stp x23, x24, [sp, #0x0] + + mov x19, x0 /* x19 = function ptr */ + mov x20, x1 /* x20 = argv */ + mov x21, x2 /* x21 = nstacks */ + mov x22, sp /* save the sp before call function */ + + /* Fill in float-point registers */ + ldp d0, d1, [x20], #16 /* d0 = argv[0], d1 = argv[1] */ + ldp d2, d3, [x20], #16 /* d2 = argv[2], d3 = argv[3] */ + ldp d4, d5, [x20], #16 /* d4 = argv[4], d5 = argv[5] */ + ldp d6, d7, [x20], #16 /* d6 = argv[6], d7 = argv[7] */ + + /* Fill inteter registers */ + ldp x0, x1, [x20], #16 /* x0 = argv[8] = exec_env, x1 = argv[9] */ + ldp x2, x3, [x20], #16 /* x2 = argv[10], x3 = argv[11] */ + ldp x4, x5, [x20], #16 /* x4 = argv[12], x5 = argv[13] */ + ldp x6, x7, [x20], #16 /* x6 = argv[14], x7 = argv[15] */ + + /* Now x20 points to stack args */ + + /* Directly call the fucntion if no args in stack */ + cmp x21, #0 + beq call_func + + /* Fill all stack args: reserve stack space and fill ony by one */ + mov x23, sp + bic sp, x23, #15 /* Ensure stack is 16 bytes aligned */ + lsl x23, x21, #3 /* x23 = nstacks * 8 */ + add x23, x23, #15 /* x23 = (x23 + 15) & ~15 */ + bic x23, x23, #15 + sub sp, sp, x23 /* reserved stack space for stack arguments */ + mov x23, sp + +loop_stack_args: /* copy stack arguments to stack */ + cmp x21, #0 + beq call_func + ldr x24, [x20], #8 + str x24, [x23], #8 + sub x21, x21, #1 + b loop_stack_args + +call_func: + mov x20, x30 /* save x30(lr) */ + blr x19 + mov sp, x22 /* restore sp which is saved before calling fuction*/ + +return: + mov x30, x20 /* restore x30(lr) */ + ldp x19, x20, [sp, #0x20] /* restore the registers in stack */ + ldp x21, x22, [sp, #0x10] + ldp x23, x24, [sp, #0x0] + add sp, sp, #0x30 /* restore sp */ + ret + diff --git a/core/iwasm/common/iwasm_common.cmake b/core/iwasm/common/iwasm_common.cmake index 3e2acfd9..5dfd9ee2 100644 --- a/core/iwasm/common/iwasm_common.cmake +++ b/core/iwasm/common/iwasm_common.cmake @@ -26,6 +26,8 @@ elseif (${WAMR_BUILD_TARGET} MATCHES "THUMB.*") else () set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_thumb.s) endif () +elseif (${WAMR_BUILD_TARGET} MATCHES "AARCH64.*") + set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_aarch64.s) elseif (${WAMR_BUILD_TARGET} STREQUAL "MIPS") set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_mips.s) elseif (${WAMR_BUILD_TARGET} STREQUAL "XTENSA") diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index c5e651cf..b196de9f 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -1811,7 +1811,9 @@ fail: || defined(BUILD_TARGET_MIPS) \ || defined(BUILD_TARGET_XTENSA) */ -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) +#if defined(BUILD_TARGET_X86_64) \ + || defined(BUILD_TARGET_AMD_64) \ + || defined(BUILD_TARGET_AARCH64) typedef void (*GenericFunctionPointer)(); int64 invokeNative(GenericFunctionPointer f, uint64 *args, uint64 n_stacks); @@ -1832,8 +1834,12 @@ static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)(uintptr_t)invokeNative; #define MAX_REG_INTS 4 #else #define MAX_REG_FLOATS 8 +#if defined(BUILD_TARGET_AARCH64) +#define MAX_REG_INTS 8 +#else #define MAX_REG_INTS 6 -#endif +#endif /* end of defined(BUILD_TARGET_AARCH64 */ +#endif /* end of defined(_WIN32) || defined(_WIN32_) */ bool wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr, @@ -1963,4 +1969,6 @@ fail: return ret; } -#endif /* end of defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) */ +#endif /* end of defined(BUILD_TARGET_X86_64) \ + || defined(BUILD_TARGET_AMD_64) \ + || defined(BUILD_TARGET_AARCH64) */ diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c index 0634435b..72ea7c67 100644 --- a/core/iwasm/compilation/aot_emit_function.c +++ b/core/iwasm/compilation/aot_emit_function.c @@ -8,41 +8,17 @@ #include "aot_emit_control.h" #include "../aot/aot_runtime.h" -/* Check whether there was exception thrown, if yes, return directly */ static bool -check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +create_func_return_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) { + LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder); AOTFuncType *aot_func_type = func_ctx->aot_func->func_type; - LLVMBasicBlockRef block_curr, check_exce_succ; - LLVMValueRef value, cmp; - - /* Load the first byte of aot_module_inst->cur_exception, and check - whether it is '\0'. If yes, no exception was thrown. */ - if (!(value = LLVMBuildLoad(comp_ctx->builder, func_ctx->cur_exception, - "exce_value")) - || !(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, - value, I8_ZERO, "cmp"))) { - aot_set_last_error("llvm build icmp failed."); - return false; - } - - /* Add check exection success block */ - if (!(check_exce_succ = LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_exce_succ"))) { - aot_set_last_error("llvm add basic block failed."); - return false; - } - - block_curr = LLVMGetInsertBlock(comp_ctx->builder); - LLVMMoveBasicBlockAfter(check_exce_succ, block_curr); /* Create function return block if it isn't created */ if (!func_ctx->func_return_block) { if (!(func_ctx->func_return_block = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "func_ret"))) { + LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, "func_ret"))) { aot_set_last_error("llvm add basic block failed."); return false; } @@ -70,6 +46,42 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) } } + LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr); + return true; +} + +/* Check whether there was exception thrown, if yes, return directly */ +static bool +check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + LLVMBasicBlockRef block_curr, check_exce_succ; + LLVMValueRef value, cmp; + + /* Create function return block if it isn't created */ + if (!create_func_return_block(comp_ctx, func_ctx)) + return false; + + /* Load the first byte of aot_module_inst->cur_exception, and check + whether it is '\0'. If yes, no exception was thrown. */ + if (!(value = LLVMBuildLoad(comp_ctx->builder, func_ctx->cur_exception, + "exce_value")) + || !(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, + value, I8_ZERO, "cmp"))) { + aot_set_last_error("llvm build icmp failed."); + return false; + } + + /* Add check exection success block */ + if (!(check_exce_succ = LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, + "check_exce_succ"))) { + aot_set_last_error("llvm add basic block failed."); + return false; + } + + block_curr = LLVMGetInsertBlock(comp_ctx->builder); + LLVMMoveBasicBlockAfter(check_exce_succ, block_curr); + LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr); /* Create condition br */ if (!LLVMBuildCondBr(comp_ctx->builder, cmp, @@ -82,18 +94,59 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) return true; } +/* Check whether there was exception thrown, if yes, return directly */ +static bool +check_call_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMValueRef res) +{ + LLVMBasicBlockRef block_curr, check_call_succ; + LLVMValueRef cmp; + + /* Create function return block if it isn't created */ + if (!create_func_return_block(comp_ctx, func_ctx)) + return false; + + if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, + res, I8_ZERO, "cmp"))) { + aot_set_last_error("llvm build icmp failed."); + return false; + } + + /* Add check exection success block */ + if (!(check_call_succ = LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, + "check_exce_succ"))) { + aot_set_last_error("llvm add basic block failed."); + return false; + } + + block_curr = LLVMGetInsertBlock(comp_ctx->builder); + LLVMMoveBasicBlockAfter(check_call_succ, block_curr); + + LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr); + /* Create condition br */ + if (!LLVMBuildCondBr(comp_ctx->builder, cmp, + check_call_succ, func_ctx->func_return_block)) { + aot_set_last_error("llvm build cond br failed."); + return false; + } + + LLVMPositionBuilderAtEnd(comp_ctx->builder, check_call_succ); + return true; +} + static bool call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMValueRef func_idx, AOTFuncType *aot_func_type, LLVMTypeRef *param_types, LLVMValueRef *param_values, uint32 param_count, uint32 param_cell_num, LLVMTypeRef ret_type, uint8 wasm_ret_type, - LLVMValueRef *p_value_ret) + LLVMValueRef *p_value_ret, LLVMValueRef *p_res) { LLVMTypeRef func_type, func_ptr_type, func_param_types[5]; LLVMTypeRef ret_ptr_type, elem_ptr_type; LLVMValueRef func, elem_idx, elem_ptr; - LLVMValueRef func_param_values[5], value_ret, value_ret_ptr, res; + LLVMValueRef func_param_values[5], value_ret = NULL, value_ret_ptr, res; char buf[32], *func_name = "aot_invoke_native"; uint32 i, cell_num = 0; @@ -103,7 +156,7 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, func_param_types[2] = INT32_PTR_TYPE; /* frame_lp */ func_param_types[3] = I32_TYPE; /* argc */ func_param_types[4] = INT32_PTR_TYPE; /* argv_ret */ - if (!(func_type = LLVMFunctionType(VOID_TYPE, func_param_types, 5, false))) { + if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 5, false))) { aot_set_last_error("llvm add function type failed."); return false; } @@ -198,7 +251,8 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* call aot_invoke_native() function */ - if (!(LLVMBuildCall(comp_ctx->builder, func, func_param_values, 5, ""))) { + if (!(res = LLVMBuildCall(comp_ctx->builder, func, + func_param_values, 5, "res"))) { aot_set_last_error("llvm build call failed."); return false; } @@ -207,6 +261,7 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* get function return value */ *p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret"); + *p_res = res; return true; } @@ -221,7 +276,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, AOTFuncType *func_type; LLVMTypeRef *param_types = NULL, ret_type; LLVMValueRef *param_values = NULL, value_ret = NULL, func; - LLVMValueRef import_func_idx; + LLVMValueRef import_func_idx, res; int32 i, j = 0, param_count; uint64 total_size; uint8 wasm_ret_type; @@ -292,13 +347,17 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, if (!call_aot_invoke_native_func(comp_ctx, func_ctx, import_func_idx, func_type, param_types + 1, param_values + 1, param_count, param_cell_num, - ret_type, wasm_ret_type, &value_ret)) + ret_type, wasm_ret_type, &value_ret, &res)) + goto fail; + + /* Check whether there was exception thrown when executing the function */ + if (!check_call_return(comp_ctx, func_ctx, res)) goto fail; } else { func = func_ctxes[func_idx - import_func_count]->func; - /* Call the function */ + /* Call the function */ if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func, param_values, (uint32)param_count + 1, (func_type->result_count > 0 @@ -309,15 +368,15 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Set calling convention for the call with the func's calling convention */ LLVMSetInstructionCallConv(value_ret, LLVMGetFunctionCallConv(func)); + + /* Check whether there was exception thrown when executing the function */ + if (!check_exception_thrown(comp_ctx, func_ctx)) + goto fail; } if (func_type->result_count > 0) PUSH(value_ret, func_type->types[func_type->param_count]); - /* Check whether there was exception thrown when executing the function */ - if (!check_exception_thrown(comp_ctx, func_ctx)) - goto fail; - ret = true; fail: if (param_types) @@ -327,21 +386,148 @@ fail: return ret; } +static bool +call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + AOTFuncType *aot_func_type, + LLVMValueRef func_type_idx, LLVMValueRef table_elem_idx, + LLVMTypeRef *param_types, LLVMValueRef *param_values, + uint32 param_count, uint32 param_cell_num, + LLVMTypeRef ret_type, uint8 wasm_ret_type, + LLVMValueRef *p_value_ret, LLVMValueRef *p_res) +{ + LLVMTypeRef func_type, func_ptr_type, func_param_types[6]; + LLVMTypeRef ret_ptr_type, elem_ptr_type; + LLVMValueRef func, elem_idx, elem_ptr; + LLVMValueRef func_param_values[6], value_ret = NULL, value_ret_ptr, res = NULL; + char buf[32], *func_name = "aot_call_indirect"; + uint32 i, cell_num = 0; + + /* prepare function type of aot_call_indirect */ + func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */ + func_param_types[1] = I32_TYPE; /* func_type_idx */ + func_param_types[2] = I32_TYPE; /* table_elem_idx */ + func_param_types[3] = INT32_PTR_TYPE; /* frame_lp */ + func_param_types[4] = I32_TYPE; /* argc */ + func_param_types[5] = INT32_PTR_TYPE; /* argv_ret */ + if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 6, false))) { + aot_set_last_error("llvm add function type failed."); + return false; + } + + /* prepare function pointer */ + if (comp_ctx->is_jit_mode) { + if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { + aot_set_last_error("create LLVM function type failed."); + return false; + } + + /* JIT mode, call the function directly */ + if (!(func = I64_CONST((uint64)(uintptr_t)aot_call_indirect)) + || !(func = LLVMConstIntToPtr(func, func_ptr_type))) { + aot_set_last_error("create LLVM value failed."); + return false; + } + } + else { + if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) + && !(func = LLVMAddFunction(comp_ctx->module, + func_name, func_type))) { + aot_set_last_error("add LLVM function failed."); + return false; + } + } + + if (param_count > 64) { + aot_set_last_error("prepare native arguments failed: " + "maximum 64 parameter cell number supported."); + return false; + } + + /* prepare frame_lp */ + for (i = 0; i < param_count; i++) { + if (!(elem_idx = I32_CONST(cell_num)) + || !(elem_ptr_type = LLVMPointerType(param_types[i], 0))) { + aot_set_last_error("llvm add const or pointer type failed."); + return false; + } + + snprintf(buf, sizeof(buf), "%s%d", "elem", i); + if (!(elem_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, + func_ctx->argv_buf, &elem_idx, 1, buf)) + || !(elem_ptr = LLVMBuildBitCast(comp_ctx->builder, elem_ptr, + elem_ptr_type, buf))) { + aot_set_last_error("llvm build bit cast failed."); + return false; + } + + if (!(res = LLVMBuildStore(comp_ctx->builder, param_values[i], elem_ptr))) { + aot_set_last_error("llvm build store failed."); + return false; + } + LLVMSetAlignment(res, 1); + + cell_num += wasm_value_type_cell_num(aot_func_type->types[i]); + } + + if (wasm_ret_type != VALUE_TYPE_VOID) { + if (!(ret_ptr_type = LLVMPointerType(ret_type, 0))) { + aot_set_last_error("llvm add pointer type failed."); + return false; + } + + if (!(value_ret = LLVMBuildBitCast(comp_ctx->builder, func_ctx->argv_buf, + ret_ptr_type, "argv_ret"))) { + aot_set_last_error("llvm build bit cast failed."); + return false; + } + + /* convert to int32 pointer */ + if (!(value_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, value_ret, + INT32_PTR_TYPE, "argv_ret_ptr"))) { + aot_set_last_error("llvm build store failed."); + return false; + } + } + else { + value_ret_ptr = LLVMConstNull(INT32_PTR_TYPE); + } + + func_param_values[0] = func_ctx->exec_env; + func_param_values[1] = func_type_idx; + func_param_values[2] = table_elem_idx; + func_param_values[3] = func_ctx->argv_buf; + func_param_values[4] = I32_CONST(param_cell_num); + func_param_values[5] = value_ret_ptr; + + if (!func_param_values[4]) { + aot_set_last_error("llvm create const failed."); + return false; + } + + /* call aot_call_indirect() function */ + if (!(res = LLVMBuildCall(comp_ctx->builder, func, + func_param_values, 6, "res"))) { + aot_set_last_error("llvm build call failed."); + return false; + } + + if (wasm_ret_type != VALUE_TYPE_VOID) + /* get function return value */ + *p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret"); + + *p_res = res; + return true; +} + bool aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, uint32 type_idx) { AOTFuncType *func_type; - LLVMValueRef elem_idx, table_elem, func_idx, ftype_idx_ptr, ftype_idx; - LLVMValueRef cmp_elem_idx, cmp_func_idx, is_ftype_match, is_ftype_mismatch; - LLVMValueRef func, func_ptr, func_const, table_size_const, cmp_func_ptr; - LLVMValueRef *param_values = NULL, param_values_tmp[3], value_ret; - LLVMTypeRef *param_types = NULL, param_types_tmp[3], ret_type, - f_type, f_ptr_type; - LLVMBasicBlockRef check_elem_idx_succ, check_ftype_idx_succ; - LLVMBasicBlockRef check_func_idx_succ, check_func_ptr_succ; - char *func_name = "aot_is_wasm_type_equal"; - int32 i, j = 0, param_count; + LLVMValueRef elem_idx, ftype_idx; + LLVMValueRef *param_values = NULL, value_ret = NULL, res = NULL; + LLVMTypeRef *param_types = NULL, ret_type; + int32 i, param_count; uint32 param_cell_num; uint64 total_size; uint8 wasm_ret_type; @@ -353,210 +539,26 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return false; } + ftype_idx = I32_CONST(type_idx); + CHECK_LLVM_CONST(ftype_idx); + func_type = comp_ctx->comp_data->func_types[type_idx]; param_cell_num = wasm_type_param_cell_num(func_type); POP_I32(elem_idx); - table_size_const = I32_CONST(comp_ctx->comp_data->table_size); - CHECK_LLVM_CONST(table_size_const); - - /* Check if (uint32)elem index >= table size */ - if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, - elem_idx, table_size_const, - "cmp_elem_idx"))) { - aot_set_last_error("llvm build icmp failed."); - goto fail; - } - - /* Throw exception if elem index >= table size */ - if (!(check_elem_idx_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_elem_idx_succ"))) { - aot_set_last_error("llvm add basic block failed."); - goto fail; - } - - LLVMMoveBasicBlockAfter(check_elem_idx_succ, - LLVMGetInsertBlock(comp_ctx->builder)); - - if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNDEFINED_ELEMENT, - true, cmp_elem_idx, check_elem_idx_succ))) - goto fail; - - /* Load function index */ - if (!(table_elem = LLVMBuildInBoundsGEP(comp_ctx->builder, - func_ctx->table_base, - &elem_idx, 1, "table_elem"))) { - aot_set_last_error("llvm build add failed."); - goto fail; - } - - if (!(func_idx = LLVMBuildLoad(comp_ctx->builder, table_elem, "func_idx"))) { - aot_set_last_error("llvm build load failed."); - goto fail; - } - - /* Check if func_idx == -1 */ - if (!(cmp_func_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, - func_idx, I32_NEG_ONE, - "cmp_func_idx"))) { - aot_set_last_error("llvm build icmp failed."); - goto fail; - } - - /* Throw exception if func_idx == -1 */ - if (!(check_func_idx_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_func_idx_succ"))) { - aot_set_last_error("llvm add basic block failed."); - goto fail; - } - - LLVMMoveBasicBlockAfter(check_func_idx_succ, - LLVMGetInsertBlock(comp_ctx->builder)); - - if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNINITIALIZED_ELEMENT, - true, cmp_func_idx, check_func_idx_succ))) - goto fail; - - /* Load function type index */ - if (!(ftype_idx_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, - func_ctx->func_type_indexes, - &func_idx, 1, - "ftype_idx_ptr"))) { - aot_set_last_error("llvm build inbounds gep failed."); - goto fail; - } - - if (!(ftype_idx = LLVMBuildLoad(comp_ctx->builder, ftype_idx_ptr, - "ftype_idx"))) { - aot_set_last_error("llvm build load failed."); - goto fail; - } - - /* Call aot_is_type_equal() to check whether function type match */ - param_types_tmp[0] = INT8_PTR_TYPE; - param_types_tmp[1] = I32_TYPE; - param_types_tmp[2] = I32_TYPE; - ret_type = INT8_TYPE; - - /* Create function type */ - if (!(f_type = LLVMFunctionType(ret_type, param_types_tmp, - 3, false))) { - aot_set_last_error("create LLVM function type failed."); - goto fail; - } - - if (comp_ctx->is_jit_mode) { - /* Create function type */ - if (!(f_ptr_type = LLVMPointerType(f_type, 0))) { - aot_set_last_error("create LLVM function type failed."); - goto fail; - } - /* Create LLVM function with const function pointer */ - if (!(func_const = I64_CONST((uint64)(uintptr_t)aot_is_wasm_type_equal)) - || !(func = LLVMConstIntToPtr(func_const, f_ptr_type))) { - aot_set_last_error("create LLVM value failed."); - goto fail; - } - } - else { - /* Create LLVM function with external function pointer */ - if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) - && !(func = LLVMAddFunction(comp_ctx->module, func_name, f_type))) { - aot_set_last_error("add LLVM function failed."); - goto fail; - } - } - - /* Call the aot_is_type_equal() function */ - param_values_tmp[0] = func_ctx->aot_inst; - param_values_tmp[1] = I32_CONST(type_idx); - param_values_tmp[2] = ftype_idx; - - CHECK_LLVM_CONST(param_values_tmp[1]); - - if (!(is_ftype_match = LLVMBuildCall(comp_ctx->builder, func, - param_values_tmp, 3, - "is_ftype_match"))) { - aot_set_last_error("llvm build icmp failed."); - goto fail; - } - - if (!(is_ftype_mismatch = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, - is_ftype_match, I8_ZERO, - "is_ftype_mismatch"))) { - aot_set_last_error("llvm build icmp failed."); - goto fail; - } - - if (!(check_ftype_idx_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_ftype_idx_success"))) { - aot_set_last_error("llvm add basic block failed."); - goto fail; - } - - LLVMMoveBasicBlockAfter(check_ftype_idx_succ, - LLVMGetInsertBlock(comp_ctx->builder)); - - if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INVALID_FUNCTION_TYPE_INDEX, - true, is_ftype_mismatch, check_ftype_idx_succ))) - goto fail; - - /* Load function pointer */ - if (!(func_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->func_ptrs, - &func_idx, 1, "func_ptr"))) { - aot_set_last_error("llvm build inbounds gep failed."); - goto fail; - } - - if (!(func = LLVMBuildLoad(comp_ctx->builder, func_ptr, "func_tmp"))) { - aot_set_last_error("llvm build load failed."); - goto fail; - } - - /* Check whether import function is NULL */ - if (!(cmp_func_ptr = LLVMBuildIsNull(comp_ctx->builder, func, "is_func_null"))) { - aot_set_last_error("llvm build is null failed."); - goto fail; - } - - /* Throw exception if import function is NULL */ - if (!(check_func_ptr_succ = - LLVMAppendBasicBlockInContext(comp_ctx->context, - func_ctx->func, - "check_func_ptr_succ"))) { - aot_set_last_error("llvm add basic block failed."); - goto fail; - } - - LLVMMoveBasicBlockAfter(check_func_ptr_succ, - LLVMGetInsertBlock(comp_ctx->builder)); - - if (!(aot_emit_exception(comp_ctx, func_ctx, - EXCE_CALL_UNLINKED_IMPORT_FUNC, - true, cmp_func_ptr, check_func_ptr_succ))) - goto fail; - /* Initialize parameter types of the LLVM function */ param_count = (int32)func_type->param_count; - total_size = sizeof(LLVMTypeRef) * (uint64)(param_count + 1); + total_size = sizeof(LLVMTypeRef) * (uint64)param_count; if (total_size >= UINT32_MAX || !(param_types = wasm_runtime_malloc((uint32)total_size))) { aot_set_last_error("Allocate memory failed."); goto fail; } - j = 0; - param_types[j++] = comp_ctx->exec_env_type; for (i = 0; i < param_count; i++) - param_types[j++] = TO_LLVM_TYPE(func_type->types[i]); + param_types[i] = TO_LLVM_TYPE(func_type->types[i]); /* Resolve return type of the LLVM function */ if (func_type->result_count) { @@ -569,32 +571,30 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } /* Allocate memory for parameters */ - total_size = sizeof(LLVMValueRef) * (uint64)(param_count + 1); + total_size = sizeof(LLVMValueRef) * (uint64)param_count; if (total_size >= UINT32_MAX || !(param_values = wasm_runtime_malloc((uint32)total_size))) { aot_set_last_error("Allocate memory failed."); goto fail; } - /* First parameter is exec env */ - j = 0; - param_values[j++] = func_ctx->exec_env; - /* Pop parameters from stack */ for (i = param_count - 1; i >= 0; i--) - POP(param_values[i + j], func_type->types[i]); + POP(param_values[i], func_type->types[i]); - if (!call_aot_invoke_native_func(comp_ctx, func_ctx, func_idx, func_type, - param_types + 1, param_values + 1, + if (!call_aot_call_indirect_func(comp_ctx, func_ctx, + func_type, ftype_idx, elem_idx, + param_types, param_values, param_count, param_cell_num, - ret_type, wasm_ret_type, &value_ret)) + ret_type, wasm_ret_type, + &value_ret, &res)) goto fail; if (func_type->result_count > 0) PUSH(value_ret, func_type->types[func_type->param_count]); /* Check whether there was exception thrown when executing the function */ - if (!check_exception_thrown(comp_ctx, func_ctx)) + if (!check_call_return(comp_ctx, func_ctx, res)) goto fail; ret = true; diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index 80857dd5..c903a0c8 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -741,6 +741,18 @@ static ArchItem valid_archs[] = { { "x86_64", false }, { "i386", false }, { "mips", true }, + { "aarch64v8", false }, + { "aarch64v8.1", false }, + { "aarch64v8.2", false }, + { "aarch64v8.3", false }, + { "aarch64v8.4", false }, + { "aarch64v8.5", false }, + { "aarch64_bev8", false }, /* big endian */ + { "aarch64_bev8.1", false }, + { "aarch64_bev8.2", false }, + { "aarch64_bev8.3", false }, + { "aarch64_bev8.4", false }, + { "aarch64_bev8.5", false }, { "armv4", true }, { "armv4t", true }, { "armv5t", true }, @@ -939,6 +951,10 @@ aot_create_comp_context(AOTCompData *comp_data, arch = "thumbv4t"; else if (!strcmp(arch, "thumbeb")) arch = "thumbv4teb"; + else if (!strcmp(arch, "aarch64")) + arch = "aarch64v8"; + else if (!strcmp(arch, "aarch64_be")) + arch = "aarch64_bev8"; } /* Check target arch */ diff --git a/doc/build_wamr.md b/doc/build_wamr.md index ea863738..602892a4 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -23,7 +23,7 @@ The script `runtime_lib.cmake` defined a number of variables for configuring the - **WAMR_BUILD_PLATFORM**: set the target platform. It can be set to any platform name (folder name) under folder [core/shared/platform](../core/shared/platform). -- **WAMR_BUILD_TARGET**: set the target CPU architecture. Current supported targets: X86_64, X86_32, ARM, THUMB, XTENSA and MIPS. For ARM and THUMB, the format is [][_VFP] where is the ARM sub-architecture and the "_VFP" suffix means VFP coprocessor registers s0-s15 (d0-d7) are used for passing arguments or returning results in standard procedure-call. Both and [_VFP] are optional. e.g. ARMV7, ARMV7_VFP, THUMBV7, THUMBV7_VFP and so on. +- **WAMR_BUILD_TARGET**: set the target CPU architecture. Current supported targets: X86_64, X86_32, AArch64, ARM, THUMB, XTENSA and MIPS. For AArch64, ARM and THUMB, the format is [][_VFP] where is the ARM sub-architecture and the "_VFP" suffix means VFP coprocessor registers s0-s15 (d0-d7) are used for passing arguments or returning results in standard procedure-call. Both and "_VFP" are optional. e.g. AARCH64, AARCH64V8, AARCHV8.1, ARMV7, ARMV7_VFP, THUMBV7, THUMBV7_VFP and so on. ```bash cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM @@ -229,6 +229,10 @@ source ../../zephyr-env.sh ``` Bash ./build.sh stm32 ``` +3. build for AArch64 (qemu_cortex_a53) +``` Bash +./build.sh qemu_cortex_a53 +``` Note: WAMR provides some features which can be easily configured by passing options to cmake, please see [Linux platform](./build_wamr.md#linux) for details. Currently in Zephyr, interpreter, AoT and builtin libc are enabled by default. @@ -272,6 +276,7 @@ AliOS-Things aos make helloworld@linuxhost -c config aos make ./out/helloworld@linuxhost/binary/helloworld@linuxhost.elf + ``` ``` For developerkit: @@ -279,8 +284,8 @@ AliOS-Things ``` C WAMR_BUILD_TARGET := THUMBV7M - ``` - +``` + ``` Bash aos make helloworld@developerkit -c config aos make diff --git a/product-mini/platforms/android/CMakeLists.txt b/product-mini/platforms/android/CMakeLists.txt index b7fa6882..26f9c737 100644 --- a/product-mini/platforms/android/CMakeLists.txt +++ b/product-mini/platforms/android/CMakeLists.txt @@ -27,7 +27,7 @@ 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[sub]", "THUMB[sub]", "MIPS", "XTENSA" +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" if (NOT DEFINED WAMR_BUILD_TARGET) if (CMAKE_SIZEOF_VOID_P EQUAL 8) # Build as X86_64 by default in 64-bit platform diff --git a/product-mini/platforms/linux/CMakeLists.txt b/product-mini/platforms/linux/CMakeLists.txt index 0512c835..fd8657a9 100644 --- a/product-mini/platforms/linux/CMakeLists.txt +++ b/product-mini/platforms/linux/CMakeLists.txt @@ -12,7 +12,7 @@ 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[sub]", "THUMB[sub]", "MIPS", "XTENSA" +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" if (NOT DEFINED WAMR_BUILD_TARGET) if (CMAKE_SIZEOF_VOID_P EQUAL 8) # Build as X86_64 by default in 64-bit platform diff --git a/product-mini/platforms/zephyr/simple/CMakeLists.txt b/product-mini/platforms/zephyr/simple/CMakeLists.txt index c55de4a7..60aab2ba 100644 --- a/product-mini/platforms/zephyr/simple/CMakeLists.txt +++ b/product-mini/platforms/zephyr/simple/CMakeLists.txt @@ -10,7 +10,7 @@ enable_language (ASM) set (WAMR_BUILD_PLATFORM "zephyr") -# Build as X86_32 by default, change to "ARM[sub]", "THUMB[sub]", "MIPS" or "XTENSA" +# Build as X86_32 by default, change to "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS" or "XTENSA" # if we want to support arm, thumb, mips or xtensa if (NOT DEFINED WAMR_BUILD_TARGET) set (WAMR_BUILD_TARGET "X86_32") diff --git a/product-mini/platforms/zephyr/simple/build.sh b/product-mini/platforms/zephyr/simple/build.sh index 32a2c400..6656baf0 100755 --- a/product-mini/platforms/zephyr/simple/build.sh +++ b/product-mini/platforms/zephyr/simple/build.sh @@ -5,13 +5,15 @@ X86_TARGET="x86" STM32_TARGET="stm32" +QEMU_CORTEX_A53="qemu_cortex_a53" if [ $# != 1 ] ; then echo "USAGE:" - echo "$0 $X86_TARGET|$STM32_TARGET" + echo "$0 $X86_TARGET|$STM32_TARGET|$QEMU_CORTEX_A53" echo "Example:" echo " $0 $X86_TARGET" echo " $0 $STM32_TARGET" + echo " $0 $QEMU_CORTEX_A53" exit 1 fi @@ -29,6 +31,12 @@ elif [ "$TARGET" = "$STM32_TARGET" ] ; then cmake -GNinja -DBOARD=nucleo_f767zi -DWAMR_BUILD_TARGET=THUMBV7 .. ninja ninja flash +elif [ "$TARGET" = "$QEMU_CORTEX_A53" ] ; then + cp prj_qemu_cortex_a53.conf prj.conf + rm -fr build && mkdir build && cd build + cmake -GNinja -DBOARD=qemu_cortex_a53 -DWAMR_BUILD_TARGET=AARCH64 .. + ninja + ninja run else echo "unsupported target: $TARGET" exit 1 diff --git a/product-mini/platforms/zephyr/simple/prj_qemu_cortex_a53.conf b/product-mini/platforms/zephyr/simple/prj_qemu_cortex_a53.conf new file mode 100644 index 00000000..d248565f --- /dev/null +++ b/product-mini/platforms/zephyr/simple/prj_qemu_cortex_a53.conf @@ -0,0 +1,7 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +CONFIG_ARM_MMU=n +CONFIG_STACK_SENTINEL=y +CONFIG_PRINTK=y +CONFIG_LOG=y diff --git a/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt b/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt index 7a5a9a60..005358c7 100644 --- a/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt +++ b/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt @@ -10,6 +10,9 @@ set (WAMR_BUILD_PLATFORM "zephyr") enable_language (ASM) +add_definitions(-DWA_MALLOC=wasm_runtime_malloc) +add_definitions(-DWA_FREE=wasm_runtime_free) + # Build as THUMB by default # change to "ARM[sub]", "THUMB[sub]", "X86_32", "MIPS" or "XTENSA" # if we want to support arm_32, x86, mips or xtensa diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c index 9b5fa286..c229daec 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c @@ -345,7 +345,7 @@ static host_interface interface = { .send = uart_send, .destroy = uart_destroy } #endif #ifdef __x86_64__ -static char global_heap_buf[400 * 1024] = { 0 }; +static char global_heap_buf[420 * 1024] = { 0 }; #else static char global_heap_buf[270 * 1024] = { 0 }; #endif diff --git a/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt index 7458080d..723ff8fa 100644 --- a/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt +++ b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt @@ -10,6 +10,9 @@ set (WAMR_BUILD_PLATFORM "zephyr") enable_language (ASM) +add_definitions(-DWA_MALLOC=wasm_runtime_malloc) +add_definitions(-DWA_FREE=wasm_runtime_free) + # Build as THUMB by default # change to "ARM[sub]", "THUMB[sub]", "X86_32", "MIPS_32" or "XTENSA_32" # if we want to support arm_32, x86, mips or xtensa diff --git a/test-tools/component_test/README.md b/test-tools/component_test/README.md new file mode 100644 index 00000000..c72d0fcb --- /dev/null +++ b/test-tools/component_test/README.md @@ -0,0 +1,56 @@ +# Component Test + +The purpose of this test suite is to verify the basic components of WAMR work well in combination. It is highly recommended to run pass all suites before each commitment. + +Prerequisites +============== +- clang is available to build wasm application. +- python is installed to run test script. + + +Run the test +============= +``` +start.py [-h] [-s SUITE_ID [SUITE_ID ...]] [-t CASE_ID [CASE_ID ...]] + [-n REPEAT_TIME] [--shuffle_all] + [--cases_list CASES_LIST_FILE_PATH] [--skip_proc] + [-b BINARIES] [-d] [--rebuild] +``` +It builds out the simple project binary including WAMR runtime binary ```simple``` and the testing tool ```host_tool``` before running the test suites. + +Test output is like: +``` +Test Execution Summary: + Success: 8 + Cases fails: 0 + Setup fails: 0 + Case load fails: 0 + + +------------------------------------------------------------ +The run folder is [run-03-23-16-29] +that's all. bye +kill to quit.. +Killed +``` + +The detailed report and log is generated in ```run``` folder. The binaries copy is also put in that folder. + +Usage samples +============== + +Run default test suite: +
+```python start.py``` + +Rebuild all test apps and then run default test suite: +
+```python start.py --rebuild``` + +Run a specified test suite: +
+```python start.py -s 01-life-cycle``` + +Run a specified test case: +
+```python start.py -t 01-install``` \ No newline at end of file diff --git a/test-tools/component_test/__init__.py b/test-tools/component_test/__init__.py new file mode 100644 index 00000000..fd734d56 --- /dev/null +++ b/test-tools/component_test/__init__.py @@ -0,0 +1,11 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +__all__ = [ + "net_manager", "wifi_daemon_utils" +] + +__author__ = "" +__package__ = "model" +__version__ = "1.0" diff --git a/test-tools/component_test/framework/__init__.py b/test-tools/component_test/framework/__init__.py new file mode 100644 index 00000000..fd734d56 --- /dev/null +++ b/test-tools/component_test/framework/__init__.py @@ -0,0 +1,11 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +__all__ = [ + "net_manager", "wifi_daemon_utils" +] + +__author__ = "" +__package__ = "model" +__version__ = "1.0" diff --git a/test-tools/component_test/framework/case_base.py b/test-tools/component_test/framework/case_base.py new file mode 100644 index 00000000..311de5ea --- /dev/null +++ b/test-tools/component_test/framework/case_base.py @@ -0,0 +1,29 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import os +import json +from test.test_support import _run_suite + +class CTestCaseBase(object): + def __init__(self, suite): + self.m_suite = suite + return + def on_get_case_description(self): + return "Undefined" + + def on_setup_case(self): + return True, '' + + def on_cleanup_case(self): + return True, '' + + # called by the framework + def on_run_case(self): + return True, '' + + def get_suite(self): + return self.m_suite + diff --git a/test-tools/component_test/framework/engine.py b/test-tools/component_test/framework/engine.py new file mode 100644 index 00000000..48911d19 --- /dev/null +++ b/test-tools/component_test/framework/engine.py @@ -0,0 +1,38 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import datetime +import os +import pprint +import random +import re +import shlex +import subprocess +import signal +import sys +import time + +from .test_utils import * +from .test_api import * + + + + +def read_cases_from_file(file_path): + if not os.path.exists(file_path): + return False, None + + with open(file_path, 'r') as f: + content = f.readlines() + + content = [x.strip() for x in content] + print content + if len(content) == 0: + return False, None + + return True, content + + + diff --git a/test-tools/component_test/framework/framework.py b/test-tools/component_test/framework/framework.py new file mode 100644 index 00000000..78e187fe --- /dev/null +++ b/test-tools/component_test/framework/framework.py @@ -0,0 +1,287 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import datetime +import os +import pprint +import random +import re +import shlex +import subprocess +import signal +import sys +import time +import shutil + +from .test_api import * +import this + + +''' +The run evironment dir structure: + + run/ + run{date-time}/ + suites/ + {suite name}/ + -- target/ (the target software being tested) + -- tools/ (the tools for testing the target software) +''' + + +framework=None + +def get_framework(): + global framework + return framework + +def my_import(name): + mod = __import__(name) + components = name.split('.') + for comp in components[1:]: + mod = getattr(mod, comp) + return mod + + +# we maintain a root path apart from framework location +# so the suites can be located in anywhere +class CTestFramework(object): + + def __init__(self, path): + self.running_case = '' + self.running_suite = '' + self.target_suites = {} + self.target_cases = {} + self.root_path = path + self.running_folder='' + self.report = None + self.sucess_cases = 0 + self.failed_cases = 0 + self.setup_fails = 0 + self.load_fails = 0; + global framework + framework = self + + api_set_root_path(path) + + print "root_path is " + self.root_path + + def gen_execution_stats(self): + return '\nTest Execution Summary: ' \ + '\n\tSuccess: {}' \ + '\n\tCases fails: {}' \ + '\n\tSetup fails: {}' \ + '\n\tCase load fails: {}'.format( + self.sucess_cases, self.failed_cases, self.setup_fails, self.load_fails) + + def report_result(self, success, message, case_description): + if self.report is None: + return + + case_pass = "pass" + if not success: + case_pass = "fail" + + self.report.write(case_pass + ": [" + self.running_case + "]\n\treason: " + \ + message + "\n\tcase: " + case_description + "\n") + return + + def get_running_path(self): + return self.root_path + "/run/" + self.running_folder + + def load_suites(self): + self.target_suites = os.listdir(self.root_path + "/suites") + return + + def run_case(self, suite_instance, case): + # load the test case module + case_description = '' + suite = suite_instance.m_name + api_log("\n>>start run [" + case + "] >>") + module_name = 'suites.' + suite + ".cases." + case + ".case" + try: + module = my_import(module_name) + except Exception, e: + report_fail("load case fail: " + str(e)) + api_log_error("load case fail: " + str(e)) + self.load_fails = self.load_fails +1 + print(traceback.format_exc()) + return False + + try: + case = module.CTestCase(suite_instance) + except Exception, e: + report_fail("initialize case fail: " + str(e)) + api_log_error("initialize case fail: " + str(e)) + self.load_fails = self.load_fails +1 + return False + + # call the case on setup callback + try: + case_description = case.on_get_case_description() + result, message = case.on_setup_case() + except Exception, e: + result = False + message = str(e); + if not result: + api_log_error(message) + report_fail (message, case_description) + self.failed_cases = self.failed_cases+1 + return False + + # call the case execution callaback + try: + result, message = case.on_run_case() + except Exception, e: + result = False + message = str(e); + if not result: + report_fail (message, case_description) + api_log_error(message) + self.failed_cases = self.failed_cases+1 + else: + report_success(case_description) + self.sucess_cases = self.sucess_cases +1 + + # call the case cleanup callback + try: + clean_result, message = case.on_cleanup_case() + except Exception, e: + clean_result = False + message = str(e) + + if not clean_result: + api_log(message) + + return result + + def run_suite(self, suite, cases): + # suite setup + message = '' + api_log("\n>>> Suite [" + suite + "] starting >>>") + running_folder = self.get_running_path()+ "/suites/" + suite; + + module_name = 'suites.' + suite + ".suite_setup" + try: + module = my_import(module_name) + except Exception, e: + report_fail("load suite [" + suite +"] fail: " + str(e)) + self.load_fails = self.load_fails +1 + return False + + try: + suite_instance = module.CTestSuite(suite, \ + self.root_path + '/suites/' + suite, running_folder) + except Exception, e: + report_fail("initialize suite fail: " + str(e)) + self.load_fails = self.load_fails +1 + return False + + result, message = suite_instance.load_settings() + if not result: + report_fail("load settings fail: " + str(e)) + self.load_fails = self.load_fails +1 + return False + + try: + result, message = suite_instance.on_suite_setup() + except Exception, e: + result = False + message = str(e); + if not result: + api_log_error(message) + report_fail (message) + self.setup_fails = self.setup_fails + 1 + return False + + self.running_suite = suite + + cases.sort() + + # run cases + for case in cases: + if not os.path.isdir(self.root_path + '/suites/' + suite + '/cases/' + case): + continue + + self.running_case = case + self.run_case(suite_instance, case) + self.running_case = '' + + # suites cleanup + self.running_suite = '' + try: + result, message = suite_instance.on_suite_cleanup() + except Exception, e: + result = False + message = str(e); + if not result: + api_log_error(message) + report_fail (message) + self.setup_fails = self.setup_fails + 1 + return + + def start_run(self): + if self.target_suites is None: + print "\n\nstart run: no target suites, exit.." + return + + cur_time = time.localtime() + time_prefix = "{:02}-{:02}-{:02}-{:02}".format( + cur_time.tm_mon, cur_time.tm_mday, cur_time.tm_hour, cur_time.tm_min) + + debug = api_get_value('debug', False) + if debug: + self.running_folder = 'debug' + else: + self.running_folder = 'run-' + time_prefix + + folder = self.root_path + "/run/" +self.running_folder; + + if os.path.exists(folder): + shutil.rmtree(folder, ignore_errors=True) + + if not os.path.exists(folder): + os.makedirs(folder ) + os.makedirs(folder + "/suites") + + api_init_log(folder + "/test.log") + + self.report = open(folder + "/report.txt", 'a') + + self.target_suites.sort() + + for suite in self.target_suites: + if not os.path.isdir(self.root_path + '/suites/' + suite): + continue + self.report.write("suite " + suite + " cases:\n") + if self.target_cases is None: + cases = os.listdir(self.root_path + "/suites/" + suite + "/cases") + self.run_suite(suite, cases) + else: + self.run_suite(suite, self.target_cases) + self.report.write("\n") + + self.report.write("\n\n") + summary = self.gen_execution_stats() + self.report.write(summary); + self.report.flush() + self.report.close() + print summary + + +def report_fail(message, case_description=''): + global framework + if framework is not None: + framework.report_result(False, message, case_description) + + api_log_error(message) + + return + +def report_success(case_description=''): + global framework + if framework is not None: + framework.report_result(True , "OK", case_description) + return diff --git a/test-tools/component_test/framework/suite.py b/test-tools/component_test/framework/suite.py new file mode 100644 index 00000000..2b690b08 --- /dev/null +++ b/test-tools/component_test/framework/suite.py @@ -0,0 +1,40 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import os +import json + +class CTestSuiteBase(object): + def __init__(self, name, suite_path, run_path): + self.suite_path=suite_path + self.run_path=run_path + self.m_name = name + self.settings = {} + + def get_settings_item(self, item): + if item in self.settings: + return self.settings[item] + else: + return None + + def load_settings(self): + path = self.suite_path + "/settings.cfg" + if os.path.isfile(path): + try: + fp = open(path, 'r') + self.settings = json.load(fp) + fp.close() + except Exception, e: + return False, 'Load settings fail: ' + e.message + return True, 'OK' + else: + return True, 'No file' + + def on_suite_setup(self): + return True, 'OK' + + def on_suite_cleanup(self): + return True, 'OK' + diff --git a/test-tools/component_test/framework/test_api.py b/test-tools/component_test/framework/test_api.py new file mode 100644 index 00000000..ed9391e2 --- /dev/null +++ b/test-tools/component_test/framework/test_api.py @@ -0,0 +1,98 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import logging +import threading +from .test_utils import * + +global logger +logger = None + +def api_init_log(log_path): + global logger + print "api_init_log: " + log_path + logger = logging.getLogger(__name__) + + logger.setLevel(level = logging.INFO) + handler = logging.FileHandler(log_path) + handler.setLevel(logging.INFO) + formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') + handler.setFormatter(formatter) + + console = logging.StreamHandler() + console.setLevel(logging.INFO) + + logger.addHandler(handler) + logger.addHandler(console) + + return + +def api_log(message): + global logger + if logger is None: + print message + else: + logger.info (message) + return + +def api_log_error(message): + global logger + if logger is None: + print message + else: + logger.error (message) + return + +def api_logv(message): + global logger + if logger is None: + print message + else: + logger.info(message) + return + +#####################################3 +global g_case_runner_event +def api_wait_case_event(timeout): + global g_case_runner_event + g_case_runner_event.clear() + g_case_runner_event.wait(timeout) + +def api_notify_case_runner(): + global g_case_runner_event + g_case_runner_event.set() + +def api_create_case_event(): + global g_case_runner_event + g_case_runner_event = threading.Event() + +####################################### + +def api_init_globals(): + global _global_dict + _global_dict = {} + +def api_set_value(name, value): + _global_dict[name] = value + +def api_get_value(name, defValue=None): + try: + return _global_dict[name] + except KeyError: + return defValue + + +######################################### +global root_path +def api_set_root_path(root): + global root_path + root_path = root + +def api_get_root_path(): + global root_path + return root_path; + + + diff --git a/test-tools/component_test/framework/test_utils.py b/test-tools/component_test/framework/test_utils.py new file mode 100644 index 00000000..1b8bbd01 --- /dev/null +++ b/test-tools/component_test/framework/test_utils.py @@ -0,0 +1,70 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import datetime +import os +import random +import re +import shlex +import subprocess +import sys +import time +import shutil +from subprocess import check_output, CalledProcessError + +def t_getPIDs(process): + try: + pidlist = map(int, check_output(["pidof", process]).split()) + except CalledProcessError: + pidlist = [] + #print process + ':list of PIDs = ' + ', '.join(str(e) for e in pidlist) + return pidlist + + +def t_kill_process_by_name(p_keywords): + pid_list = [] + ps_info = subprocess.check_output(shlex.split("ps aux")).split("\n") + for p in ps_info: + if p_keywords in p: + tmp = p.split(" ") + tmp = [x for x in tmp if len(x) > 0] + pid_list.append(tmp[1]) + + for pid in pid_list: + cmd = "kill -9 {}".format(pid) + subprocess.call(shlex.split(cmd)) + + return pid_list + + + +#proc -> name of the process +#kill = 1 -> search for pid for kill +#kill = 0 -> search for name (default) + +def t_process_exists(proc, kill = 0): + ret = False + processes = t_getPIDs(proc) + + for pid in processes: + if kill == 0: + return True + else: + print "kill [" + proc + "], pid=" + str(pid) + os.kill((pid), 9) + ret = True + return ret + +def t_copy_files(source_dir, pattern, dest_dir): + files = os.listdir(source_dir) + for file in files: + if file is '/' or file is '.' or file is '..': + continue + + if pattern == '*' or pattern is '' or files.endswith(pattern): + shutil.copy(source_dir+"/"+ file,dest_dir) + + + diff --git a/test-tools/component_test/harness/__init__.py b/test-tools/component_test/harness/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test-tools/component_test/harness/harness_api.py b/test-tools/component_test/harness/harness_api.py new file mode 100644 index 00000000..e35aa6b4 --- /dev/null +++ b/test-tools/component_test/harness/harness_api.py @@ -0,0 +1,150 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import os +import shutil +import subprocess +import json +import time + +from framework import test_api +from framework.test_utils import * + +output = "output.txt" + +def start_env(): + os.system("./start.sh") + +def stop_env(): + os.system("./stop.sh") + time.sleep(0.5) + os.chdir("../") #reset path for other cases in the same suite + +def check_is_timeout(): + line_num = 0 + ft = open(output, 'r') + lines = ft.readlines() + + for line in reversed(lines): + if (line[0:36] == "--------one operation begin.--------"): + break + line_num = line_num + 1 + + ft.close() + if (lines[-(line_num)] == "operation timeout"): + return True + else: + return False + +def parse_ret(file): + ft = open(file, 'a') + ft.writelines("\n") + ft.writelines("--------one operation finish.--------") + ft.writelines("\n") + ft.close() + + ft = open(file, 'r') + for line in reversed(ft.readlines()): + if (line[0:16] == "response status "): + ret = line[16:] + ft.close() + return int(ret) + +def run_host_tool(cmd, file): + ft = open(file, 'a') + ft.writelines("--------one operation begin.--------") + ft.writelines("\n") + ft.close() + os.system(cmd + " -o" + file) + if (check_is_timeout() == True): + return -1 + return parse_ret(file) + +def install_app(app_name, file_name): + return run_host_tool("./host_tool -i " + app_name + " -f ../test-app/" + file_name, output) + +def uninstall_app(app_name): + return run_host_tool("./host_tool -u " + app_name, output) + +def query_app(): + return run_host_tool("./host_tool -q ", output) + +def send_request(url, action, payload): + if (payload is None): + return run_host_tool("./host_tool -r " + url + " -A " + action, output) + else: + return run_host_tool("./host_tool -r " + url + " -A " + action + " -p " + payload, output) + +def register(url, timeout, alive_time): + return run_host_tool("./host_tool -s " + url + " -t " + str(timeout) + " -a " + str(alive_time), output) + +def deregister(url): + return run_host_tool("./host_tool -d " + url, output) + +def get_response_payload(): + line_num = 0 + ft = open(output, 'r') + lines = ft.readlines() + + for line in reversed(lines): + if (line[0:16] == "response status "): + break + line_num = line_num + 1 + + payload_lines = lines[-(line_num):-1] + ft.close() + + return payload_lines + +def check_query_apps(expected_app_list): + if (check_is_timeout() == True): + return False + json_lines = get_response_payload() + json_str = " ".join(json_lines) + json_dict = json.loads(json_str) + app_list = [] + + for key, value in json_dict.items(): + if key[0:6] == "applet": + app_list.append(value) + + if (sorted(app_list) == sorted(expected_app_list)): + return True + else: + return False + +def check_response_payload(expected_payload): + if (check_is_timeout() == True): + return False + json_lines = get_response_payload() + json_str = " ".join(json_lines) + + if (json_str.strip() != ""): + json_dict = json.loads(json_str) + else: + json_dict = {} + + if (json_dict == expected_payload): + return True + else: + return False + +def check_get_event(): + line_num = 0 + ft = open(output, 'r') + lines = ft.readlines() + + for line in reversed(lines): + if (line[0:16] == "response status "): + break + line_num = line_num + 1 + + payload_lines = lines[-(line_num):-1] + ft.close() + + if (payload_lines[1][0:17] == "received an event"): + return True + else: + return False diff --git a/test-tools/component_test/host-clients/src/host_app_sample.c b/test-tools/component_test/host-clients/src/host_app_sample.c new file mode 100644 index 00000000..1fb4ba12 --- /dev/null +++ b/test-tools/component_test/host-clients/src/host_app_sample.c @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include +#include "host_api.h" +#include "bi-inc/attr_container.h" +#include "er-coap-constants.h" + +static char *read_file_to_buffer(const char *filename, int *ret_size); +int send_request_to_applet_success = 0; +const char *label_for_request = "request1"; +int event_listener_counter = 0; +char *applet_buf[1024 * 1024]; +const char *host_agent_ip = "127.0.0.1"; +void f_aee_response_handler(void *usr_ctx, aee_response_t *response) +{ + if (response == NULL) { + printf("########## request timeout!!! \n"); + } else { + char *str = (char *) usr_ctx; + printf("#### dump response ####\n"); + printf("#### user data: %s \n", str); + printf("#### status: %d \n", response->status); + if (response->payload != NULL) + attr_container_dump((attr_container_t *) response->payload); + } +} + +void f_aee_event_listener(const char *url, void *event, int fmt) +{ + printf("######## event is received. url: %s, fmt:%d ############\n", url, + fmt); + + attr_container_t *attr_obj = (attr_container_t *) event; + + attr_container_dump(attr_obj); + /* + if (0 == strcmp(url, "alert/overheat")) + { + event_listener_counter++; + printf("event :%d \n", event_listener_counter); + } + */ +} + +static int print_menu_and_select(void) +{ + char s[256]; + int choice; + do { + printf("\n"); + printf("1. Install TestApplet1\n"); + printf("2. Install TestApplet2\n"); + printf("3. Install TestApplet3\n"); + printf("4. Uninstall TestApplet1\n"); + printf("5. Uninstall TestApplet2\n"); + printf("6. Uninstall TestApplet3\n"); + printf("7. Send Request to TestApplet1\n"); + printf("8. Register Event to TestApplet1\n"); + printf("9. UnRegister Event to TestApplet1\n"); + printf("a. Query Applets\n"); + printf("t. Auto Test\n"); + printf("q. Exit\n"); + printf("Please Select: "); + + if (fgets(s, sizeof(s), stdin)) { + if (!strncmp(s, "q", 1)) + return 0; + if (!strncmp(s, "a", 1)) + return 10; + if (!strncmp(s, "t", 1)) + return 20; + choice = atoi(s); + if (choice >= 1 && choice <= 9) + return choice; + } + } while (1); + return 0; +} + +static void install_applet(int index) +{ + char applet_name[64]; + char applet_file_name[64]; + char *buf; + int size; + int ret; + + printf("Installing TestApplet%d...\n", index); + snprintf(applet_name, sizeof(applet_name), "TestApplet%d", index); + snprintf(applet_file_name, sizeof(applet_file_name), "./TestApplet%d.wasm", + index); + buf = read_file_to_buffer(applet_file_name, &size); + if (!buf) { + printf("Install Applet failed: read file %s error.\n", + applet_file_name); + return; + } + + //step2. install applet + ret = aee_applet_install(buf, "wasm", size, applet_name, 5000); + if (ret) { + printf("%s install success\n", applet_name); + } + free(buf); +} + +static void uninstall_applet(int index) +{ + int ret; + char applet_name[64]; + snprintf(applet_name, sizeof(applet_name), "TestApplet%d", index); + ret = aee_applet_uninstall(applet_name, "wasm", 5000); + if (ret) { + printf("uninstall %s success\n", applet_name); + } else { + printf("uninstall %s failed\n", applet_name); + } +} + +static void send_request(int index) +{ + char url[64]; + int ret; + aee_request_t req; + const char *user_context = "label for request"; + attr_container_t *attr_obj = attr_container_create( + "Send Request to Applet"); + attr_container_set_string(&attr_obj, "String key", "Hello"); + attr_container_set_int(&attr_obj, "Int key", 1000); + attr_container_set_int64(&attr_obj, "Int64 key", 0x77BBCCDD11223344LL); + + //specify the target wasm app + snprintf(url, sizeof(url), "/app/TestApplet%d/url1", index); + + //not specify the target wasm app + //snprintf(url, sizeof(url), "url1"); + aee_request_init(&req, url, COAP_PUT); + aee_request_set_payload(&req, attr_obj, + attr_container_get_serialize_length(attr_obj), + PAYLOAD_FORMAT_ATTRIBUTE_OBJECT); + ret = aee_request_send(&req, f_aee_response_handler, (void *) user_context, + 10000); + + if (ret) { + printf("send request to TestApplet1 success\n"); + } +} + +static void register_event(const char *event_path) +{ + hostclient_register_event(event_path, f_aee_event_listener); +} + +static void unregister_event(const char *event_path) +{ + hostclient_unregister_event(event_path); +} + +static void query_applets() +{ + aee_applet_list_t applet_lst; + aee_applet_list_init(&applet_lst); + aee_applet_list(5000, &applet_lst); + aee_applet_list_clean(&applet_lst); +} + +static char * +read_file_to_buffer(const char *filename, int *ret_size) +{ + FILE *fl = NULL; + char *buffer = NULL; + int file_size = 0; + if (!(fl = fopen(filename, "rb"))) { + printf("file open failed\n"); + return NULL; + } + + fseek(fl, 0, SEEK_END); + file_size = ftell(fl); + + if (file_size == 0) { + printf("file length 0\n"); + return NULL; + } + + if (!(buffer = (char *) malloc(file_size))) { + fclose(fl); + return NULL; + } + + fseek(fl, 0, SEEK_SET); + + if (!fread(buffer, 1, file_size, fl)) { + printf("file read failed\n"); + return NULL; + } + + fclose(fl); + *ret_size = file_size; + return buffer; +} + +static void auto_test() +{ + int i; + int interval = 1000; /* ms */ + while (1) { + uninstall_applet(1); + uninstall_applet(2); + uninstall_applet(3); + install_applet(1); + install_applet(2); + install_applet(3); + + for (i = 0; i < 60 * 1000 / interval; i++) { + query_applets(); + send_request(1); + send_request(2); + send_request(3); + usleep(interval * 1000); + } + } +} + +void exit_program() +{ + hostclient_shutdown(); + exit(0); +} + +int + +main() +{ + bool ret; + + //step1. host client init + ret = hostclient_initialize(host_agent_ip, 3456); + + if (!ret) { + printf("host client initialize failed\n"); + return -1; + } + + do { + int choice = print_menu_and_select(); + printf("\n"); + + if (choice == 0) + exit_program(); + if (choice <= 3) + install_applet(choice); + else if (choice <= 6) + uninstall_applet(choice - 3); + else if (choice <= 7) + send_request(1); + else if (choice <= 8) + register_event("alert/overheat"); + else if (choice <= 9) + unregister_event("alert/overheat"); + else if (choice == 10) + query_applets(); + else if (choice == 20) + auto_test(); + } while (1); + + return 0; +} + +// Run program: Ctrl + F5 or Debug > Start Without Debugging menu +// Debug program: F5 or Debug > Start Debugging menu + +// Tips for Getting Started: +// 1. Use the Solution Explorer window to add/manage files +// 2. Use the Team Explorer window to connect to source control +// 3. Use the Output window to see build output and other messages +// 4. Use the Error List window to view errors +// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project +// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file diff --git a/test-tools/component_test/host-clients/src/makefile b/test-tools/component_test/host-clients/src/makefile new file mode 100644 index 00000000..763a60c3 --- /dev/null +++ b/test-tools/component_test/host-clients/src/makefile @@ -0,0 +1,44 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +CC = gcc +CFLAGS := -Wall -g + +# Add this to make compiler happy +CFLAGS += -DWASM_ENABLE_INTERP=1 + +host_api_c=../../../../host-agent/host-api-c +attr_container_dir=../../../../wamr/core/app-framework/app-native-shared +coap_dir=../../../../host-agent/coap +shared_dir=../../../../wamr/core/shared + +# core +INCLUDE_PATH = -I$(host_api_c)/src -I$(attr_container_dir)/ \ + -I$(coap_dir)/er-coap -I$(coap_dir)/er-coap/extension \ + -I$(shared_dir)/include \ + -I$(shared_dir)/utils \ + -I$(shared_dir)/platform/include/ \ + -I$(shared_dir)/platform/linux/ + +LIB := $(host_api_c)/src/libhostapi.a +EXE := ./hostapp + +App_C_Files := host_app_sample.c + +OBJS := $(App_C_Files:.c=.o) + +all: $(EXE) + +%.o: %.c + @$(CC) $(CFLAGS) -c $< -o $@ $(INCLUDE_PATH) + +$(EXE): $(OBJS) + @rm -f $(EXE) + @$(CC) $(OBJS) -o $(EXE) $(LIB) -lpthread -lrt + @rm -f $(OBJS) + +.PHONY: clean +clean: + rm -f $(OBJS) $(EXE) diff --git a/test-tools/component_test/set_dev_env.sh b/test-tools/component_test/set_dev_env.sh new file mode 100755 index 00000000..1abe23b8 --- /dev/null +++ b/test-tools/component_test/set_dev_env.sh @@ -0,0 +1,7 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +#!/bin/sh + diff --git a/test-tools/component_test/start.py b/test-tools/component_test/start.py new file mode 100755 index 00000000..062ec2e4 --- /dev/null +++ b/test-tools/component_test/start.py @@ -0,0 +1,151 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +#!/usr/bin/env python + +# -*- coding: utf-8 -*- +""" +It is the entrance of the iagent test framework. + +""" + +import argparse +import datetime +import os +import pprint +import random +import re +import shlex +import subprocess +import signal +import sys +import time + +sys.path.append('../../../app-sdk/python') +from framework.test_utils import * +from framework.framework import * + + +def signal_handler(signal, frame): + print('Pressed Ctrl+C!') + sys.exit(0) + +def Register_signal_handler(): + signal.signal(signal.SIGINT, signal_handler) +# signal.pause() + + +def flatten_args_list(l): + if l is None: + return None + + return [x for y in l for x in y] + + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description = "to run specific case(s) "\ + "in specific suite(s) with FC test framework") + parser.add_argument('-s', dest = 'suite_id', action = 'append', + nargs = '+', + help = 'one or multiple suite ids, which are also setup ids.'\ + 'by default if it isn\'t passed from argument, all '\ + 'suites are going to be run.') + parser.add_argument('-t', dest = 'case_id', action = 'append', + nargs = '+', + help = 'one or multiple cases ids.'\ + 'by default if it isn\'t passed from argument, all '\ + 'cases in specific suites are going to be run.') + parser.add_argument('-n', dest = 'repeat_time', action = 'store', + default = 1, + help = 'how many times do you want to run. there is 40s '\ + 'break time between two rounds. each round includs '\ + 'init_setup, run_test_case and deinit_setup.') + parser.add_argument('--shuffle_all', dest = 'shuffle_all', + default = False, action = 'store_true', + help = 'shuffle_all test cases in per test suite '\ + 'by default, all cases under per suite should '\ + 'be executed by input order.') + parser.add_argument('--cases_list', dest='cases_list_file_path', + default=None, + action='store', + help="read cases list from a flie ") + parser.add_argument('--skip_proc', dest='skip_proc', + default = False, action = 'store_true', + help='do not start the test process.'\ + 'sometimes the gw_broker process will be started in eclipse for debug purpose') + parser.add_argument('-b', dest = 'binaries', action = 'store', + help = 'The path of target folder ') + parser.add_argument('-d', dest = 'debug', action = 'store_true', + help = 'wait user to attach the target process after launch processes ') + parser.add_argument('--rebuild', dest = 'rebuild', action = 'store_true', + help = 'rebuild all test binaries') + args = parser.parse_args() + + print "------------------------------------------------------------" + print "parsing arguments ... ..." + print args + + ''' + logger = logging.getLogger('coapthon.server.coap') + logger.setLevel(logging.DEBUG) + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + logger.addHandler(console) + ''' + print "------------------------------------------------------------" + print "preparing wamr binary and test tools ... ..." + os.system("cd ../../samples/simple/ && bash build.sh -p host-interp") + + Register_signal_handler() + + api_init_globals(); + + api_create_case_event(); + + suites_list = flatten_args_list(args.suite_id) + cases_list = flatten_args_list(args.case_id) + + dirname, filename = os.path.split(os.path.abspath(sys.argv[0])) + api_set_root_path(dirname); + + framework = CTestFramework(dirname); + framework.repeat_time = int(args.repeat_time) + framework.shuffle_all = args.shuffle_all + framework.skip_proc=args.skip_proc + + api_set_value('keep_env', args.skip_proc) + api_set_value('debug', args.debug) + api_set_value('rebuild', args.rebuild) + + binary_path = args.binaries + if binary_path is None: + binary_path = os.path.abspath(dirname + '/../..') + + print "checking execution binary path: " + binary_path + if not os.path.exists(binary_path): + print "The execution binary path was not available. quit..." + os._exit(0) + api_set_value('binary_path', binary_path) + + if suites_list is not None: + framework.target_suites = suites_list + else: + framework.load_suites() + + framework.target_cases = cases_list + framework.start_run() + + print "\n\n------------------------------------------------------------" + print "The run folder is [" + framework.running_folder +"]" + print "that's all. bye" + + print "kill to quit.." + t_kill_process_by_name("start.py") + + sys.exit(0) + os._exit() + + diff --git a/test-tools/component_test/suites/01-life-cycle/__init__.py b/test-tools/component_test/suites/01-life-cycle/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test-tools/component_test/suites/01-life-cycle/cases/01-install/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/01-install/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test-tools/component_test/suites/01-life-cycle/cases/01-install/case.py b/test-tools/component_test/suites/01-life-cycle/cases/01-install/case.py new file mode 100644 index 00000000..b8d2c38b --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/01-install/case.py @@ -0,0 +1,94 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #uninstall inexistent App1 + ret = uninstall_app("App1") + if (ret != 160): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps([]) + if (ret == False): + return False, '' + + #install App1 + ret = install_app("App1", "01_install.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1"]) + if (ret == False): + return False, '' + + #install App2 + ret = install_app("App2", "01_install.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1","App2"]) + if (ret == False): + return False, '' + + #uninstall App2 + ret = uninstall_app("App2") + if (ret != 66): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1"]) + if (ret == False): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/02-request/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/02-request/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test-tools/component_test/suites/01-life-cycle/cases/02-request/case.py b/test-tools/component_test/suites/01-life-cycle/cases/02-request/case.py new file mode 100644 index 00000000..e2192d5f --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/02-request/case.py @@ -0,0 +1,73 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #install App1 + ret = install_app("App1", "02_request.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1"]) + if (ret == False): + return False, '' + + #send request to App1 + ret = send_request("/res1", "GET", None) + if (ret != 69): + return False, '' + expect_response_payload = {"key1":"value1","key2":"value2"} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + #send request to App1 + ret = send_request("/res2", "DELETE", None) + if (ret != 66): + return False, '' + expect_response_payload = {} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/03-event/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/03-event/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test-tools/component_test/suites/01-life-cycle/cases/03-event/case.py b/test-tools/component_test/suites/01-life-cycle/cases/03-event/case.py new file mode 100644 index 00000000..3886cb82 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/03-event/case.py @@ -0,0 +1,67 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #install App1 + ret = install_app("App1", "03_event.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1"]) + if (ret == False): + return False, '' + + #register event + ret = register("/alert/overheat", 2000, 5000) + if (ret != 69): + return False, '' + ret = check_get_event() + if (ret == False): + return False, '' + + #deregister event + ret = deregister("/alert/overheat") + if (ret != 69): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/case.py b/test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/case.py new file mode 100644 index 00000000..bf395f58 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/04-request-internal/case.py @@ -0,0 +1,80 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #install App1 + ret = install_app("App1", "04_request_internal_resp.wasm") + if (ret != 65): + return False, '' + + #install App2 + ret = install_app("App2", "04_request_internal_req.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1","App2"]) + if (ret == False): + return False, '' + + #send request to App2 + ret = send_request("/res1", "GET", None) + if (ret != 69): + return False, '' + time.sleep(2) + expect_response_payload = {"key1":"value1","key2":"value2"} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + #send request to App2 + ret = send_request("/res2", "GET", None) + if (ret != 69): + return False, '' + time.sleep(2) + expect_response_payload = {"key1":"value1","key2":"value2"} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/case.py b/test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/case.py new file mode 100644 index 00000000..79c32874 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/05-event-internal/case.py @@ -0,0 +1,70 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #install App1 + ret = install_app("App1", "05_event_internal_provider.wasm") + if (ret != 65): + return False, '' + + #install App2 + ret = install_app("App2", "05_event_internal_subscriber.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1","App2"]) + if (ret == False): + return False, '' + + #send request to App2 + ret = send_request("/res1", "GET", None) + if (ret != 69): + return False, '' + time.sleep(2) + expect_response_payload = {"key1":"value1","key2":"value2"} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/06-timer/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/06-timer/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test-tools/component_test/suites/01-life-cycle/cases/06-timer/case.py b/test-tools/component_test/suites/01-life-cycle/cases/06-timer/case.py new file mode 100644 index 00000000..90af4d5d --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/06-timer/case.py @@ -0,0 +1,70 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #install App1 + ret = install_app("App1", "06_timer.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1"]) + if (ret == False): + return False, '' + + #send request to App1 + ret = send_request("/res1", "GET", None) + if (ret != 69): + return False, '' + + time.sleep(3) + + ret = send_request("/check_timer", "GET", None) + if (ret != 69): + return False, '' + expect_response_payload = {"num":2} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/07-sensor/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/07-sensor/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test-tools/component_test/suites/01-life-cycle/cases/07-sensor/case.py b/test-tools/component_test/suites/01-life-cycle/cases/07-sensor/case.py new file mode 100644 index 00000000..2bb75620 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/07-sensor/case.py @@ -0,0 +1,65 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #install App1 + ret = install_app("App1", "07_sensor.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1"]) + if (ret == False): + return False, '' + + #send request to App1 + ret = send_request("/res1", "GET", None) + if (ret != 69): + return False, '' + time.sleep(2) + expect_response_payload = {"key1":"value1","key2":"value2"} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/case.py b/test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/case.py new file mode 100644 index 00000000..99a4512e --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/cases/08-on-destroy/case.py @@ -0,0 +1,78 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import sys +import time +import random +import logging +import json + +from framework.case_base import * +from framework.test_api import * +from harness.harness_api import * + +class CTestCase(CTestCaseBase): + def __init__(self, suite): + CTestCaseBase.__init__(self, suite) + + def get_case_name(self): + case_path = os.path.dirname(os.path.abspath( __file__ )) + return os.path.split(case_path)[1] + + def on_get_case_description(self): + return "startup the executables" + + def on_setup_case(self): + os.chdir(self.get_case_name()) + start_env() + api_log_error("on_setup_case OK") + return True, '' + + def on_cleanup_case(self): + stop_env() + api_log_error("on_cleanup_case OK") + return True, '' + + # called by the framework + def on_run_case(self): + time.sleep(0.5) + + #install App1 + ret = install_app("App1", "08_on_destroy.wasm") + if (ret != 65): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps(["App1"]) + if (ret == False): + return False, '' + + #send request to App1 + ret = send_request("/res1", "GET", None) + if (ret != 69): + return False, '' + time.sleep(2) + expect_response_payload = {"key1":"value1"} + ret = check_response_payload(expect_response_payload) + if (ret == False): + return False, '' + + #uninstall App1 + ret = uninstall_app("App1") + if (ret != 66): + return False, '' + + #query Apps + ret = query_app() + if (ret != 69): + return False, '' + ret = check_query_apps([]) + if (ret == False): + return False, '' + + return True, '' diff --git a/test-tools/component_test/suites/01-life-cycle/cases/__init__.py b/test-tools/component_test/suites/01-life-cycle/cases/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test-tools/component_test/suites/01-life-cycle/suite_setup.py b/test-tools/component_test/suites/01-life-cycle/suite_setup.py new file mode 100644 index 00000000..2307186f --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/suite_setup.py @@ -0,0 +1,56 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +import os +import shutil +import types +import time +import glob + +from framework.test_api import * +from framework.test_utils import * +from harness.harness_api import * +from framework.suite import * + +class CTestSuite(CTestSuiteBase): + setup_path = "" + def __init__(self, name, suite_path, run_path): + CTestSuiteBase.__init__(self, name, suite_path, run_path) + + def on_suite_setup(self): + global setup_path + setup_path = os.getcwd() + cases = os.listdir(self.suite_path + "/cases/") + cases.sort() + + if api_get_value("rebuild", False): + path_tmp = os.getcwd() + os.chdir(self.suite_path + "/test-app") + os.system(self.suite_path + "/test-app" + "/build.sh") + os.chdir(path_tmp) + + os.makedirs(self.run_path + "/test-app") + + for case in cases: + if case != "__init__.pyc" and case != "__init__.py": + os.makedirs(self.run_path + "/" + case) + #copy each case's host_tool, simple, wasm files, start/stop scripts to the run directory, + shutil.copy(setup_path + "/../../samples/simple/out/simple", self.run_path + "/" + case) + shutil.copy(setup_path + "/../../samples/simple/out/host_tool", self.run_path + "/" + case) + for file in glob.glob(self.suite_path + "/test-app/" + "/*.wasm"): + shutil.copy(file, self.run_path + "/test-app") + shutil.copy(self.suite_path + "/tools/product/start.sh", self.run_path + "/" + case) + shutil.copy(self.suite_path + "/tools/product/stop.sh", self.run_path + "/" + case) + + os.chdir(self.run_path) + + return True, 'OK' + + def on_suite_cleanup(self): + global setup_path + os.chdir(setup_path) + api_log("stopping env..") + + return True, 'OK' diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/01_install.c b/test-tools/component_test/suites/01-life-cycle/test-app/01_install.c new file mode 100644 index 00000000..f8ec3937 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/01_install.c @@ -0,0 +1,16 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" + +void on_init() +{ + printf("Hello, I was installed.\n"); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/02_request.c b/test-tools/component_test/suites/01-life-cycle/test-app/02_request.c new file mode 100644 index 00000000..ee7ecafe --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/02_request.c @@ -0,0 +1,62 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/request.h" + +void res1_handler(request_t *request) +{ + response_t response[1]; + attr_container_t *payload; + + printf("### user resource 1 handler called\n"); + + printf("###### dump request ######\n"); + printf("sender: %lu\n", request->sender); + printf("url: %s\n", request->url); + printf("action: %d\n", request->action); + printf("payload:\n"); + if (request->payload + != NULL&& request->payload_len > 0 && request->fmt == FMT_ATTR_CONTAINER) + attr_container_dump((attr_container_t *) request->payload); + printf("#### dump request end ###\n"); + + payload = attr_container_create("wasm app response payload"); + if (payload == NULL) + return; + + attr_container_set_string(&payload, "key1", "value1"); + attr_container_set_string(&payload, "key2", "value2"); + + make_response_for_request(request, response); + set_response(response, CONTENT_2_05, + FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload)); + printf("reciver: %lu, mid:%d\n", response->reciever, response->mid); + api_response_send(response); + + attr_container_destroy(payload); +} + +void res2_handler(request_t *request) +{ + response_t response[1]; + make_response_for_request(request, response); + set_response(response, DELETED_2_02, 0, NULL, 0); + api_response_send(response); + + printf("### user resource 2 handler called\n"); +} + +void on_init() +{ + /* register resource uri */ + api_register_resource_handler("/res1", res1_handler); + api_register_resource_handler("/res2", res2_handler); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/03_event.c b/test-tools/component_test/suites/01-life-cycle/test-app/03_event.c new file mode 100644 index 00000000..712110a9 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/03_event.c @@ -0,0 +1,53 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/timer_wasm_app.h" +#include "wa-inc/request.h" + +int num = 0; + +void publish_overheat_event() +{ + attr_container_t *event; + + event = attr_container_create("event"); + attr_container_set_string(&event, "warning", "temperature is over high"); + + printf("###app publish event begin ###\n"); + + api_publish_event("alert/overheat", FMT_ATTR_CONTAINER, event, + attr_container_get_serialize_length(event)); + + printf("###app publish event end ###\n"); + + attr_container_destroy(event); +} + +/* Timer callback */ +void timer1_update(user_timer_t timer) +{ + printf("Timer update %d\n", num++); + publish_overheat_event(); +} + +void start_timer() +{ + user_timer_t timer; + + /* set up a timer */ + timer = api_timer_create(1000, true, false, timer1_update); + api_timer_restart(timer, 1000); +} + +void on_init() +{ + start_timer(); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_req.c b/test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_req.c new file mode 100644 index 00000000..3e3ad0e6 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_req.c @@ -0,0 +1,66 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/request.h" + +uint32 mid; +unsigned long sender; + +void my_response_handler(response_t *response, void *user_data) +{ + attr_container_t *payload; + printf("### user resource 1 handler called\n"); + + payload = attr_container_create("wasm app response payload"); + if (payload == NULL) + return; + + attr_container_set_string(&payload, "key1", "value1"); + attr_container_set_string(&payload, "key2", "value2"); + + response->mid = mid; + response->reciever = sender; + set_response(response, CONTENT_2_05, + FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload)); + printf("reciver: %lu, mid:%d\n", response->reciever, response->mid); + api_response_send(response); + + attr_container_destroy(payload); +} + +static void test_send_request(const char *url, const char *tag) +{ + request_t request[1]; + + init_request(request, (char *)url, COAP_PUT, 0, NULL, 0); + api_send_request(request, my_response_handler, (void *)tag); +} + +void res1_handler(request_t *request) +{ + mid = request->mid; + sender = request->sender; + test_send_request("url1", "a general request"); +} + +void res2_handler(request_t *request) +{ + mid = request->mid; + sender = request->sender; + test_send_request("/app/App1/url1", "a general request"); +} + +void on_init() +{ + /* register resource uri */ + api_register_resource_handler("/res1", res1_handler); + api_register_resource_handler("/res2", res2_handler); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_resp.c b/test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_resp.c new file mode 100644 index 00000000..45b25cbd --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/04_request_internal_resp.c @@ -0,0 +1,52 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/request.h" + +void res1_handler(request_t *request) +{ + response_t response[1]; + attr_container_t *payload; + + printf("[resp] ### user resource 1 handler called\n"); + + printf("[resp] ###### dump request ######\n"); + printf("[resp] sender: %lu\n", request->sender); + printf("[resp] url: %s\n", request->url); + printf("[resp] action: %d\n", request->action); + printf("[resp] payload:\n"); + if (request->payload != NULL && request->fmt == FMT_ATTR_CONTAINER) + attr_container_dump((attr_container_t *) request->payload); + printf("[resp] #### dump request end ###\n"); + + payload = attr_container_create("wasm app response payload"); + if (payload == NULL) + return; + + attr_container_set_string(&payload, "key1", "value1"); + attr_container_set_string(&payload, "key2", "value2"); + + make_response_for_request(request, response); + set_response(response, CONTENT_2_05, + FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload)); + printf("[resp] response payload len %d\n", + attr_container_get_serialize_length(payload)); + printf("[resp] reciver: %lu, mid:%d\n", response->reciever, response->mid); + api_response_send(response); + + attr_container_destroy(payload); +} + +void on_init() +{ + /* register resource uri */ + api_register_resource_handler("/url1", res1_handler); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_provider.c b/test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_provider.c new file mode 100644 index 00000000..712110a9 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_provider.c @@ -0,0 +1,53 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/timer_wasm_app.h" +#include "wa-inc/request.h" + +int num = 0; + +void publish_overheat_event() +{ + attr_container_t *event; + + event = attr_container_create("event"); + attr_container_set_string(&event, "warning", "temperature is over high"); + + printf("###app publish event begin ###\n"); + + api_publish_event("alert/overheat", FMT_ATTR_CONTAINER, event, + attr_container_get_serialize_length(event)); + + printf("###app publish event end ###\n"); + + attr_container_destroy(event); +} + +/* Timer callback */ +void timer1_update(user_timer_t timer) +{ + printf("Timer update %d\n", num++); + publish_overheat_event(); +} + +void start_timer() +{ + user_timer_t timer; + + /* set up a timer */ + timer = api_timer_create(1000, true, false, timer1_update); + api_timer_restart(timer, 1000); +} + +void on_init() +{ + start_timer(); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_subscriber.c b/test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_subscriber.c new file mode 100644 index 00000000..dd031f80 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/05_event_internal_subscriber.c @@ -0,0 +1,50 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/request.h" + +uint32 mid; +unsigned long sender; + +void over_heat_event_handler(request_t *request) +{ + response_t response[1]; + attr_container_t *payload; + + payload = attr_container_create("wasm app response payload"); + if (payload == NULL) + return; + + attr_container_set_string(&payload, "key1", "value1"); + attr_container_set_string(&payload, "key2", "value2"); + + response->mid = mid; + response->reciever = sender; + set_response(response, CONTENT_2_05, + FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload)); + printf("reciver: %lu, mid:%d\n", response->reciever, response->mid); + api_response_send(response); + + attr_container_destroy(payload); +} + +void res1_handler(request_t *request) +{ + mid = request->mid; + sender = request->sender; + api_subscribe_event("alert/overheat", over_heat_event_handler); +} + +void on_init() +{ + /* register resource uri */ + api_register_resource_handler("/res1", res1_handler); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/06_timer.c b/test-tools/component_test/suites/01-life-cycle/test-app/06_timer.c new file mode 100644 index 00000000..c2036571 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/06_timer.c @@ -0,0 +1,76 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/request.h" +#include "wa-inc/timer_wasm_app.h" + +/* User global variable */ +int num = 0; + +/* Timer callback */ +void timer1_update(user_timer_t timer) +{ + if (num < 2) + num++; +} + +void res1_handler(request_t *request) +{ + user_timer_t timer; + + /* set up a timer */ + timer = api_timer_create(1000, true, false, timer1_update); + api_timer_restart(timer, 1000); + + response_t response[1]; + + make_response_for_request(request, response); + + set_response(response, CONTENT_2_05, + FMT_ATTR_CONTAINER, NULL, 0); + + api_response_send(response); +} + +void res2_handler(request_t *request) +{ + response_t response[1]; + attr_container_t *payload; + + if (num == 2) { + attr_container_t *payload; + printf("### user resource 1 handler called\n"); + + payload = attr_container_create("wasm app response payload"); + if (payload == NULL) + return; + + attr_container_set_int(&payload, "num", num); + + make_response_for_request(request, response); + + set_response(response, CONTENT_2_05, + FMT_ATTR_CONTAINER, (const char *)payload, + attr_container_get_serialize_length(payload)); + printf("reciver: %lu, mid:%d\n", response->reciever, response->mid); + api_response_send(response); + + attr_container_destroy(payload); + } + +} + +void on_init() +{ + /* register resource uri */ + api_register_resource_handler("/res1", res1_handler); + api_register_resource_handler("/check_timer", res2_handler); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/07_sensor.c b/test-tools/component_test/suites/01-life-cycle/test-app/07_sensor.c new file mode 100644 index 00000000..24af34c9 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/07_sensor.c @@ -0,0 +1,69 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/request.h" +#include "wa-inc/sensor.h" + +uint32 mid; +unsigned long sender; + +/* Sensor event callback*/ +void sensor_event_handler(sensor_t sensor, attr_container_t *event, + void *user_data) +{ + printf("### app get sensor event\n"); + + response_t response[1]; + attr_container_t *payload; + + payload = attr_container_create("wasm app response payload"); + if (payload == NULL) + return; + + attr_container_set_string(&payload, "key1", "value1"); + attr_container_set_string(&payload, "key2", "value2"); + + response->mid = mid; + response->reciever = sender; + set_response(response, CONTENT_2_05, + FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload)); + printf("reciver: %lu, mid:%d\n", response->reciever, response->mid); + api_response_send(response); + + attr_container_destroy(payload); +} + +void res1_handler(request_t *request) +{ + mid = request->mid; + sender = request->sender; + + sensor_t sensor; + char *user_data; + attr_container_t *config; + + printf("### app on_init 1\n"); + /* open a sensor */ + user_data = malloc(100); + printf("### app on_init 2\n"); + sensor = sensor_open("sensor_test", 0, sensor_event_handler, user_data); + printf("### app on_init 3\n"); + + /* config the sensor */ + sensor_config(sensor, 2000, 0, 0); + printf("### app on_init 4\n"); +} + +void on_init() +{ + /* register resource uri */ + api_register_resource_handler("/res1", res1_handler); +} + +void on_destroy() +{ + /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */ +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/08_on_destroy.c b/test-tools/component_test/suites/01-life-cycle/test-app/08_on_destroy.c new file mode 100644 index 00000000..637e0f7a --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/08_on_destroy.c @@ -0,0 +1,67 @@ +/* +* Copyright (C) 2019 Intel Corporation. All rights reserved. +* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +*/ + +#include "wasm_app.h" +#include "wa-inc/request.h" +#include "wa-inc/sensor.h" + +uint32 mid; +unsigned long sender; +sensor_t sensor; + +/* Sensor event callback*/ +void sensor_event_handler(sensor_t sensor, attr_container_t *event, void *user_data) { + printf("### app get sensor event\n"); + + response_t response[1]; + attr_container_t *payload; + + payload = attr_container_create("wasm app response payload"); + if (payload == NULL) + return; + + attr_container_set_string(&payload, "key1", "value1"); + + response->mid = mid; + response->reciever = sender; + set_response(response, + CONTENT_2_05, + FMT_ATTR_CONTAINER, + (const char *)payload, + attr_container_get_serialize_length(payload)); + printf("reciver: %lu, mid:%d\n", response->reciever, response->mid); + api_response_send(response); + + attr_container_destroy(payload); +} + +void res1_handler(request_t *request) +{ + mid = request->mid; + sender = request->sender; + + char *user_data; + attr_container_t *config; + + printf("### app on_init 1\n"); + /* open a sensor */ + user_data = malloc(100); + printf("### app on_init 2\n"); + sensor = sensor_open("sensor_test", 0, sensor_event_handler, user_data); + printf("### app on_init 3\n"); +} + +void on_init() +{ + /* register resource uri */ + api_register_resource_handler("/res1", res1_handler); +} + +void on_destroy() +{ + if(NULL != sensor){ + sensor_close(sensor); + } +} diff --git a/test-tools/component_test/suites/01-life-cycle/test-app/build.sh b/test-tools/component_test/suites/01-life-cycle/test-app/build.sh new file mode 100755 index 00000000..7ea7f312 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/test-app/build.sh @@ -0,0 +1,39 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +. ../../../set_dev_env.sh + +CC=/opt/wasi-sdk/bin/clang +APP_DIR=$PWD +WAMR_DIR=${APP_DIR}/../../../../../ +SDK_DIR=${WAMR_DIR}/wamr-sdk/out/simple-host-interp +APP_FRAMEWORK_DIR=${SDK_DIR}/app-sdk/wamr-app-framework +DEPS_DIR=${WAMR_DIR}/core/deps + +for i in `ls *.c` +do +APP_SRC="$i" +OUT_FILE=${i%.*}.wasm +/opt/wasi-sdk/bin/clang -O3 \ + -Wno-int-conversion \ + -I${APP_FRAMEWORK_DIR}/include \ + -I${DEPS_DIR} \ + --target=wasm32 -O3 -z stack-size=4096 -Wl,--initial-memory=65536 \ + --sysroot=${SDK_DIR}/app-sdk/libc-builtin-sysroot \ + -L${APP_FRAMEWORK_DIR}/lib -lapp_framework \ + -Wl,--allow-undefined-file=${SDK_DIR}/app-sdk/libc-builtin-sysroot/share/defined-symbols.txt \ + -Wl,--no-threads,--strip-all,--no-entry -nostdlib \ + -Wl,--export=on_init -Wl,--export=on_destroy \ + -Wl,--export=on_request -Wl,--export=on_response \ + -Wl,--export=on_sensor_event -Wl,--export=on_timer_callback \ + -Wl,--export=on_connection_data \ + -o ${OUT_FILE} \ + ${APP_SRC} +if [ -f ${OUT_FILE} ]; then + echo "build ${OUT_FILE} success" +else + echo "build ${OUT_FILE} fail" +fi +done \ No newline at end of file diff --git a/test-tools/component_test/suites/01-life-cycle/tools/product/start.sh b/test-tools/component_test/suites/01-life-cycle/tools/product/start.sh new file mode 100755 index 00000000..f83e3935 --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/tools/product/start.sh @@ -0,0 +1,10 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +#!/bin/bash + +cd $(dirname "$0") + +./simple -s > /dev/null 2>&1 & diff --git a/test-tools/component_test/suites/01-life-cycle/tools/product/stop.sh b/test-tools/component_test/suites/01-life-cycle/tools/product/stop.sh new file mode 100755 index 00000000..b7bc2c8d --- /dev/null +++ b/test-tools/component_test/suites/01-life-cycle/tools/product/stop.sh @@ -0,0 +1,9 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +#!/bin/bash + +ps aux | grep -ie host_tool | awk '{print $2}' | xargs kill -9 & +ps aux | grep -ie simple | awk '{print $2}' | xargs kill -9 & diff --git a/test-tools/component_test/suites/__init__.py b/test-tools/component_test/suites/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test-tools/component_test/suites/readme.txt b/test-tools/component_test/suites/readme.txt new file mode 100644 index 00000000..1e8792f5 --- /dev/null +++ b/test-tools/component_test/suites/readme.txt @@ -0,0 +1,19 @@ +The description of each case in the test suites, should add descriptions in this file when new cases created in the future. + +suite 01-life-cycle: +case 01-install: + install or uninstall apps for times and query apps to see if the app list is expected. +case 02-request: + send request to an app, the app will respond specific attribute objects, host side should get them. +case 03-event: + register event to an app, the app will send event back periodically, host side should get some payload. +case 04-request_internal: + install 2 apps, host sends request to app2, then app2 sends request to app1, finally app1 respond specific payload to host, host side will check it. +case 05-event_internal: + install 2 apps, host sends request to app2, then app2 subscribe app1's event, finally app1 respond specific payload to host, host side will check it. +case 06-timer: + host send request to an app, the app then start a timer, when time goes by 2 seconds, app will respond specific payload to host, host side will check it. +case 07-sensor: + open sensor in app and then config the sensor in on_init, finally app will respond specific payload to host, host side will check it. +case 08-on_destroy: + open sensor in app in on_init, and close the sensor in on_destroy, host should install and uninstall the app successfully. diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index 8b85045f..ea65406b 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -34,6 +34,9 @@ elseif (WAMR_BUILD_TARGET STREQUAL "AMD_64") add_definitions(-DBUILD_TARGET_AMD_64) elseif (WAMR_BUILD_TARGET STREQUAL "X86_32") add_definitions(-DBUILD_TARGET_X86_32) +elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*") + add_definitions(-DBUILD_TARGET_AARCH64) + add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}") elseif (WAMR_BUILD_TARGET MATCHES "ARM.*") add_definitions(-DBUILD_TARGET_ARM) add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}") @@ -44,7 +47,7 @@ endif () message ("-- Build as target ${WAMR_BUILD_TARGET}") if (CMAKE_SIZEOF_VOID_P EQUAL 8) - if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*") # Add -fPIC flag if build as 64-bit set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC") diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c index cc92dbcc..181e8cdc 100644 --- a/wamr-compiler/main.c +++ b/wamr-compiler/main.c @@ -14,7 +14,7 @@ print_help() { printf("Usage: wamrc [options] -o output_file wasm_file\n"); printf(" --target= Set the target arch, which has the general format: \n"); - printf(" = x86_64, i386, arm, thumb, mips.\n"); + printf(" = x86_64, i386, aarch64, arm, thumb, mips.\n"); printf(" Default is host arch, e.g. x86_64\n"); printf(" = for ex. on arm or thumb: v5, v6m, v7a, v7m, etc.\n"); printf(" Use --target=help to list supported targets\n");