From 380cd7b0e79ab239cfba3fff2180f4868a101164 Mon Sep 17 00:00:00 2001 From: "Zhang, Yi" Date: Tue, 4 Jun 2024 11:24:27 +0800 Subject: [PATCH] Add unit test suites (#3490) --- tests/unit/CMakeLists.txt | 69 +- tests/unit/aot-stack-frame/CMakeLists.txt | 55 + .../aot-stack-frame/aot_stack_frame_test.cc | 288 ++++ .../aot-stack-frame/wasm-apps/CMakeLists.txt | 27 + .../unit/aot-stack-frame/wasm-apps/test.wast | 36 + tests/unit/aot/CMakeLists.txt | 59 + tests/unit/aot/aot_test.cc | 1190 ++++++++++++++ tests/unit/common/mock_allocator.h | 89 ++ tests/unit/common/test_helper.h | 325 ++++ tests/unit/compilation/CMakeLists.txt | 72 + tests/unit/compilation/aot_compiler_test.cc | 203 +++ .../compilation/aot_emit_aot_file_test.cc | 104 ++ .../unit/compilation/aot_emit_compare_test.cc | 112 ++ .../unit/compilation/aot_emit_control_test.cc | 196 +++ .../compilation/aot_emit_function_test.cc | 101 ++ .../unit/compilation/aot_emit_memory_test.cc | 335 ++++ .../compilation/aot_emit_numberic_test.cc | 119 ++ .../compilation/aot_emit_parametric_test.cc | 143 ++ tests/unit/compilation/aot_emit_table_test.cc | 105 ++ .../compilation/aot_emit_variable_test.cc | 97 ++ tests/unit/compilation/aot_llvm_test.cc | 305 ++++ tests/unit/compilation/wasm-apps/main.wasm | Bin 0 -> 1217 bytes tests/unit/custom-section/CMakeLists.txt | 65 + .../custom-section/custom_section_test.cc | 161 ++ .../custom-section/wasm-apps/CMakeLists.txt | 14 + tests/unit/custom-section/wasm-apps/app.c | 10 + tests/unit/gc/CMakeLists.txt | 51 + tests/unit/gc/gc_test.cc | 102 ++ tests/unit/gc/wasm-apps/func1.wasm | Bin 0 -> 106 bytes tests/unit/gc/wasm-apps/func1.wast | 35 + tests/unit/gc/wasm-apps/func2.wasm | Bin 0 -> 470 bytes tests/unit/gc/wasm-apps/func2.wast | 78 + tests/unit/gc/wasm-apps/global1.wasm | Bin 0 -> 554 bytes tests/unit/gc/wasm-apps/global1.wast | 91 ++ tests/unit/gc/wasm-apps/struct1.wasm | Bin 0 -> 85 bytes tests/unit/gc/wasm-apps/struct1.wast | 10 + tests/unit/gc/wasm-apps/struct2.wasm | Bin 0 -> 234 bytes tests/unit/gc/wasm-apps/struct2.wast | 33 + tests/unit/gc/wasm-apps/struct3.wasm | Bin 0 -> 118 bytes tests/unit/gc/wasm-apps/struct3.wast | 9 + tests/unit/gc/wasm-apps/table1.wasm | Bin 0 -> 560 bytes tests/unit/gc/wasm-apps/table1.wast | 108 ++ tests/unit/gc/wasm-apps/test1.wasm | Bin 0 -> 647 bytes tests/unit/gc/wasm-apps/test1.wast | 117 ++ tests/unit/gc/wasm-apps/test2.wasm | Bin 0 -> 626 bytes tests/unit/gc/wasm-apps/test2.wast | 104 ++ tests/unit/gc/wasm-apps/test3.wasm | Bin 0 -> 976 bytes tests/unit/gc/wasm-apps/test3.wast | 146 ++ tests/unit/gc/wasm-apps/test4.wasm | Bin 0 -> 299 bytes tests/unit/gc/wasm-apps/test4.wast | 46 + tests/unit/gc/wasm-apps/test5.wasm | Bin 0 -> 512 bytes tests/unit/gc/wasm-apps/test5.wast | 85 + tests/unit/gc/wasm-apps/test6.wasm | Bin 0 -> 197 bytes tests/unit/gc/wasm-apps/test6.wast | 27 + tests/unit/interpreter/.gitignore | 1 + tests/unit/interpreter/CMakeLists.txt | 42 + tests/unit/interpreter/interpreter_test.cc | 50 + tests/unit/libc-builtin/CMakeLists.txt | 32 + tests/unit/libc-builtin/func_types.h | 170 ++ tests/unit/libc-builtin/libc_builtin_test.cc | 1412 +++++++++++++++++ tests/unit/linear-memory-aot/CMakeLists.txt | 78 + tests/unit/linear-memory-aot/build_aot.sh | 45 + .../linear_memory_aot_test.cc | 361 +++++ .../mem_grow_out_of_bounds_01.wast | 16 + .../mem_grow_out_of_bounds_02.wast | 16 + tests/unit/linear-memory-aot/mem_page_01.wast | 1 + tests/unit/linear-memory-aot/mem_page_02.wast | 1 + tests/unit/linear-memory-aot/mem_page_03.wast | 1 + tests/unit/linear-memory-aot/mem_page_05.wast | 1 + tests/unit/linear-memory-aot/mem_page_07.wast | 1 + tests/unit/linear-memory-aot/mem_page_08.wast | 1 + tests/unit/linear-memory-aot/mem_page_09.wast | 1 + tests/unit/linear-memory-aot/mem_page_10.wast | 1 + tests/unit/linear-memory-aot/mem_page_12.wast | 1 + tests/unit/linear-memory-aot/mem_page_14.wast | 1 + tests/unit/linear-memory-aot/mem_page_16.wast | 1 + tests/unit/linear-memory-aot/mem_page_20.wast | 1 + .../unit/linear-memory-aot/out_of_bounds.wast | 10 + tests/unit/linear-memory-aot/readme | 2 + tests/unit/linear-memory-wasm/CMakeLists.txt | 59 + .../linear_memory_wasm_test.cc | 327 ++++ .../mem_grow_out_of_bounds_01.wast | 16 + .../mem_grow_out_of_bounds_02.wast | 16 + .../unit/linear-memory-wasm/mem_page_01.wast | 1 + .../unit/linear-memory-wasm/mem_page_02.wast | 1 + .../unit/linear-memory-wasm/mem_page_03.wast | 1 + .../unit/linear-memory-wasm/mem_page_04.wast | 1 + .../unit/linear-memory-wasm/mem_page_05.wast | 1 + .../unit/linear-memory-wasm/mem_page_06.wast | 1 + .../unit/linear-memory-wasm/mem_page_07.wast | 1 + .../unit/linear-memory-wasm/mem_page_08.wast | 1 + .../unit/linear-memory-wasm/mem_page_09.wast | 1 + .../unit/linear-memory-wasm/mem_page_10.wast | 1 + .../unit/linear-memory-wasm/mem_page_11.wast | 1 + .../unit/linear-memory-wasm/mem_page_12.wast | 1 + .../unit/linear-memory-wasm/mem_page_13.wast | 1 + .../unit/linear-memory-wasm/mem_page_14.wast | 1 + .../unit/linear-memory-wasm/mem_page_15.wast | 1 + .../unit/linear-memory-wasm/mem_page_16.wast | 1 + .../unit/linear-memory-wasm/mem_page_17.wast | 1 + .../unit/linear-memory-wasm/mem_page_18.wast | 1 + .../unit/linear-memory-wasm/mem_page_19.wast | 1 + .../unit/linear-memory-wasm/mem_page_20.wast | 1 + .../linear-memory-wasm/out_of_bounds.wast | 10 + tests/unit/linear-memory-wasm/readme | 2 + .../wasm_files/mem_grow_out_of_bounds_01.wasm | Bin 0 -> 70 bytes .../wasm_files/mem_grow_out_of_bounds_02.wasm | Bin 0 -> 70 bytes .../wasm_files/out_of_bounds.wasm | Bin 0 -> 46 bytes .../wasm_files/wasm_app_heap_02.wasm | Bin 0 -> 15 bytes .../wasm_files/wasm_mem_page_01.wasm | Bin 0 -> 13 bytes .../wasm_files/wasm_mem_page_02.wasm | Bin 0 -> 13 bytes .../wasm_files/wasm_mem_page_03.wasm | Bin 0 -> 15 bytes .../wasm_files/wasm_mem_page_04.wasm | Bin 0 -> 15 bytes .../wasm_files/wasm_mem_page_05.wasm | Bin 0 -> 14 bytes .../wasm_files/wasm_mem_page_06.wasm | Bin 0 -> 14 bytes .../wasm_files/wasm_mem_page_07.wasm | Bin 0 -> 14 bytes .../wasm_files/wasm_mem_page_08.wasm | Bin 0 -> 14 bytes .../wasm_files/wasm_mem_page_09.wasm | Bin 0 -> 15 bytes .../wasm_files/wasm_mem_page_10.wasm | Bin 0 -> 16 bytes .../wasm_files/wasm_mem_page_11.wasm | Bin 0 -> 16 bytes .../wasm_files/wasm_mem_page_12.wasm | Bin 0 -> 16 bytes .../wasm_files/wasm_mem_page_13.wasm | Bin 0 -> 16 bytes .../wasm_files/wasm_mem_page_14.wasm | Bin 0 -> 18 bytes .../wasm_files/wasm_mem_page_15.wasm | Bin 0 -> 18 bytes .../wasm_files/wasm_mem_page_16.wasm | Bin 0 -> 18 bytes .../wasm_files/wasm_mem_page_17.wasm | Bin 0 -> 18 bytes .../wasm_files/wasm_mem_page_18.wasm | Bin 0 -> 18 bytes .../wasm_files/wasm_mem_page_19.wasm | Bin 0 -> 18 bytes .../wasm_files/wasm_mem_page_20.wasm | Bin 0 -> 15 bytes tests/unit/linux-perf/CMakeLists.txt | 46 + tests/unit/linux-perf/test_sort_func_ptrs.cc | 110 ++ tests/unit/memory64/CMakeLists.txt | 67 + tests/unit/memory64/memory64_atomic_test.cc | 355 +++++ tests/unit/memory64/memory64_common.h | 63 + tests/unit/memory64/memory64_test.cc | 235 +++ tests/unit/memory64/wasm-apps/8GB_memory.wasm | Bin 0 -> 249 bytes tests/unit/memory64/wasm-apps/8GB_memory.wat | 53 + .../memory64/wasm-apps/atomic_opcodes.wasm | Bin 0 -> 820 bytes .../memory64/wasm-apps/atomic_opcodes.wat | 120 ++ tests/unit/memory64/wasm-apps/mem64.c | 56 + tests/unit/memory64/wasm-apps/mem64.wasm | Bin 0 -> 1992 bytes .../memory64/wasm-apps/page_exceed_u32.wasm | Bin 0 -> 22 bytes .../memory64/wasm-apps/page_exceed_u32.wat | 4 + .../memory64/wasm-apps/page_exceed_u32_2.wasm | Bin 0 -> 21 bytes .../memory64/wasm-apps/page_exceed_u32_2.wat | 4 + .../unit/memory64/wasm-apps/page_u32_max.wasm | Bin 0 -> 22 bytes .../unit/memory64/wasm-apps/page_u32_max.wat | 4 + tests/unit/running-modes/CMakeLists.txt | 56 + .../running-modes/wasm-apps/CMakeLists.txt | 49 + tests/unit/running-modes/wasm-apps/hello.c | 31 + tests/unit/running-modes/wasm-apps/mytest.c | 53 + .../running-modes/wasm_running_modes_test.cc | 308 ++++ tests/unit/runtime-common/CMakeLists.txt | 73 + tests/unit/runtime-common/build_aot.sh | 31 + tests/unit/runtime-common/wasm-apps/main.aot | Bin 0 -> 1164 bytes tests/unit/runtime-common/wasm-apps/main.wasm | Bin 0 -> 1217 bytes .../unit/runtime-common/wasm_exec_env_test.cc | 45 + .../wasm_runtime_common_test.cc | 682 ++++++++ .../runtime-common/wasm_runtime_init_test.cc | 162 ++ tests/unit/shared-utils/CMakeLists.txt | 30 + tests/unit/shared-utils/bh_assert_test.cc | 38 + tests/unit/shared-utils/bh_common_test.cc | 96 ++ tests/unit/shared-utils/bh_hashmap_test.cc | 362 +++++ tests/unit/shared-utils/bh_list_test.cc | 137 ++ tests/unit/shared-utils/bh_log_test.cc | 95 ++ tests/unit/shared-utils/bh_queue_test.cc | 278 ++++ tests/unit/shared-utils/bh_vector_test.cc | 268 ++++ tests/unit/shared-utils/shared_utils_test.cc | 33 + tests/unit/tid-allocator/CMakeLists.txt | 39 + tests/unit/{ => tid-allocator}/main.cpp | 1 + tests/unit/unit_common.cmake | 105 ++ tests/unit/wasm-c-api/CMakeLists.txt | 62 + tests/unit/wasm-c-api/basic.cc | 191 +++ tests/unit/wasm-c-api/run.sh | 21 + tests/unit/wasm-vm/.gitignore | 2 + tests/unit/wasm-vm/CMakeLists.txt | 53 + tests/unit/wasm-vm/wasm-apps/app1.wast | 106 ++ tests/unit/wasm-vm/wasm-apps/app1/main.c | 56 + tests/unit/wasm-vm/wasm-apps/app1_wasm.h | 54 + tests/unit/wasm-vm/wasm-apps/app2.wast | 311 ++++ tests/unit/wasm-vm/wasm-apps/app2/main.c | 140 ++ tests/unit/wasm-vm/wasm-apps/app2_wasm.h | 104 ++ tests/unit/wasm-vm/wasm-apps/app3.wast | 63 + tests/unit/wasm-vm/wasm-apps/app3/main.c | 32 + tests/unit/wasm-vm/wasm-apps/app3_wasm.h | 42 + tests/unit/wasm-vm/wasm-apps/app4/m1.wasm | Bin 0 -> 103 bytes tests/unit/wasm-vm/wasm-apps/app4/m1.wat | 14 + tests/unit/wasm-vm/wasm-apps/app4/m2.wasm | Bin 0 -> 122 bytes tests/unit/wasm-vm/wasm-apps/app4/m2.wat | 24 + tests/unit/wasm-vm/wasm-apps/app4/m3.wasm | Bin 0 -> 86 bytes tests/unit/wasm-vm/wasm-apps/app4/m3.wat | 7 + tests/unit/wasm-vm/wasm-apps/binarydump | Bin 0 -> 13448 bytes tests/unit/wasm-vm/wasm-apps/build.sh | 32 + tests/unit/wasm-vm/wasm_vm.cc | 716 +++++++++ 194 files changed, 14104 insertions(+), 34 deletions(-) create mode 100644 tests/unit/aot-stack-frame/CMakeLists.txt create mode 100644 tests/unit/aot-stack-frame/aot_stack_frame_test.cc create mode 100644 tests/unit/aot-stack-frame/wasm-apps/CMakeLists.txt create mode 100644 tests/unit/aot-stack-frame/wasm-apps/test.wast create mode 100644 tests/unit/aot/CMakeLists.txt create mode 100644 tests/unit/aot/aot_test.cc create mode 100644 tests/unit/common/mock_allocator.h create mode 100644 tests/unit/common/test_helper.h create mode 100644 tests/unit/compilation/CMakeLists.txt create mode 100644 tests/unit/compilation/aot_compiler_test.cc create mode 100644 tests/unit/compilation/aot_emit_aot_file_test.cc create mode 100644 tests/unit/compilation/aot_emit_compare_test.cc create mode 100644 tests/unit/compilation/aot_emit_control_test.cc create mode 100644 tests/unit/compilation/aot_emit_function_test.cc create mode 100644 tests/unit/compilation/aot_emit_memory_test.cc create mode 100644 tests/unit/compilation/aot_emit_numberic_test.cc create mode 100644 tests/unit/compilation/aot_emit_parametric_test.cc create mode 100644 tests/unit/compilation/aot_emit_table_test.cc create mode 100644 tests/unit/compilation/aot_emit_variable_test.cc create mode 100644 tests/unit/compilation/aot_llvm_test.cc create mode 100644 tests/unit/compilation/wasm-apps/main.wasm create mode 100644 tests/unit/custom-section/CMakeLists.txt create mode 100644 tests/unit/custom-section/custom_section_test.cc create mode 100644 tests/unit/custom-section/wasm-apps/CMakeLists.txt create mode 100644 tests/unit/custom-section/wasm-apps/app.c create mode 100644 tests/unit/gc/CMakeLists.txt create mode 100644 tests/unit/gc/gc_test.cc create mode 100644 tests/unit/gc/wasm-apps/func1.wasm create mode 100644 tests/unit/gc/wasm-apps/func1.wast create mode 100644 tests/unit/gc/wasm-apps/func2.wasm create mode 100644 tests/unit/gc/wasm-apps/func2.wast create mode 100644 tests/unit/gc/wasm-apps/global1.wasm create mode 100644 tests/unit/gc/wasm-apps/global1.wast create mode 100644 tests/unit/gc/wasm-apps/struct1.wasm create mode 100644 tests/unit/gc/wasm-apps/struct1.wast create mode 100644 tests/unit/gc/wasm-apps/struct2.wasm create mode 100644 tests/unit/gc/wasm-apps/struct2.wast create mode 100644 tests/unit/gc/wasm-apps/struct3.wasm create mode 100644 tests/unit/gc/wasm-apps/struct3.wast create mode 100644 tests/unit/gc/wasm-apps/table1.wasm create mode 100644 tests/unit/gc/wasm-apps/table1.wast create mode 100644 tests/unit/gc/wasm-apps/test1.wasm create mode 100644 tests/unit/gc/wasm-apps/test1.wast create mode 100644 tests/unit/gc/wasm-apps/test2.wasm create mode 100644 tests/unit/gc/wasm-apps/test2.wast create mode 100644 tests/unit/gc/wasm-apps/test3.wasm create mode 100644 tests/unit/gc/wasm-apps/test3.wast create mode 100644 tests/unit/gc/wasm-apps/test4.wasm create mode 100644 tests/unit/gc/wasm-apps/test4.wast create mode 100644 tests/unit/gc/wasm-apps/test5.wasm create mode 100644 tests/unit/gc/wasm-apps/test5.wast create mode 100644 tests/unit/gc/wasm-apps/test6.wasm create mode 100644 tests/unit/gc/wasm-apps/test6.wast create mode 100644 tests/unit/interpreter/.gitignore create mode 100644 tests/unit/interpreter/CMakeLists.txt create mode 100644 tests/unit/interpreter/interpreter_test.cc create mode 100644 tests/unit/libc-builtin/CMakeLists.txt create mode 100644 tests/unit/libc-builtin/func_types.h create mode 100644 tests/unit/libc-builtin/libc_builtin_test.cc create mode 100644 tests/unit/linear-memory-aot/CMakeLists.txt create mode 100755 tests/unit/linear-memory-aot/build_aot.sh create mode 100644 tests/unit/linear-memory-aot/linear_memory_aot_test.cc create mode 100644 tests/unit/linear-memory-aot/mem_grow_out_of_bounds_01.wast create mode 100644 tests/unit/linear-memory-aot/mem_grow_out_of_bounds_02.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_01.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_02.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_03.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_05.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_07.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_08.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_09.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_10.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_12.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_14.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_16.wast create mode 100644 tests/unit/linear-memory-aot/mem_page_20.wast create mode 100644 tests/unit/linear-memory-aot/out_of_bounds.wast create mode 100644 tests/unit/linear-memory-aot/readme create mode 100644 tests/unit/linear-memory-wasm/CMakeLists.txt create mode 100644 tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc create mode 100644 tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_01.wast create mode 100644 tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_02.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_01.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_02.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_03.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_04.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_05.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_06.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_07.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_08.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_09.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_10.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_11.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_12.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_13.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_14.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_15.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_16.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_17.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_18.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_19.wast create mode 100644 tests/unit/linear-memory-wasm/mem_page_20.wast create mode 100644 tests/unit/linear-memory-wasm/out_of_bounds.wast create mode 100644 tests/unit/linear-memory-wasm/readme create mode 100644 tests/unit/linear-memory-wasm/wasm_files/mem_grow_out_of_bounds_01.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/mem_grow_out_of_bounds_02.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/out_of_bounds.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_app_heap_02.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_01.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_02.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_03.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_04.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_05.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_06.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_07.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_08.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_09.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_10.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_11.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_12.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_13.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_14.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_15.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_16.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_17.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_18.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_19.wasm create mode 100644 tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_20.wasm create mode 100644 tests/unit/linux-perf/CMakeLists.txt create mode 100644 tests/unit/linux-perf/test_sort_func_ptrs.cc create mode 100644 tests/unit/memory64/CMakeLists.txt create mode 100644 tests/unit/memory64/memory64_atomic_test.cc create mode 100644 tests/unit/memory64/memory64_common.h create mode 100644 tests/unit/memory64/memory64_test.cc create mode 100644 tests/unit/memory64/wasm-apps/8GB_memory.wasm create mode 100644 tests/unit/memory64/wasm-apps/8GB_memory.wat create mode 100644 tests/unit/memory64/wasm-apps/atomic_opcodes.wasm create mode 100644 tests/unit/memory64/wasm-apps/atomic_opcodes.wat create mode 100644 tests/unit/memory64/wasm-apps/mem64.c create mode 100755 tests/unit/memory64/wasm-apps/mem64.wasm create mode 100644 tests/unit/memory64/wasm-apps/page_exceed_u32.wasm create mode 100644 tests/unit/memory64/wasm-apps/page_exceed_u32.wat create mode 100644 tests/unit/memory64/wasm-apps/page_exceed_u32_2.wasm create mode 100644 tests/unit/memory64/wasm-apps/page_exceed_u32_2.wat create mode 100644 tests/unit/memory64/wasm-apps/page_u32_max.wasm create mode 100644 tests/unit/memory64/wasm-apps/page_u32_max.wat create mode 100644 tests/unit/running-modes/CMakeLists.txt create mode 100644 tests/unit/running-modes/wasm-apps/CMakeLists.txt create mode 100644 tests/unit/running-modes/wasm-apps/hello.c create mode 100644 tests/unit/running-modes/wasm-apps/mytest.c create mode 100644 tests/unit/running-modes/wasm_running_modes_test.cc create mode 100644 tests/unit/runtime-common/CMakeLists.txt create mode 100755 tests/unit/runtime-common/build_aot.sh create mode 100644 tests/unit/runtime-common/wasm-apps/main.aot create mode 100644 tests/unit/runtime-common/wasm-apps/main.wasm create mode 100644 tests/unit/runtime-common/wasm_exec_env_test.cc create mode 100644 tests/unit/runtime-common/wasm_runtime_common_test.cc create mode 100644 tests/unit/runtime-common/wasm_runtime_init_test.cc create mode 100644 tests/unit/shared-utils/CMakeLists.txt create mode 100644 tests/unit/shared-utils/bh_assert_test.cc create mode 100644 tests/unit/shared-utils/bh_common_test.cc create mode 100644 tests/unit/shared-utils/bh_hashmap_test.cc create mode 100644 tests/unit/shared-utils/bh_list_test.cc create mode 100644 tests/unit/shared-utils/bh_log_test.cc create mode 100644 tests/unit/shared-utils/bh_queue_test.cc create mode 100644 tests/unit/shared-utils/bh_vector_test.cc create mode 100644 tests/unit/shared-utils/shared_utils_test.cc create mode 100644 tests/unit/tid-allocator/CMakeLists.txt rename tests/unit/{ => tid-allocator}/main.cpp (99%) create mode 100644 tests/unit/unit_common.cmake create mode 100644 tests/unit/wasm-c-api/CMakeLists.txt create mode 100644 tests/unit/wasm-c-api/basic.cc create mode 100755 tests/unit/wasm-c-api/run.sh create mode 100644 tests/unit/wasm-vm/.gitignore create mode 100644 tests/unit/wasm-vm/CMakeLists.txt create mode 100644 tests/unit/wasm-vm/wasm-apps/app1.wast create mode 100644 tests/unit/wasm-vm/wasm-apps/app1/main.c create mode 100644 tests/unit/wasm-vm/wasm-apps/app1_wasm.h create mode 100644 tests/unit/wasm-vm/wasm-apps/app2.wast create mode 100644 tests/unit/wasm-vm/wasm-apps/app2/main.c create mode 100644 tests/unit/wasm-vm/wasm-apps/app2_wasm.h create mode 100644 tests/unit/wasm-vm/wasm-apps/app3.wast create mode 100644 tests/unit/wasm-vm/wasm-apps/app3/main.c create mode 100644 tests/unit/wasm-vm/wasm-apps/app3_wasm.h create mode 100644 tests/unit/wasm-vm/wasm-apps/app4/m1.wasm create mode 100644 tests/unit/wasm-vm/wasm-apps/app4/m1.wat create mode 100644 tests/unit/wasm-vm/wasm-apps/app4/m2.wasm create mode 100644 tests/unit/wasm-vm/wasm-apps/app4/m2.wat create mode 100644 tests/unit/wasm-vm/wasm-apps/app4/m3.wasm create mode 100644 tests/unit/wasm-vm/wasm-apps/app4/m3.wat create mode 100755 tests/unit/wasm-vm/wasm-apps/binarydump create mode 100755 tests/unit/wasm-vm/wasm-apps/build.sh create mode 100644 tests/unit/wasm-vm/wasm_vm.cc diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index a9a7b8776..40c9bb6ae 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -1,51 +1,52 @@ -# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -cmake_minimum_required (VERSION 3.14) +cmake_minimum_required(VERSION 2.9) -project (wamr_unit_tests) +project(unit-test) -include (CTest) +SET(CMAKE_BUILD_TYPE Debug) -if (NOT DEFINED WAMR_BUILD_INTERP) - # Enable Interpreter by default - set (WAMR_BUILD_INTERP 1) -endif () +# add_definitions (-m32) +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") -if (NOT DEFINED WAMR_BUILD_PLATFORM) - string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) -endif () +if(WAMR_BUILD_TARGET STREQUAL "X86_32") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32") +endif() -set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) -include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) -add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE}) +# Prevent overriding the parent project's compiler/linker +# settings on Windows +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +# Fetch Google test include (FetchContent) FetchContent_Declare ( googletest URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip ) -# For Windows: Prevent overriding the parent project's compiler/linker settings -set (gtest_force_shared_crt ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable (googletest) -include (GoogleTest) +SET(GOOGLETEST_INCLUDED 1) -add_library (wamr_gtest_main main.cpp) -target_link_libraries (wamr_gtest_main PUBLIC gtest vmlib) +include(GoogleTest) +enable_testing() -function (create_wamr_unit_test test_name) - set (sources ${ARGN}) - add_executable (${test_name} ${sources}) - target_link_libraries ( - ${test_name} - wamr_gtest_main - vmlib - ${LLVM_AVAILABLE_LIBS} - ) - gtest_discover_tests (${test_name}) - endfunction () - -if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1) - include (${IWASM_DIR}/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake) -endif () +add_subdirectory(wasm-vm) +add_subdirectory(interpreter) +add_subdirectory(aot) +add_subdirectory(wasm-c-api) +add_subdirectory(libc-builtin) +add_subdirectory(shared-utils) +add_subdirectory(running-modes) +add_subdirectory(runtime-common) +add_subdirectory(custom-section) +add_subdirectory(compilation) +add_subdirectory(linear-memory-wasm) +add_subdirectory(linear-memory-aot) +add_subdirectory(aot-stack-frame) +add_subdirectory(linux-perf) +add_subdirectory(gc) +add_subdirectory(memory64) +add_subdirectory(tid-allocator) diff --git a/tests/unit/aot-stack-frame/CMakeLists.txt b/tests/unit/aot-stack-frame/CMakeLists.txt new file mode 100644 index 000000000..9ff066f08 --- /dev/null +++ b/tests/unit/aot-stack-frame/CMakeLists.txt @@ -0,0 +1,55 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-aot-stack-frame) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_INTERP 0) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_SIMD 1) +set (WAMR_BUILD_REF_TYPES 1) +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_LIBC_BUILTIN 0) +set (WAMR_BUILD_MULTI_MODULE 0) +set (WAMR_DISABLE_HW_BOUND_CHECK 1) +set (WAMR_DISABLE_WRITE_GS_BASE 1) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1) +add_definitions (-DAOT_STACK_FRAME_DEBUG) +#add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} + ) + +# Automatically build wasm-apps for this test +add_subdirectory(wasm-apps) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable (aot_stack_frame_test ${unit_test_sources}) + +add_dependencies (aot_stack_frame_test aot-stack-frame-test-wasm) + +target_link_libraries (aot_stack_frame_test ${LLVM_AVAILABLE_LIBS} gtest_main ) + +#gtest_discover_tests(aot_stack_frame_test) \ No newline at end of file diff --git a/tests/unit/aot-stack-frame/aot_stack_frame_test.cc b/tests/unit/aot-stack-frame/aot_stack_frame_test.cc new file mode 100644 index 000000000..9bea2b2a0 --- /dev/null +++ b/tests/unit/aot-stack-frame/aot_stack_frame_test.cc @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "bh_platform.h" +#include "wasm_runtime_common.h" +#include "aot_runtime.h" +#include "test_helper.h" + +#ifndef __aligned +#define __aligned(n) +#endif +#include "wasm-apps/test_aot.h" + +typedef struct MyAOTFrame { + uintptr_t func_index; + + /* Instruction pointer: offset to the bytecode array */ + uintptr_t ip_offset; + + /* Operand stack top pointer of the current frame */ + uint32 *sp; + +#if WASM_ENABLE_GC != 0 + /* Frame ref flags (GC only) */ + uint8 *frame_ref; +#endif + + uint32 lp[1]; +} MyAOTFrame; + +class AOTStackFrameTest : public testing::Test +{ + protected: + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + } + + virtual void TearDown() + { + DestroyFrames(); + wasm_runtime_destroy(); + } + + public: + static void DestroyFrames() + { + if (my_frames) { + for (uint32 i = 0; i < my_frame_num; i++) { + if (my_frames[i]) + wasm_runtime_free(my_frames[i]); + } + wasm_runtime_free(my_frames); + my_frames = NULL; + my_frame_num = 0; + } + } + + public: + RuntimeInitArgs init_args; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_function_inst_t func_inst = NULL; + wasm_exec_env_t exec_env = NULL; + static MyAOTFrame **my_frames; + static uint32 my_frame_num; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + unsigned char test_aot_buf[16 * 1024]; + unsigned argv[8]; +}; + +MyAOTFrame **AOTStackFrameTest::my_frames = NULL; +uint32 AOTStackFrameTest::my_frame_num = 0; + +extern "C" { + +typedef void (*stack_frame_callback_t)(struct WASMExecEnv *exec_env); + +void +aot_set_stack_frame_callback(stack_frame_callback_t callback); + +void +aot_stack_frame_cb(struct WASMExecEnv *exec_env) +{ + AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst; + AOTModule *module = (AOTModule *)module_inst->module; + AOTFrame *frame = (AOTFrame *)exec_env->cur_frame; + MyAOTFrame *my_frame, **my_frames; + uint32 all_cell_num, max_local_cell_num, max_stack_cell_num; + uint32 frame_size_old, frame_size, i, frame_num = 0, aot_func_idx; + + AOTStackFrameTest::DestroyFrames(); + + while (frame) { + frame_num++; + frame = frame->prev_frame; + } + + my_frames = + (MyAOTFrame **)wasm_runtime_malloc(sizeof(MyAOTFrame *) * frame_num); + bh_assert(my_frames); + + frame = (AOTFrame *)exec_env->cur_frame; + for (i = 0; i < frame_num; i++) { + aot_func_idx = frame->func_index; + max_local_cell_num = module->max_local_cell_nums[aot_func_idx]; + max_stack_cell_num = module->max_stack_cell_nums[aot_func_idx]; + all_cell_num = max_local_cell_num + max_stack_cell_num; + + frame_size_old = (uint32)offsetof(AOTFrame, lp) + all_cell_num * 4; + frame_size = (uint32)offsetof(MyAOTFrame, lp) + all_cell_num * 4; + + my_frames[frame_num - 1 - i] = my_frame = + (MyAOTFrame *)wasm_runtime_malloc(frame_size); + + my_frame->func_index = aot_func_idx; + my_frame->ip_offset = frame->ip_offset; + my_frame->sp = my_frame->lp + (frame->sp - frame->lp); +#if WASM_ENABLE_GC != 0 + my_frame->frame_ref = + (uint8 *)my_frame->lp + (frame->frame_ref - (uint8 *)frame->lp); +#endif + + bh_memcpy_s(my_frame->lp, all_cell_num * 4, frame->lp, + all_cell_num * 4); + + frame = frame->prev_frame; + } + + AOTStackFrameTest::my_frames = my_frames; + AOTStackFrameTest::my_frame_num = frame_num; +} +} + +TEST_F(AOTStackFrameTest, test1) +{ + MyAOTFrame *frame, **frames; + uint32 frame_num; + + aot_set_stack_frame_callback(aot_stack_frame_cb); + + bh_memcpy_s(test_aot_buf, sizeof(test_aot_buf), test_aot, sizeof(test_aot)); + + module = wasm_runtime_load(test_aot_buf, sizeof(test_aot), error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + module_inst = wasm_runtime_instantiate(module, 16384, 0, error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + func_inst = wasm_runtime_lookup_function(module_inst, "test1"); + ASSERT_TRUE(func_inst != NULL); + + argv[0] = 33; + argv[1] = 44; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst)); + + frames = AOTStackFrameTest::my_frames; + frame_num = AOTStackFrameTest::my_frame_num; + + ASSERT_TRUE(frames != NULL); + ASSERT_TRUE(frame_num == 1); + + ASSERT_TRUE(frames[0]->lp[0] == 33); + ASSERT_TRUE(frames[0]->lp[1] == 44); + ASSERT_TRUE(frames[0]->lp[2] == 0x11223344); + ASSERT_TRUE(*(uint64 *)(frames[0]->lp + 3) == 0x12345678ABCDEF99LL); + ASSERT_TRUE(*(float *)(frames[0]->lp + 5) == 5566.7788f); + ASSERT_TRUE(*(double *)(frames[0]->lp + 6) == 99887766.55443322); + + wasm_runtime_destroy_exec_env(exec_env); + exec_env = NULL; + + wasm_runtime_deinstantiate(module_inst); + module_inst = NULL; + + wasm_runtime_unload(module); + module = NULL; +} + +TEST_F(AOTStackFrameTest, test2) +{ + MyAOTFrame *frame, **frames; + uint32 frame_num; + + aot_set_stack_frame_callback(aot_stack_frame_cb); + + bh_memcpy_s(test_aot_buf, sizeof(test_aot_buf), test_aot, sizeof(test_aot)); + + module = wasm_runtime_load(test_aot_buf, sizeof(test_aot), error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + module_inst = wasm_runtime_instantiate(module, 16384, 0, error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + func_inst = wasm_runtime_lookup_function(module_inst, "test2"); + ASSERT_TRUE(func_inst != NULL); + + argv[0] = 1234; + argv[1] = 5678; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst)); + + frames = AOTStackFrameTest::my_frames; + frame_num = AOTStackFrameTest::my_frame_num; + + ASSERT_TRUE(frames != NULL); + ASSERT_TRUE(frame_num == 1); + + ASSERT_TRUE(frames[0]->lp[0] == 1234); + ASSERT_TRUE(frames[0]->lp[1] == 5678); + ASSERT_TRUE(frames[0]->lp[2] == 0x11223344); + ASSERT_TRUE(*(uint64 *)(frames[0]->lp + 3) == 0x12345678ABCDEF99LL); + ASSERT_TRUE(*(float *)(frames[0]->lp + 5) == 5566.7788f); + ASSERT_TRUE(*(double *)(frames[0]->lp + 6) == 99887766.55443322); + ASSERT_TRUE(frames[0]->lp[8] == 0x1234); + ASSERT_TRUE(frames[0]->lp[9] == 0x5678); +} + +TEST_F(AOTStackFrameTest, test3) +{ + MyAOTFrame *frame, **frames; + uint32 frame_num; + + aot_set_stack_frame_callback(aot_stack_frame_cb); + + bh_memcpy_s(test_aot_buf, sizeof(test_aot_buf), test_aot, sizeof(test_aot)); + + module = wasm_runtime_load(test_aot_buf, sizeof(test_aot), error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + module_inst = wasm_runtime_instantiate(module, 16384, 0, error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + func_inst = wasm_runtime_lookup_function(module_inst, "test3"); + ASSERT_TRUE(func_inst != NULL); + + argv[0] = 1234; + argv[1] = 5678; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst)); + + frames = AOTStackFrameTest::my_frames; + frame_num = AOTStackFrameTest::my_frame_num; + + ASSERT_TRUE(frames != NULL); + ASSERT_TRUE(frame_num == 2); + + ASSERT_TRUE(frames[0]->sp - frames[0]->lp == 5); + ASSERT_TRUE(frames[0]->ip_offset == 24); + + ASSERT_TRUE(frames[0]->lp[0] == 1234); + ASSERT_TRUE(frames[0]->lp[1] == 5678); + ASSERT_TRUE(frames[0]->lp[2] == 0x11223344); + ASSERT_TRUE(*(uint64 *)(frames[0]->lp + 3) == 0x12345678ABCDEF99LL); + + ASSERT_TRUE(frames[1]->lp[0] == 0x1234); + ASSERT_TRUE(frames[1]->lp[1] == 0x5678); + ASSERT_TRUE(frames[1]->lp[2] == 0x11223344); + ASSERT_TRUE(*(uint64 *)(frames[1]->lp + 3) == 0x12345678ABCDEF99LL); + ASSERT_TRUE(*(float *)(frames[1]->lp + 5) == 5566.7788f); + ASSERT_TRUE(*(double *)(frames[1]->lp + 6) == 99887766.55443322); +} diff --git a/tests/unit/aot-stack-frame/wasm-apps/CMakeLists.txt b/tests/unit/aot-stack-frame/wasm-apps/CMakeLists.txt new file mode 100644 index 000000000..9dd9565a5 --- /dev/null +++ b/tests/unit/aot-stack-frame/wasm-apps/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project(wasm-apps-aot-stack-frame) + +add_custom_target(aot-stack-frame-test-wasm ALL + COMMAND cmake -B ${CMAKE_CURRENT_BINARY_DIR}/build-wamrc + -S ${WAMR_ROOT_DIR}/wamr-compiler + && cmake --build ${CMAKE_CURRENT_BINARY_DIR}/build-wamrc + && /opt/wabt/bin/wat2wasm + -o ${CMAKE_CURRENT_BINARY_DIR}/test.wasm + ${CMAKE_CURRENT_LIST_DIR}/test.wast + && ${CMAKE_CURRENT_BINARY_DIR}/build-wamrc/wamrc + --enable-dump-call-stack --bounds-checks=1 + -o ${CMAKE_CURRENT_BINARY_DIR}/test.aot + ${CMAKE_CURRENT_BINARY_DIR}/test.wasm + && cmake -B ${CMAKE_CURRENT_BINARY_DIR}/build-binarydump + -S ${WAMR_ROOT_DIR}/test-tools/binarydump-tool + && cmake --build ${CMAKE_CURRENT_BINARY_DIR}/build-binarydump + && ${CMAKE_CURRENT_BINARY_DIR}/build-binarydump/binarydump + -o ${CMAKE_CURRENT_LIST_DIR}/test_aot.h -n test_aot + ${CMAKE_CURRENT_BINARY_DIR}/test.aot + +) + diff --git a/tests/unit/aot-stack-frame/wasm-apps/test.wast b/tests/unit/aot-stack-frame/wasm-apps/test.wast new file mode 100644 index 000000000..1ef866efc --- /dev/null +++ b/tests/unit/aot-stack-frame/wasm-apps/test.wast @@ -0,0 +1,36 @@ +(module + (func $test1 (export "test1") (param i32 i32) (result i32) + i32.const 0x11223344 + i64.const 0x1234_5678_ABCD_EF99 + f32.const 5566.7788 + f64.const 99887766.55443322 + unreachable + ) + + (func $test2 (export "test2") (param f32 f32) (result i32) + i32.const 0x11223344 + i64.const 0x1234_5678_ABCD_EF99 + f32.const 5566.7788 + f64.const 99887766.55443322 + + loop + i32.const 0x1234 + i32.const 0x5678 + unreachable + end + + unreachable + ) + + (func $test3 (export "test3") (param i32 i32) (result i32) + i32.const 0x11223344 + i64.const 0x1234_5678_ABCD_EF99 + + i32.const 0x1234 + i32.const 0x5678 + call $test1 + + drop + drop + ) +) diff --git a/tests/unit/aot/CMakeLists.txt b/tests/unit/aot/CMakeLists.txt new file mode 100644 index 000000000..6b9c70c88 --- /dev/null +++ b/tests/unit/aot/CMakeLists.txt @@ -0,0 +1,59 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-aot) + +add_definitions (-DRUN_ON_LINUX) + +add_definitions (-Dattr_container_malloc=malloc) +add_definitions (-Dattr_container_free=free) +add_definitions (-DWASM_ENABLE_WAMR_COMPILER=1) +add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1) +add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 1) + +include (../unit_common.cmake) + +set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") +if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif () +set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include (${IWASM_DIR}/compilation/iwasm_compl.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable (aot_test ${unit_test_sources}) + +target_link_libraries (aot_test ${LLVM_AVAILABLE_LIBS} gtest_main ) + +gtest_discover_tests(aot_test) + diff --git a/tests/unit/aot/aot_test.cc b/tests/unit/aot/aot_test.cc new file mode 100644 index 000000000..261b378e4 --- /dev/null +++ b/tests/unit/aot/aot_test.cc @@ -0,0 +1,1190 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include "gtest/gtest.h" +#include "wasm_export.h" +#include "bh_platform.h" +#include "aot_llvm.h" +#include "aot_intrinsic.h" +#include "aot.h" + +#define G_INTRINSIC_COUNT (50u) +#define CONS(num) ("f##num##.const") + +const char *llvm_intrinsic_tmp[G_INTRINSIC_COUNT] = { + "llvm.experimental.constrained.fadd.f32", + "llvm.experimental.constrained.fadd.f64", + "llvm.experimental.constrained.fsub.f32", + "llvm.experimental.constrained.fsub.f64", + "llvm.experimental.constrained.fmul.f32", + "llvm.experimental.constrained.fmul.f64", + "llvm.experimental.constrained.fdiv.f32", + "llvm.experimental.constrained.fdiv.f64", + "llvm.fabs.f32", + "llvm.fabs.f64", + "llvm.ceil.f32", + "llvm.ceil.f64", + "llvm.floor.f32", + "llvm.floor.f64", + "llvm.trunc.f32", + "llvm.trunc.f64", + "llvm.rint.f32", + "llvm.rint.f64", + "llvm.sqrt.f32", + "llvm.sqrt.f64", + "llvm.copysign.f32", + "llvm.copysign.f64", + "llvm.minnum.f32", + "llvm.minnum.f64", + "llvm.maxnum.f32", + "llvm.maxnum.f64", + "llvm.ctlz.i32", + "llvm.ctlz.i64", + "llvm.cttz.i32", + "llvm.cttz.i64", + "llvm.ctpop.i32", + "llvm.ctpop.i64", + "f64_convert_i32_s", + "f64_convert_i32_u", + "f32_convert_i32_s", + "f32_convert_i32_u", + "f64_convert_i64_s", + "f64_convert_i64_u", + "f32_convert_i64_s", + "f32_convert_i64_u", + "i32_trunc_f32_u", + "i32_trunc_f32_s", + "i32_trunc_f64_u", + "i32_trunc_f64_s", + "f32_demote_f64", + "f64_promote_f32", + "f32_cmp", + "f64_cmp", + "f32.const", + "f64.const", +}; + +uint64 g_intrinsic_flag[G_INTRINSIC_COUNT] = { + AOT_INTRINSIC_FLAG_F32_FADD, AOT_INTRINSIC_FLAG_F64_FADD, + AOT_INTRINSIC_FLAG_F32_FSUB, AOT_INTRINSIC_FLAG_F64_FSUB, + AOT_INTRINSIC_FLAG_F32_FMUL, AOT_INTRINSIC_FLAG_F64_FMUL, + AOT_INTRINSIC_FLAG_F32_FDIV, AOT_INTRINSIC_FLAG_F64_FDIV, + AOT_INTRINSIC_FLAG_F32_FABS, AOT_INTRINSIC_FLAG_F64_FABS, + AOT_INTRINSIC_FLAG_F32_CEIL, AOT_INTRINSIC_FLAG_F64_CEIL, + AOT_INTRINSIC_FLAG_F32_FLOOR, AOT_INTRINSIC_FLAG_F64_FLOOR, + AOT_INTRINSIC_FLAG_F32_TRUNC, AOT_INTRINSIC_FLAG_F64_TRUNC, + AOT_INTRINSIC_FLAG_F32_RINT, AOT_INTRINSIC_FLAG_F64_RINT, + AOT_INTRINSIC_FLAG_F32_SQRT, AOT_INTRINSIC_FLAG_F64_SQRT, + AOT_INTRINSIC_FLAG_F32_COPYSIGN, AOT_INTRINSIC_FLAG_F64_COPYSIGN, + AOT_INTRINSIC_FLAG_F32_MIN, AOT_INTRINSIC_FLAG_F64_MIN, + AOT_INTRINSIC_FLAG_F32_MAX, AOT_INTRINSIC_FLAG_F64_MAX, + AOT_INTRINSIC_FLAG_I32_CLZ, AOT_INTRINSIC_FLAG_I64_CLZ, + AOT_INTRINSIC_FLAG_I32_CTZ, AOT_INTRINSIC_FLAG_I64_CTZ, + AOT_INTRINSIC_FLAG_I32_POPCNT, AOT_INTRINSIC_FLAG_I64_POPCNT, + AOT_INTRINSIC_FLAG_I32_TO_F64, AOT_INTRINSIC_FLAG_U32_TO_F64, + AOT_INTRINSIC_FLAG_I32_TO_F32, AOT_INTRINSIC_FLAG_U32_TO_F32, + AOT_INTRINSIC_FLAG_I32_TO_F64, AOT_INTRINSIC_FLAG_U64_TO_F64, + AOT_INTRINSIC_FLAG_I64_TO_F32, AOT_INTRINSIC_FLAG_U64_TO_F32, + AOT_INTRINSIC_FLAG_F32_TO_U32, AOT_INTRINSIC_FLAG_F32_TO_I32, + AOT_INTRINSIC_FLAG_F64_TO_U32, AOT_INTRINSIC_FLAG_F64_TO_I32, + AOT_INTRINSIC_FLAG_F64_TO_F32, AOT_INTRINSIC_FLAG_F32_TO_F64, + AOT_INTRINSIC_FLAG_F32_CMP, AOT_INTRINSIC_FLAG_F64_CMP, + AOT_INTRINSIC_FLAG_F32_CONST, AOT_INTRINSIC_FLAG_F64_CONST, +}; + +// To use a test fixture, derive a class from testing::Test. +class AOTTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() { wasm_runtime_destroy(); } + + public: + char global_heap_buf[512 * 1024]; + RuntimeInitArgs init_args; +}; + +TEST_F(AOTTest, aot_value_stack_push_pop) +{ + AOTValueStack *stack; + AOTValue *value1, *value2, *value3; + AOTCompContext comp_ctx = { 0 }; + + stack = (AOTValueStack *)wasm_runtime_malloc(sizeof(AOTValueStack)); + EXPECT_TRUE(stack != NULL); + + memset(stack, 0, sizeof(AOTValueStack)); + + value1 = (AOTValue *)wasm_runtime_malloc(sizeof(AOTValue)); + EXPECT_TRUE(value1 != NULL); + + memset(value1, 0, sizeof(AOTValue)); + value1->type = VALUE_TYPE_I32; + + aot_value_stack_push(&comp_ctx, stack, value1); + EXPECT_EQ(stack->value_list_head, value1); + EXPECT_EQ(stack->value_list_end, value1); + + value2 = (AOTValue *)wasm_runtime_malloc(sizeof(AOTValue)); + EXPECT_TRUE(value2 != NULL); + + memset(value2, 0, sizeof(AOTValue)); + value2->type = VALUE_TYPE_I64; + + aot_value_stack_push(&comp_ctx, stack, value2); + EXPECT_EQ(stack->value_list_head, value1); + EXPECT_EQ(stack->value_list_end, value2); + EXPECT_EQ(value2->prev, value1); + + value3 = aot_value_stack_pop(&comp_ctx, stack); + EXPECT_EQ(value3, value2); + EXPECT_EQ(stack->value_list_head, value1); + EXPECT_EQ(stack->value_list_end, value1); + EXPECT_TRUE(value3->prev == NULL); + + aot_value_stack_destroy(&comp_ctx, stack); + wasm_runtime_free(value3); + wasm_runtime_free(stack); +} + +TEST_F(AOTTest, aot_block_stack_push_pop) +{ + AOTBlockStack *stack; + AOTBlock *block1, *block2, *block3; + AOTCompContext comp_ctx = { 0 }; + + stack = (AOTBlockStack *)wasm_runtime_malloc(sizeof(AOTBlockStack)); + EXPECT_TRUE(stack != NULL); + + memset(stack, 0, sizeof(AOTBlockStack)); + + block1 = (AOTBlock *)wasm_runtime_malloc(sizeof(AOTBlock)); + EXPECT_TRUE(block1 != NULL); + + memset(block1, 0, sizeof(AOTBlock)); + block1->label_type = LABEL_TYPE_LOOP; + + aot_block_stack_push(stack, block1); + EXPECT_EQ(stack->block_list_head, block1); + EXPECT_EQ(stack->block_list_end, block1); + + block2 = (AOTBlock *)wasm_runtime_malloc(sizeof(AOTBlock)); + EXPECT_TRUE(block2 != NULL); + + memset(block2, 0, sizeof(AOTBlock)); + block2->label_type = LABEL_TYPE_IF; + + aot_block_stack_push(stack, block2); + EXPECT_EQ(stack->block_list_head, block1); + EXPECT_EQ(stack->block_list_end, block2); + EXPECT_EQ(block2->prev, block1); + + block3 = aot_block_stack_pop(stack); + EXPECT_EQ(block3, block2); + EXPECT_EQ(stack->block_list_head, block1); + EXPECT_EQ(stack->block_list_end, block1); + EXPECT_TRUE(block3->prev == NULL); + + aot_block_stack_destroy(&comp_ctx, stack); + wasm_runtime_free(block3); + wasm_runtime_free(stack); +} + +TEST_F(AOTTest, aot_intrinsic_fadd_f32) +{ + float32 a = 1.0; + float32 b = 1.0; + EXPECT_EQ(aot_intrinsic_fadd_f32(a, b), (a + b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fadd_f32(a, b), (a + b)); +} + +TEST_F(AOTTest, aot_intrinsic_fadd_f64) +{ + float64 a = 1.0; + float64 b = 1.0; + EXPECT_EQ(aot_intrinsic_fadd_f64(a, b), (a + b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fadd_f64(a, b), (a + b)); +} + +TEST_F(AOTTest, aot_intrinsic_fsub_f32) +{ + float32 a = 1.0; + float32 b = 1.0; + EXPECT_EQ(aot_intrinsic_fsub_f32(a, b), (a - b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fsub_f32(a, b), (a - b)); +} + +TEST_F(AOTTest, aot_intrinsic_fsub_f64) +{ + float64 a = 1.0; + float64 b = 1.0; + EXPECT_EQ(aot_intrinsic_fsub_f64(a, b), (a - b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fsub_f64(a, b), (a - b)); +} + +TEST_F(AOTTest, aot_intrinsic_fmul_f32) +{ + float32 a = 1.0; + float32 b = 1.0; + EXPECT_EQ(aot_intrinsic_fmul_f32(a, b), (a * b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fmul_f32(a, b), (a * b)); +} + +TEST_F(AOTTest, aot_intrinsic_fmul_f64) +{ + float64 a = 1.0; + float64 b = 1.0; + EXPECT_EQ(aot_intrinsic_fmul_f64(a, b), (a * b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fmul_f64(a, b), (a * b)); +} + +TEST_F(AOTTest, aot_intrinsic_fdiv_f32) +{ + float32 a = 1.0; + float32 b = 1.0; + EXPECT_EQ(aot_intrinsic_fdiv_f32(a, b), (a / b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fdiv_f32(a, b), (a / b)); + + a = -1.0; + b = 0.0; + EXPECT_EQ(aot_intrinsic_fdiv_f32(a, b), (a / b)); +} + +TEST_F(AOTTest, aot_intrinsic_fdiv_f64) +{ + float64 a = 1.0; + float64 b = 1.0; + EXPECT_EQ(aot_intrinsic_fdiv_f64(a, b), (a / b)); + + a = -1.0; + b = -1.0; + EXPECT_EQ(aot_intrinsic_fdiv_f64(a, b), (a / b)); + + a = -1.0; + b = 0.0; + EXPECT_EQ(aot_intrinsic_fdiv_f64(a, b), (a / b)); +} + +TEST_F(AOTTest, aot_intrinsic_fabs_f32) +{ + float32 a = 1.0; + EXPECT_EQ(aot_intrinsic_fabs_f32(a), fabs(a)); + + a = -1.0; + EXPECT_EQ(aot_intrinsic_fabs_f32(a), fabs(a)); + + a = -1.5; + EXPECT_EQ(aot_intrinsic_fabs_f32(a), fabs(a)); +} + +TEST_F(AOTTest, aot_intrinsic_fabs_f64) +{ + float64 a = 1.0; + EXPECT_EQ(aot_intrinsic_fabs_f64(a), fabs(a)); + + a = -1.0; + EXPECT_EQ(aot_intrinsic_fabs_f64(a), fabs(a)); + + a = -1.5; + EXPECT_EQ(aot_intrinsic_fabs_f64(a), fabs(a)); +} + +TEST_F(AOTTest, aot_intrinsic_ceil_f32) +{ + float32 a = 1.0; + EXPECT_EQ(aot_intrinsic_ceil_f32(a), ceilf(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_ceil_f32(a), 2); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_ceil_f32(a), 2); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_ceil_f32(a), -1); +} + +TEST_F(AOTTest, aot_intrinsic_ceil_f64) +{ + float64 a = 1.0; + EXPECT_EQ(aot_intrinsic_ceil_f64(a), ceil(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_ceil_f64(a), 2); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_ceil_f64(a), 2); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_ceil_f64(a), -1); +} + +TEST_F(AOTTest, aot_intrinsic_floor_f32) +{ + float32 a = 1.0; + EXPECT_EQ(aot_intrinsic_floor_f32(a), floorf(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_floor_f32(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_floor_f32(a), 1); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_floor_f32(a), -2); +} + +TEST_F(AOTTest, aot_intrinsic_floor_f64) +{ + float64 a = 1.0; + EXPECT_EQ(aot_intrinsic_floor_f64(a), floor(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_floor_f64(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_floor_f64(a), 1); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_floor_f64(a), -2); +} + +TEST_F(AOTTest, aot_intrinsic_trunc_f32) +{ + float32 a = 1.0; + EXPECT_EQ(aot_intrinsic_trunc_f32(a), trunc(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_trunc_f32(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_trunc_f32(a), 1); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_trunc_f32(a), -1); +} + +TEST_F(AOTTest, aot_intrinsic_trunc_f64) +{ + float64 a = 1.0; + EXPECT_EQ(aot_intrinsic_trunc_f64(a), trunc(a)); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_trunc_f64(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_trunc_f64(a), 1); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_trunc_f64(a), -1); +} + +TEST_F(AOTTest, aot_intrinsic_rint_f32) +{ + float32 a = 1.0; + EXPECT_EQ(aot_intrinsic_rint_f32(a), rint(a)); + EXPECT_EQ(aot_intrinsic_rint_f32(a), 1); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_rint_f32(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_rint_f32(a), 2); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_rint_f32(a), -2); +} + +TEST_F(AOTTest, aot_intrinsic_rint_f64) +{ + float64 a = 1.0; + EXPECT_EQ(aot_intrinsic_rint_f64(a), rint(a)); + EXPECT_EQ(aot_intrinsic_rint_f64(a), 1); + + a = 1.1; + EXPECT_EQ(aot_intrinsic_rint_f64(a), 1); + + a = 1.9; + EXPECT_EQ(aot_intrinsic_rint_f64(a), 2); + + a = -1.9; + EXPECT_EQ(aot_intrinsic_rint_f64(a), -2); +} + +TEST_F(AOTTest, aot_intrinsic_sqrt_f32) +{ + float32 a = 2.0; + EXPECT_EQ(aot_intrinsic_sqrt_f32(a), sqrt(a)); + + a = 2; + EXPECT_EQ(aot_intrinsic_sqrt_f32(a), sqrt(a)); +} + +TEST_F(AOTTest, aot_intrinsic_sqrt_f64) +{ + float64 a = 2.0; + EXPECT_EQ(aot_intrinsic_sqrt_f64(a), sqrt(a)); + + a = 2; + EXPECT_EQ(aot_intrinsic_sqrt_f64(a), sqrt(a)); +} + +TEST_F(AOTTest, aot_intrinsic_copysign_f32) +{ + float32 a = 20.0; + float32 b = 2.0; + + EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), fabs(a)); + + b = 1.5; + EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), fabs(a)); + + b = -2.0; + EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), -fabs(a)); + + a = -20.0; + b = -1.5; + EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), -fabs(a)); +} + +TEST_F(AOTTest, aot_intrinsic_copysign_f64) +{ + float64 a = 20.0; + float64 b = 2.0; + + EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), fabs(a)); + + b = 1.5; + EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), fabs(a)); + + b = -2.0; + EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), -fabs(a)); + + a = -20.0; + b = -1.5; + EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), -fabs(a)); +} + +TEST_F(AOTTest, aot_intrinsic_fmin_f32) +{ + float32 a = 1.2; + float32 b = 2.5; + + EXPECT_EQ(aot_intrinsic_fmin_f32(a, b), a); + + a = -3; + b = -1; + EXPECT_EQ(aot_intrinsic_fmin_f32(a, b), a); + + b = 1; + EXPECT_EQ(aot_intrinsic_fmin_f32('a', b), b); + + a = 3; + EXPECT_EQ(aot_intrinsic_fmin_f32(a, 'b'), a); + + EXPECT_EQ(aot_intrinsic_fmin_f32('a', 'b'), 'a'); + + EXPECT_EQ(aot_intrinsic_fmin_f32('b', 'c'), 'b'); + EXPECT_EQ(aot_intrinsic_fmin_f32('c', 'b'), 'b'); + + EXPECT_EQ(aot_intrinsic_fmin_f32(true, 2.5), 1); + EXPECT_EQ(aot_intrinsic_fmin_f32(1.0, false), 0); + + EXPECT_NE(aot_intrinsic_fmin_f32(sqrt(-1), 3), 3); + EXPECT_NE(aot_intrinsic_fmin_f32(3, sqrt(-1)), 3); +} + +TEST_F(AOTTest, aot_intrinsic_fmin_f64) +{ + float64 a = 1.00000000; + float64 b = 3.00000000; + + EXPECT_EQ(aot_intrinsic_fmin_f64(a, b), a); + + EXPECT_EQ(aot_intrinsic_fmin_f64(-a, b), -a); + + EXPECT_EQ(aot_intrinsic_fmin_f64(-a, -b), -b); + + EXPECT_EQ(aot_intrinsic_fmin_f64(a, -b), -b); + + EXPECT_EQ(aot_intrinsic_fmin_f64(a, a), a); + + a = 0.0000; + EXPECT_EQ(aot_intrinsic_fmin_f64(-a, -a), -a); +} + +TEST_F(AOTTest, aot_intrinsic_fmax_f32) +{ + float32 a = 1.2; + float32 b = 2.5; + + EXPECT_EQ(aot_intrinsic_fmax_f32(a, b), b); + + a = -3; + b = -1; + EXPECT_EQ(aot_intrinsic_fmax_f32(a, b), b); + + b = 1; + EXPECT_EQ(aot_intrinsic_fmax_f32('a', b), 'a'); + + a = 3; + EXPECT_EQ(aot_intrinsic_fmax_f32(a, 'b'), 'b'); + + EXPECT_EQ(aot_intrinsic_fmax_f32('a', 'b'), 'b'); + + EXPECT_EQ(aot_intrinsic_fmax_f32(' ', 'b'), 'b'); + EXPECT_EQ(aot_intrinsic_fmax_f32('a', ' '), 'a'); + + EXPECT_NE(aot_intrinsic_fmax_f32(sqrt(-1), 3), 3); + EXPECT_NE(aot_intrinsic_fmax_f32(3, sqrt(-1)), 3); +} + +TEST_F(AOTTest, aot_intrinsic_fmax_f64) +{ + float64 a = 1.00000000; + float64 b = 3.00000000; + + EXPECT_EQ(aot_intrinsic_fmax_f64(a, b), b); + + EXPECT_EQ(aot_intrinsic_fmax_f64(-a, b), b); + + EXPECT_EQ(aot_intrinsic_fmax_f64(-a, -b), -a); + + EXPECT_EQ(aot_intrinsic_fmax_f64(a, -b), a); + + EXPECT_EQ(aot_intrinsic_fmax_f64(a, a), a); + + a = 0.0000; + EXPECT_EQ(aot_intrinsic_fmax_f64(-a, -a), -a); + + EXPECT_EQ(aot_intrinsic_fmax_f64(-0, -0), -0); +} + +TEST_F(AOTTest, aot_intrinsic_clz_i32) +{ + uint32 type = 0; + uint32 data = 0; + uint32 num = 0; + + EXPECT_EQ(aot_intrinsic_clz_i32(0), 32); + + for (uint32 i = 0; i < 0xFFFF; i++) { + /* Generate random numbers [1,0xFFFFFFFF] */ + type = 1 + (rand() % (0xFFFFFFFF - 1 + 1)); + data = type; + while (!(type & 0x80000000)) { + num++; + type <<= 1; + } + EXPECT_EQ(aot_intrinsic_clz_i32(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_clz_i32(0xFFFFFFFF), 0); +} + +TEST_F(AOTTest, aot_intrinsic_clz_i64) +{ + uint64 type = 0; + uint64 data = 0; + uint64 num = 0; + + EXPECT_EQ(aot_intrinsic_clz_i64(0), 64); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + /* Generate random numbers [1,0xFFFFFFFFFFFFFFFF] */ + type = 1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1)); + data = type; + while (!(type & 0x8000000000000000LL)) { + num++; + type <<= 1; + } + EXPECT_EQ(aot_intrinsic_clz_i64(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_clz_i64(0xFFFFFFFFFFFFFFFF), 0); +} + +TEST_F(AOTTest, ast_intrinsic_ctz_i32) +{ + uint32 type = 0; + uint32 data = 0; + uint32 num = 0; + + EXPECT_EQ(aot_intrinsic_ctz_i32(0), 32); + + for (uint32 i = 0; i < 0xFFFF; i++) { + type = 1 + (rand() % (0xFFFFFFFF - 1 + 1)); + data = type; + while (!(type & 1)) { + num++; + type >>= 1; + } + EXPECT_EQ(aot_intrinsic_ctz_i32(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_ctz_i32(0xFFFFFFFF), 0); +} + +TEST_F(AOTTest, ast_intrinsic_ctz_i64) +{ + uint64 type = 0; + uint64 data = 0; + uint64 num = 0; + + EXPECT_EQ(aot_intrinsic_ctz_i64(0), 64); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + type = 1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1)); + data = type; + while (!(type & 1)) { + num++; + type >>= 1; + } + EXPECT_EQ(aot_intrinsic_ctz_i64(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_ctz_i64(0xFFFFFFFFFFFFFFFF), 0); +} + +TEST_F(AOTTest, aot_intrinsic_popcnt_i32) +{ + uint32 data = 0; + uint32 num = 0; + uint32 temp = 0; + + EXPECT_EQ(aot_intrinsic_popcnt_i32(0), 0); + + for (uint32 i = 0; i < 0xFFFF; i++) { + temp = 1 + (rand() % (0x100000000 - 1 + 1)); + data = temp; + + while (temp) { + if (temp & 0x01) + num++; + temp >>= 1; + } + EXPECT_EQ(aot_intrinsic_popcnt_i32(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_popcnt_i32(0xFFFFFFFF), 32); +} + +TEST_F(AOTTest, aot_intrinsic_popcnt_i64) +{ + uint64 data = 0; + uint64 num = 0; + uint64 temp = 0; + + EXPECT_EQ(aot_intrinsic_popcnt_i64(0x00), 0); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + temp = 1 + (rand() % (0xFFFFFFFFFFFFFFFFLL - 1 + 1)); + data = temp; + + while (temp) { + if (temp & 0x01) + num++; + temp >>= 1; + } + EXPECT_EQ(aot_intrinsic_popcnt_i64(data), num); + num = 0; + } + + EXPECT_EQ(aot_intrinsic_popcnt_i64(0xFFFFFFFFFFFFFFFF), 64); +} + +TEST_F(AOTTest, aot_intrinsic_i32_to_f32) +{ + int32 idata = 0; + + EXPECT_EQ(aot_intrinsic_i32_to_f32(idata), (float32)idata); + + for (uint32 i = 0; i < 0xFFFF; i++) { + idata = (int32)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_i32_to_f32(idata), (float32)idata); + } + + idata = 0xFFFFFFFF; + EXPECT_EQ(aot_intrinsic_i32_to_f32(idata), (float32)idata); +} + +TEST_F(AOTTest, aot_intrinsic_u32_to_f32) +{ + uint32 udata = 0; + + EXPECT_EQ(aot_intrinsic_u32_to_f32(udata), (float32)udata); + + for (uint32 i = 0; i < 0xFFFF; i++) { + udata = (uint32)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_u32_to_f32(udata), (float32)udata); + } + + udata = 0xFFFFFFFF; + EXPECT_EQ(aot_intrinsic_u32_to_f32(udata), (float32)udata); +} + +TEST_F(AOTTest, aot_intrinsic_i32_to_f64) +{ + int32 idata = 0; + + EXPECT_EQ(aot_intrinsic_i32_to_f64(idata), (float64)idata); + + for (uint32 i = 0; i < 0xFFFF; i++) { + idata = (int32)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_i32_to_f64(idata), (float64)idata); + } + + idata = 0xFFFFFFFF; + EXPECT_EQ(aot_intrinsic_i32_to_f64(idata), (float64)idata); +} + +TEST_F(AOTTest, aot_intrinsic_u32_to_f64) +{ + uint32 udata = 0; + + EXPECT_EQ(aot_intrinsic_u32_to_f64(udata), (float64)udata); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + udata = (uint32)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_u32_to_f64(udata), (float64)udata); + } + + udata = 0xFFFFFFFF; + EXPECT_EQ(aot_intrinsic_u32_to_f64(udata), (float64)udata); +} + +TEST_F(AOTTest, aot_intrinsic_i64_to_f32) +{ + int64 idata = 0LL; + + EXPECT_EQ(aot_intrinsic_i64_to_f32(idata), (float32)idata); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + idata = (int64)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_i64_to_f32(idata), (float32)idata); + } + + idata = 0xFFFFFFFFFFFFFFFFLL; + EXPECT_EQ(aot_intrinsic_i64_to_f32(idata), (float32)idata); +} + +TEST_F(AOTTest, aot_intrinsic_u64_to_f32) +{ + uint64 udata = 0LL; + + EXPECT_EQ(aot_intrinsic_u64_to_f32(udata), (float32)udata); + + for (uint32 i = 0; i < 0xFFFFF; i++) { + udata = (uint64)(1 + (rand() % (0xFFFFFFFF - 1 + 1))); + EXPECT_EQ(aot_intrinsic_u64_to_f32(udata), (float32)udata); + } + + udata = 0xFFFFFFFFFFFFFFFFLL; + EXPECT_EQ(aot_intrinsic_u64_to_f32(udata), (float32)udata); +} + +TEST_F(AOTTest, aot_intrinsic_i64_to_f64) +{ + int64 idata = 0LL; + + EXPECT_EQ(aot_intrinsic_i64_to_f64(idata), float64(idata)); + + for (uint32_t i = 0; i < 0xFFFFF; i++) { + idata = (int64)(1 + (rand() % (0xFFFFFFFFFFFFFFFLL - 1 + 1))); + EXPECT_EQ(aot_intrinsic_i64_to_f64(idata), (float64)idata); + } + + idata = 0xFFFFFFFFFFFFFFFFLL; + EXPECT_EQ(aot_intrinsic_i64_to_f64(idata), (float64)idata); +} + +TEST_F(AOTTest, aot_intrinsic_u64_to_f64) +{ + uint64 udata = 0LL; + + EXPECT_EQ(aot_intrinsic_u64_to_f64(udata), float64(udata)); + + for (uint32_t i = 0; i < 0xFFFFF; i++) { + udata = (uint64)(1 + (rand() % (0xFFFFFFFFFFFFFFFLL - 1 + 1))); + EXPECT_EQ(aot_intrinsic_u64_to_f64(udata), (float64)udata); + } + + udata = 0xFFFFFFFFFFFFFFFFLL; + EXPECT_EQ(aot_intrinsic_u64_to_f64(udata), (float64)udata); +} + +TEST_F(AOTTest, aot_intrinsic_f32_to_i32) +{ + float32 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f32_to_i32(data), (int32)data); + + for (uint32 i = 0; i < 0xFFFF; i++) { + data = (float32)((1 + (rand() % (100 - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f32_to_i32(data), (int32)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f32_to_u32) +{ + float32 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f32_to_u32(data), (uint32)data); + + for (uint32 i = 0; i < 0xFFFF; i++) { + data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f32_to_u32(data), (uint32)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f32_to_i64) +{ + float32 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f32_to_i64(data), (int64)data); + + for (uint32 i = 0; i < 0xFFFF; i++) { + data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f32_to_i64(data), (int64)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f32_to_u64) +{ + float32 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f32_to_u64(data), (uint64)data); + + for (uint32 i = 0; i < 0xFFFF; i++) { + data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f32_to_u64(data), (uint64)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f64_to_i32) +{ + float64 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f64_to_i32(data), (int32)data); + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f64_to_i32(data), (int32)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f64_to_u32) +{ + float64 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f64_to_u32(data), (uint32)data); + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f64_to_u32(data), (uint32)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f64_to_i64) +{ + float64 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f64_to_i64(data), (int64)data); + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f64_to_i64(data), (int64)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f64_to_u64) +{ + float64 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f64_to_u64(data), (uint64)data); + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f64_to_u64(data), (uint64)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f32_to_f64) +{ + float32 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f32_to_f64(data), (float64)data); + + for (uint32 i = 0; i < 0xFFFF; i++) { + data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + EXPECT_EQ(aot_intrinsic_f32_to_f64(data), (float64)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f64_to_f32) +{ + float64 data = 0.0; + + EXPECT_EQ(aot_intrinsic_f64_to_f32(data), (float32)data); + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.06); + EXPECT_EQ(aot_intrinsic_f32_to_f64(data), (float32)data); + } +} + +TEST_F(AOTTest, aot_intrinsic_f32_cmp) +{ + float32 lhs = 0.0; + float32 rhs = 0.0; + AOTFloatCond index = FLOAT_EQ; + uint32 res = 0; + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + index = (AOTFloatCond)(1 + (rand() % (6 - 1 + 1))); + lhs = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + rhs = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05); + + /* cond : 0 */ + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_EQ, lhs, rhs), + lhs == rhs ? 1 : 0); + + /* cond : 1-6 */ + switch (index) { + case FLOAT_LT: // 2 + res = (lhs < rhs ? 1 : 0); + break; + case FLOAT_GT: // 3 + res = (lhs > rhs ? 1 : 0); + break; + case FLOAT_LE: // 4 + res = (lhs <= rhs ? 1 : 0); + break; + case FLOAT_GE: // 5 + res = (lhs >= rhs ? 1 : 0); + break; + case FLOAT_NE: // 1 + res = (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0; + break; + case FLOAT_UNO: // 6 + res = (isnan(lhs) || isnan(rhs)) ? 1 : 0; + break; + + default: + break; + } + + EXPECT_EQ(aot_intrinsic_f32_cmp(index, lhs, rhs), res); + index = FLOAT_EQ; + + /* cond : > 6 */ + EXPECT_EQ(aot_intrinsic_f32_cmp((AOTFloatCond)(i + 7), lhs, rhs), 0); + } + + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_NE, true, false), 1); + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_NE, true, true), 0); + + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_UNO, true, false), 0); + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_UNO, true, true), 0); + + EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_UNO, 'a', 'b'), 0); +} + +TEST_F(AOTTest, aot_intrinsic_f64_cmp) +{ + float64 lhs = 0.0; + float64 rhs = 0.0; + AOTFloatCond index = FLOAT_EQ; + uint32 res = 0; + + for (uint32 i = 0; i < 0xFFFFFF; i++) { + index = (AOTFloatCond)(1 + (rand() % (6 - 1 + 1))); + lhs = (float32)((1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1))) - 0.05); + rhs = (float32)((1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1))) - 0.05); + + /* cond : 0 */ + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_EQ, lhs, rhs), + lhs == rhs ? 1 : 0); + + /* cond : 1-6 */ + switch (index) { + case FLOAT_LT: // 2 + res = (lhs < rhs ? 1 : 0); + break; + case FLOAT_GT: // 3 + res = (lhs > rhs ? 1 : 0); + break; + case FLOAT_LE: // 4 + res = (lhs <= rhs ? 1 : 0); + break; + case FLOAT_GE: // 5 + res = (lhs >= rhs ? 1 : 0); + break; + case FLOAT_NE: // 1 + res = (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0; + break; + case FLOAT_UNO: // 6 + res = (isnan(lhs) || isnan(rhs)) ? 1 : 0; + break; + + default: + break; + } + + EXPECT_EQ(aot_intrinsic_f64_cmp(index, lhs, rhs), res); + index = FLOAT_EQ; + + /* cond : > 6 */ + EXPECT_EQ(aot_intrinsic_f64_cmp((AOTFloatCond)(i + 7), lhs, rhs), 0); + } + + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_NE, true, false), 1); + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_NE, true, true), 0); + + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_UNO, true, false), 0); + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_UNO, true, true), 0); + + EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_UNO, 'a', 'b'), 0); +} + +TEST_F(AOTTest, aot_intrinsic_get_symbol) +{ + const char *llvm_intrinsic_t = NULL; + + for (int i = 0; i < 2; i++) { + if (i == 0) + llvm_intrinsic_t = CONS(32); + else + llvm_intrinsic_t = CONS(64); + + EXPECT_EQ((const char *)aot_intrinsic_get_symbol(llvm_intrinsic_t), + (const char *)NULL); + } + + for (int i = 0; i < G_INTRINSIC_COUNT - 2; i++) { + EXPECT_NE((const char *)aot_intrinsic_get_symbol(llvm_intrinsic_tmp[i]), + (const char *)NULL); + } +} + +TEST_F(AOTTest, aot_intrinsic_check_capability) +{ + AOTCompContext *comp_ctx = NULL; + AOTCompContext scomp_ctx = { 0 }; + const char *llvm_intrinsic_t = "f64_cmp"; + bool res = false; + uint64 flag = 0; + uint64 group = 0; + + comp_ctx = &scomp_ctx; + memset(comp_ctx->flags, 0, sizeof(comp_ctx->flags)); + + /* + EXPECT_FALSE(aot_intrinsic_check_capability(comp_ctx, (const char + *)NULL)); EXPECT_FALSE(aot_intrinsic_check_capability((const + AOTCompContext *)NULL, llvm_intrinsic_t)); + */ + + EXPECT_FALSE(aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_t)); + for (int i = 0; i < G_INTRINSIC_COUNT; i++) { + EXPECT_FALSE( + aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_tmp[i])); + } + + memset(comp_ctx->flags, 1, sizeof(comp_ctx->flags)); + EXPECT_FALSE(aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_t)); + for (int i = 0; i < G_INTRINSIC_COUNT; i++) { + flag = g_intrinsic_flag[i]; + group = AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag); + flag &= AOT_INTRINSIC_FLAG_MASK; + + res = aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_tmp[i]); + if ((flag & 0x01) || (flag & 0x100) || (flag & 0x10000) + || (flag & 0x1000000)) + EXPECT_TRUE(res); + else + EXPECT_FALSE(res); + } +} + +TEST_F(AOTTest, aot_intrinsic_fill_capability_flags) +{ + // AOTCompContext *comp_ctx = NULL; + AOTCompContext scomp_ctx = { 0 }; + + // comp_ctx = &scomp_ctx; + aot_intrinsic_fill_capability_flags(&scomp_ctx); + + AOTCompContext scomp_ctx_1{ + .target_cpu = (char *)"cortex-m7", + }; + strncpy(scomp_ctx_1.target_arch, "thumb", strlen("thumb")); + aot_intrinsic_fill_capability_flags(&scomp_ctx_1); + + AOTCompContext scomp_ctx_2{ + .target_cpu = (char *)"cortex-m4", + }; + strncpy(scomp_ctx_2.target_arch, "thumb", strlen("thumb")); + aot_intrinsic_fill_capability_flags(&scomp_ctx_2); + + AOTCompContext scomp_ctx_3{ + .target_cpu = (char *)"cortex-m4", + }; + strncpy(scomp_ctx_3.target_arch, "riscv", strlen("riscv")); + aot_intrinsic_fill_capability_flags(&scomp_ctx_3); + + AOTCompContext scomp_ctx_4{ + .target_cpu = (char *)"cortex-m4", + }; + strncpy(scomp_ctx_4.target_arch, "intrinsic", strlen("intrinsic")); + aot_intrinsic_fill_capability_flags(&scomp_ctx_4); +} diff --git a/tests/unit/common/mock_allocator.h b/tests/unit/common/mock_allocator.h new file mode 100644 index 000000000..a57e2dea3 --- /dev/null +++ b/tests/unit/common/mock_allocator.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#pragma once + +#include "wasm_export.h" +#include + +template +class MockAllocator +{ + private: + RuntimeInitArgs init_args; + + public: + MockAllocator() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = (void *)my_malloc; + init_args.mem_alloc_option.allocator.realloc_func = (void *)realloc; + init_args.mem_alloc_option.allocator.free_func = (void *)free; + + /* Set count to INT32_MIN so the initialization will not fail */ + alloc_count = INT32_MIN; + + wasm_runtime_full_init(&init_args); + reset_count(); + } + + ~MockAllocator() { wasm_runtime_destroy(); } + + void reset_count() { alloc_count = 0; } + + protected: + static int32_t alloc_count; + static void *my_malloc(int32_t size) + { + if (alloc_count >= MaxAllocCount) { + return nullptr; + } + + alloc_count++; + + return malloc(size); + } +}; + +template +int32_t MockAllocator::alloc_count = 0; + +class DumpAllocUsage : public MockAllocator +{ + public: + DumpAllocUsage() + : MockAllocator() + {} + + ~DumpAllocUsage() + { + std::cout << "Alloc usage count: " << alloc_count << std::endl; + } +}; + +template +void +LIMIT_MALLOC_COUNT(std::function func) +{ + { + MockAllocator allocator; + func(); + } + + if (AllocRequired > 1) + LIMIT_MALLOC_COUNT(func); +} + +template<> +void +LIMIT_MALLOC_COUNT<0>(std::function func) +{ + { + MockAllocator<0> allocator; + func(); + } +} diff --git a/tests/unit/common/test_helper.h b/tests/unit/common/test_helper.h new file mode 100644 index 000000000..4db465fc8 --- /dev/null +++ b/tests/unit/common/test_helper.h @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#pragma once + +#include "wasm_export.h" +#include "gtest/gtest.h" + +#include +#include +#include + +template +class WAMRRuntimeRAII +{ + private: + char global_heap_buf[Size]; + RuntimeInitArgs init_args; + + public: + WAMRRuntimeRAII() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + wasm_runtime_full_init(&init_args); + } + + ~WAMRRuntimeRAII() { wasm_runtime_destroy(); } +}; + +class WAMRModule +{ + private: + wasm_module_t module_; + + public: + WAMRModule(uint8_t *buffer, uint32_t size) + { + module_ = wasm_runtime_load(buffer, size, NULL, 0); + } + + ~WAMRModule() { wasm_runtime_unload(module_); } + + wasm_module_t get() const { return module_; } +}; + +class WAMRInstance +{ + private: + wasm_module_inst_t module_inst_; + + public: + WAMRInstance(WAMRModule &module, uint32_t stack_size = 8192, + uint32_t heap_size = 8192) + { + module_inst_ = wasm_runtime_instantiate(module.get(), stack_size, + heap_size, NULL, 0); + } + + ~WAMRInstance() { wasm_runtime_deinstantiate(module_inst_); } + + wasm_module_inst_t get() const { return module_inst_; } +}; + +class WAMRExecEnv +{ + private: + wasm_exec_env_t exec_env_; + + public: + WAMRExecEnv(WAMRInstance &instance, uint32_t stack_size = 8192) + { + exec_env_ = wasm_runtime_create_exec_env(instance.get(), stack_size); + } + + ~WAMRExecEnv() { wasm_runtime_destroy_exec_env(exec_env_); } + + wasm_exec_env_t get() const { return exec_env_; } + wasm_module_inst_t get_inst() const + { + return wasm_runtime_get_module_inst(exec_env_); + } +}; + +static uint8_t dummy_wasm_buffer[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x05, 0x03, 0x01, 0x00, + 0x02, 0x06, 0x08, 0x01, 0x7F, 0x01, 0x41, 0x80, 0x88, 0x04, 0x0B, 0x07, + 0x0A, 0x01, 0x06, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x00, + 0x19, 0x04, 0x6E, 0x61, 0x6D, 0x65, 0x07, 0x12, 0x01, 0x00, 0x0F, 0x5F, + 0x5F, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74, + 0x65, 0x72, 0x00, 0x76, 0x09, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, + 0x72, 0x73, 0x01, 0x0C, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x65, + 0x64, 0x2D, 0x62, 0x79, 0x01, 0x05, 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x56, + 0x31, 0x33, 0x2E, 0x30, 0x2E, 0x30, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, + 0x73, 0x3A, 0x2F, 0x2F, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, + 0x6F, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, + 0x2D, 0x70, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x20, 0x66, 0x64, 0x31, + 0x64, 0x38, 0x63, 0x32, 0x66, 0x30, 0x34, 0x64, 0x64, 0x65, 0x32, 0x33, + 0x62, 0x65, 0x65, 0x30, 0x66, 0x62, 0x33, 0x61, 0x37, 0x64, 0x30, 0x36, + 0x39, 0x61, 0x39, 0x62, 0x31, 0x30, 0x34, 0x36, 0x64, 0x61, 0x39, 0x37, + 0x39, 0x29 +}; + +class DummyExecEnv +{ + private: + std::shared_ptr dummy_exec_env_; + std::shared_ptr inst_; + std::shared_ptr mod_; + std::vector my_wasm_buffer; + + private: + void construct(uint8_t *buf, uint32_t len) + { + std::vector buffer(buf, buf + len); + my_wasm_buffer = buffer; + + mod_ = std::make_shared(my_wasm_buffer.data(), + my_wasm_buffer.size()); + EXPECT_NE(mod_.get(), nullptr); + inst_ = std::make_shared(*mod_); + EXPECT_NE(inst_.get(), nullptr); + dummy_exec_env_ = std::make_shared(*inst_); + EXPECT_NE(dummy_exec_env_.get(), nullptr); + } + + public: + DummyExecEnv() { construct(dummy_wasm_buffer, sizeof(dummy_wasm_buffer)); } + + DummyExecEnv(uint8_t *buf, uint32_t len) { construct(buf, len); } + + DummyExecEnv(std::string filename) + { + std::ifstream wasm_file(filename, std::ios::binary); + std::vector buffer(std::istreambuf_iterator(wasm_file), + {}); + + construct(buffer.data(), buffer.size()); + } + + ~DummyExecEnv() {} + + wasm_exec_env_t get() const { return dummy_exec_env_->get(); } + + void *app_to_native(uint32_t app_addr) const + { + return wasm_runtime_addr_app_to_native(inst_->get(), app_addr); + } + + uint32_t native_to_app(void *ptr) const + { + return wasm_runtime_addr_native_to_app(inst_->get(), ptr); + } + + const char *get_exception() const + { + return wasm_runtime_get_exception(inst_->get()); + } + + void set_exception(std::string str) const + { + wasm_runtime_set_exception(inst_->get(), str.c_str()); + } + + void clear_exception() const { wasm_runtime_clear_exception(inst_->get()); } + + bool execute(const char *func_name, uint32_t argc, uint32_t argv[]) + { + wasm_function_inst_t func; + + if (!(func = wasm_runtime_lookup_function(inst_->get(), func_name))) { + return false; + } + + return wasm_runtime_call_wasm(dummy_exec_env_->get(), func, argc, argv); + } +}; + +class WAMRVaList +{ + private: + void *buffer_; + uint32_t current_loc_; + uint32_t capacity_; + wasm_exec_env_t exec_env_; + + void _append(void *ptr, uint32_t size) + { + if (current_loc_ + size >= capacity_) { + capacity_ *= 2; + buffer_ = realloc(buffer_, capacity_); + ASSERT_NE(buffer_, nullptr); + } + + memcpy((void *)((uintptr_t)buffer_ + current_loc_), ptr, size); + current_loc_ += size; + } + + public: + explicit WAMRVaList(wasm_exec_env_t exec_env) + : exec_env_(exec_env) + { + capacity_ = 64; + buffer_ = malloc(capacity_); + EXPECT_NE(buffer_, nullptr); + current_loc_ = 0; + } + + ~WAMRVaList() + { + current_loc_ = 0; + free(buffer_); + } + + template + void add(T arg) + { + if (std::is_floating_point::value) { + /* float data should be 8 bytes aligned */ + current_loc_ = ((current_loc_ + 7) & ~7); + _append(&arg, sizeof(T)); + } + else if (std::is_integral::value) { + if (sizeof(T) > 4) { + current_loc_ = ((current_loc_ + 7) & ~7); + } + _append(&arg, sizeof(T)); + } + } + + void add(std::string arg) + { + void *native_addr; + auto inst = wasm_runtime_get_module_inst(exec_env_); + uint32_t addr = + wasm_runtime_module_malloc(inst, arg.size() + 1, &native_addr); + ASSERT_NE(addr, 0); + memcpy(native_addr, arg.data(), arg.size()); + *(char *)((uintptr_t)native_addr + arg.size()) = 0; + _append(&addr, sizeof(uint32_t)); + } + + void add(const char *arg) { add(std::string(arg)); } + + char *get() const + { + auto inst = wasm_runtime_get_module_inst(exec_env_); + uint32_t addr = wasm_runtime_module_dup_data( + inst, (const char *)buffer_, current_loc_); + EXPECT_NE(addr, 0); + return (char *)wasm_runtime_addr_app_to_native(inst, addr); + } +}; + +/* Get memory space in app */ +class AppMemory +{ + private: + wasm_exec_env_t exec_env_; + void *native_addr_; + uint32_t app_addr_; + + public: + AppMemory(wasm_exec_env_t exec_env, uint32_t size) + : exec_env_(exec_env) + { + app_addr_ = wasm_runtime_module_malloc(get_module_inst(exec_env_), size, + &native_addr_); + } + + ~AppMemory() + { + wasm_runtime_module_free(get_module_inst(exec_env_), app_addr_); + } + + void *get_native_addr() const + { + return wasm_runtime_addr_app_to_native(get_module_inst(exec_env_), + app_addr_); + } + uint32_t get_app_addr() const { return app_addr_; } +}; + +/* Put the data to app */ +class AppData +{ + private: + wasm_exec_env_t exec_env_; + void *native_addr_; + uint32_t app_addr_; + + public: + AppData(wasm_exec_env_t exec_env, void *data, uint32_t size) + : exec_env_(exec_env) + { + app_addr_ = wasm_runtime_module_dup_data(get_module_inst(exec_env_), + (const char *)data, size); + } + + AppData(wasm_exec_env_t exec_env, std::string str) + : exec_env_(exec_env) + { + app_addr_ = wasm_runtime_module_dup_data(get_module_inst(exec_env_), + (const char *)str.c_str(), + str.size() + 1); + } + + ~AppData() + { + wasm_runtime_module_free(get_module_inst(exec_env_), app_addr_); + } + + void *get_native_addr() const + { + return wasm_runtime_addr_app_to_native(get_module_inst(exec_env_), + app_addr_); + } + uint32_t get_app_addr() const { return app_addr_; } +}; \ No newline at end of file diff --git a/tests/unit/compilation/CMakeLists.txt b/tests/unit/compilation/CMakeLists.txt new file mode 100644 index 000000000..0941a39cc --- /dev/null +++ b/tests/unit/compilation/CMakeLists.txt @@ -0,0 +1,72 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-compilation) + +add_definitions (-DRUN_ON_LINUX) + +add_definitions (-Dattr_container_malloc=malloc) +add_definitions (-Dattr_container_free=free) +add_definitions (-DWASM_ENABLE_WAMR_COMPILER=1) +add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1) +add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) +set (WAMR_BUILD_THREAD_MGR 1) +set (WAMR_BUILD_AOT 1) + +include (../unit_common.cmake) + +set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") +if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif () +set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include (${IWASM_DIR}/compilation/iwasm_compl.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${LIB_HOST_AGENT_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} + ) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable (compilation_test ${unit_test_sources}) + +target_link_libraries (compilation_test ${LLVM_AVAILABLE_LIBS} gtest_main ) + +add_custom_command(TARGET compilation_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/main.wasm + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copy main.wasm to the directory: build/compilation." +) + +gtest_discover_tests(compilation_test) diff --git a/tests/unit/compilation/aot_compiler_test.cc b/tests/unit/compilation/aot_compiler_test.cc new file mode 100644 index 000000000..8592a4b61 --- /dev/null +++ b/tests/unit/compilation/aot_compiler_test.cc @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "wasm_export.h" +#include "aot_export.h" +#include "bh_read_file.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +extern "C" { +char * +aot_generate_tempfile_name(const char *prefix, const char *extension, + char *buffer, uint32 len); +} + +class aot_compiler_test_suit : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +void +test_aot_emit_object_file_with_option(AOTCompOption *option_ptr) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + aot_comp_data_t comp_data = nullptr; + aot_comp_context_t comp_ctx = nullptr; + char out_file_name[] = "test.aot"; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data(wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + + comp_ctx = aot_create_comp_context(comp_data, option_ptr); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_STREQ(aot_get_last_error(), ""); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + EXPECT_TRUE(aot_emit_object_file(comp_ctx, out_file_name)); +} + +TEST_F(aot_compiler_test_suit, aot_emit_object_file) +{ + AOTCompOption option = { 0 }; + uint32_t i = 0; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + // Test opt_level in range from 0 to 3. + for (i = 0; i <= 3; i++) { + option.opt_level = i; + test_aot_emit_object_file_with_option(&option); + } + + // Test size_level in range from 0 to 3. + option.opt_level = 3; + for (i = 0; i <= 3; i++) { + option.size_level = i; + test_aot_emit_object_file_with_option(&option); + } + + // Test output_format in range from AOT_FORMAT_FILE to AOT_LLVMIR_OPT_FILE. + option.size_level = 3; + for (i = AOT_FORMAT_FILE; i <= AOT_LLVMIR_OPT_FILE; i++) { + option.output_format = i; + test_aot_emit_object_file_with_option(&option); + } + + // Test bounds_checks in range 0 to 2. + option.output_format = AOT_FORMAT_FILE; + for (i = 0; i <= 2; i++) { + option.bounds_checks = i; + test_aot_emit_object_file_with_option(&option); + } + + // Test all enable option is false. + option.bounds_checks = 2; + option.enable_simd = false; + option.enable_aux_stack_check = false; + option.enable_bulk_memory = false; + option.enable_ref_types = false; + test_aot_emit_object_file_with_option(&option); +} + +TEST_F(aot_compiler_test_suit, aot_emit_llvm_file) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + aot_comp_data_t comp_data = nullptr; + aot_comp_context_t comp_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "out_file_name_test"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data(wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_STREQ(aot_get_last_error(), ""); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + EXPECT_EQ(true, aot_emit_llvm_file(comp_ctx, out_file_name)); +} + +TEST_F(aot_compiler_test_suit, aot_generate_tempfile_name) +{ + char obj_file_name[64]; + + // Test common case. + aot_generate_tempfile_name("wamrc-obj", "o", obj_file_name, + sizeof(obj_file_name)); + EXPECT_NE(nullptr, strstr(obj_file_name, ".o")); + + // Test abnormal cases. + EXPECT_EQ(nullptr, + aot_generate_tempfile_name("wamrc-obj", "o", obj_file_name, 0)); + char obj_file_name_1[20]; + EXPECT_EQ(nullptr, aot_generate_tempfile_name( + "wamrc-obj", "12345678901234567890", obj_file_name_1, + sizeof(obj_file_name_1))); +} diff --git a/tests/unit/compilation/aot_emit_aot_file_test.cc b/tests/unit/compilation/aot_emit_aot_file_test.cc new file mode 100644 index 000000000..64c5533bb --- /dev/null +++ b/tests/unit/compilation/aot_emit_aot_file_test.cc @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "wasm_export.h" +#include "aot_export.h" +#include "bh_read_file.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +extern "C" { +uint8 * +aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data, + uint32 *p_aot_file_size); +} + +class aot_emit_aot_file_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_aot_file_test_suite, aot_emit_aot_file) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + aot_comp_data_t comp_data = nullptr; + aot_comp_context_t comp_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "test.aot"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = false; + option.enable_aux_stack_check = false; + option.enable_bulk_memory = false; + option.enable_ref_types = false; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data(wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + EXPECT_EQ(false, aot_emit_aot_file(comp_ctx, comp_data, nullptr)); +} diff --git a/tests/unit/compilation/aot_emit_compare_test.cc b/tests/unit/compilation/aot_emit_compare_test.cc new file mode 100644 index 000000000..dfd125f9a --- /dev/null +++ b/tests/unit/compilation/aot_emit_compare_test.cc @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "aot_emit_compare.h" + +class compilation_aot_emit_compare_test : public testing::Test +{ + protected: + virtual void SetUp() {} + virtual void TearDown() {} + + public: +}; + +TEST_F(compilation_aot_emit_compare_test, aot_compile_op_i32_compare) +{ + AOTCompContext comp_ctx = { 0 }; + AOTFuncContext func_ctx = { 0 }; + IntCond cond = INT_EQZ; + IntCond cond1 = INT_EQZ; + + /* false cond = 0 */ + EXPECT_FALSE(aot_compile_op_i32_compare(&comp_ctx, &func_ctx, cond)); + + /* false cond = -1 */ + EXPECT_FALSE( + aot_compile_op_i32_compare(&comp_ctx, &func_ctx, (IntCond)(-1))); + + /* false cond = [1:10] || [11:100] */ + for (int i = 0; i < 0xFFFF; i++) { + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + cond = (IntCond)(1 + (rand() % (INT_GE_U - 1 + 1))); + cond1 = (IntCond)((INT_GE_U + 1) + (rand() % (100 - 1 + 1))); + EXPECT_FALSE(aot_compile_op_i32_compare(&comp_ctx, &func_ctx, cond)); + EXPECT_FALSE(aot_compile_op_i32_compare(&comp_ctx, &func_ctx, cond1)); + } +} + +TEST_F(compilation_aot_emit_compare_test, aot_compile_op_i64_compare) +{ + AOTCompContext comp_ctx = { 0 }; + AOTFuncContext func_ctx = { 0 }; + IntCond cond = INT_EQZ; + IntCond cond1 = INT_EQZ; + + /* false cond = 0 */ + // EXPECT_FALSE(aot_compile_op_i64_compare(&comp_ctx, &func_ctx, cond)); + + /* false cond = -1 */ + EXPECT_FALSE( + aot_compile_op_i64_compare(&comp_ctx, &func_ctx, (IntCond)(-1))); + + /* false cond = [1:10] || [11:100] */ + for (int i = 0; i < 0xFFFF; i++) { + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + cond = (IntCond)(1 + (rand() % (INT_GE_U - 1 + 1))); + cond1 = (IntCond)((INT_GE_U + 1) + (rand() % (100 - 1 + 1))); + EXPECT_FALSE(aot_compile_op_i64_compare(&comp_ctx, &func_ctx, cond)); + EXPECT_FALSE(aot_compile_op_i64_compare(&comp_ctx, &func_ctx, cond1)); + } +} + +TEST_F(compilation_aot_emit_compare_test, aot_compile_op_f32_compare) +{ + AOTCompContext comp_ctx = { 0 }; + AOTFuncContext func_ctx = { 0 }; + FloatCond cond = FLOAT_EQ; + FloatCond cond1 = FLOAT_EQ; + + /* false cond = 0 */ + EXPECT_FALSE(aot_compile_op_f32_compare(&comp_ctx, &func_ctx, cond)); + + /* false cond = -1 */ + EXPECT_FALSE( + aot_compile_op_f32_compare(&comp_ctx, &func_ctx, (FloatCond)(-1))); + + /* false cond = [1:10] || [7:100] */ + for (int i = 0; i < 0xFFFF; i++) { + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + cond = (FloatCond)(1 + (rand() % (FLOAT_UNO - 1 + 1))); + cond1 = (FloatCond)((FLOAT_UNO + 1) + (rand() % (100 - 1 + 1))); + EXPECT_FALSE(aot_compile_op_f32_compare(&comp_ctx, &func_ctx, cond)); + EXPECT_FALSE(aot_compile_op_f32_compare(&comp_ctx, &func_ctx, cond1)); + } +} + +TEST_F(compilation_aot_emit_compare_test, aot_compile_op_f64_compare) +{ + AOTCompContext comp_ctx = { 0 }; + AOTFuncContext func_ctx = { 0 }; + FloatCond cond = FLOAT_EQ; + FloatCond cond1 = FLOAT_EQ; + + /* false cond = 0 */ + EXPECT_FALSE(aot_compile_op_f64_compare(&comp_ctx, &func_ctx, cond)); + + /* false cond = -1 */ + EXPECT_FALSE( + aot_compile_op_f64_compare(&comp_ctx, &func_ctx, (FloatCond)(-1))); + + /* false cond = [1:10] || [7:100] */ + for (int i = 0; i < 0xFFFF; i++) { + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + cond = (FloatCond)(1 + (rand() % (FLOAT_UNO - 1 + 1))); + cond1 = (FloatCond)((FLOAT_UNO + 1) + (rand() % (100 - 1 + 1))); + EXPECT_FALSE(aot_compile_op_f64_compare(&comp_ctx, &func_ctx, cond)); + EXPECT_FALSE(aot_compile_op_f64_compare(&comp_ctx, &func_ctx, cond1)); + } +} diff --git a/tests/unit/compilation/aot_emit_control_test.cc b/tests/unit/compilation/aot_emit_control_test.cc new file mode 100644 index 000000000..a269f51eb --- /dev/null +++ b/tests/unit/compilation/aot_emit_control_test.cc @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot.h" +#include "aot_llvm.h" +#include "aot_emit_control.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_emit_control_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_control_test_suite, check_suspend_flags) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "out_file_name_test"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + func_ctx = comp_ctx->func_ctxes[1]; + EXPECT_EQ(true, check_suspend_flags(comp_ctx, func_ctx, false)); +} + +TEST_F(aot_emit_control_test_suite, aot_compile_op_block) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "out_file_name_test"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + func_ctx = comp_ctx->func_ctxes[1]; + func_ctx->block_stack.block_list_end = nullptr; + EXPECT_EQ(false, aot_compile_op_block(comp_ctx, func_ctx, nullptr, nullptr, + 0, 0, nullptr, 0, nullptr)); +} + +TEST_F(aot_emit_control_test_suite, aot_compile_op_else) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "out_file_name_test"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + func_ctx = comp_ctx->func_ctxes[1]; + func_ctx->block_stack.block_list_end = nullptr; + EXPECT_EQ(false, aot_compile_op_else(comp_ctx, func_ctx, nullptr)); + + AOTBlock block_list_end_test; + block_list_end_test.label_type = LABEL_TYPE_FUNCTION; + func_ctx->block_stack.block_list_end = &block_list_end_test; + EXPECT_EQ(false, aot_compile_op_else(comp_ctx, func_ctx, nullptr)); + + block_list_end_test.label_type = LABEL_TYPE_IF; + block_list_end_test.llvm_else_block = nullptr; + EXPECT_EQ(false, aot_compile_op_else(comp_ctx, func_ctx, nullptr)); +} diff --git a/tests/unit/compilation/aot_emit_function_test.cc b/tests/unit/compilation/aot_emit_function_test.cc new file mode 100644 index 000000000..8c4c93fce --- /dev/null +++ b/tests/unit/compilation/aot_emit_function_test.cc @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot_emit_control.h" +#include "aot_emit_function.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_emit_function_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_function_test_suite, aot_compile_op_call) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + char out_file_name[] = "out_file_name_test"; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + func_ctx = comp_ctx->func_ctxes[1]; + EXPECT_EQ(false, aot_compile_op_call(comp_ctx, func_ctx, 9999, true)); +} diff --git a/tests/unit/compilation/aot_emit_memory_test.cc b/tests/unit/compilation/aot_emit_memory_test.cc new file mode 100644 index 000000000..26a6a79ba --- /dev/null +++ b/tests/unit/compilation/aot_emit_memory_test.cc @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "bh_platform.h" +#include "bh_read_file.h" +#include "aot_emit_memory.h" +#include "test_helper.h" + +#define DEFAULT_CYCLE_TIMES 0xFFFF +#define DEFAULT_MAX_RAND_NUM 0xFFFFFFFF + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class compilation_aot_emit_memory_test : public testing::Test +{ + protected: + void SetUp() override + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + /* default value, enable or disable depends on the platform */ + option.stack_bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = reinterpret_cast(wasm_runtime_load( + wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf))); + EXPECT_NE(wasm_module, nullptr); + comp_data = aot_create_comp_data(wasm_module, NULL, false); + EXPECT_NE(comp_data, nullptr); + + // properly init compilation and function context, to do that, + // use as a dummy module(instead of compile the function in it, simply + // test the APIs) + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + func_ctx = comp_ctx->func_ctxes[0]; + EXPECT_NE(func_ctx, nullptr); + } + + void TearDown() override + { + aot_destroy_comp_context(comp_ctx); + aot_destroy_comp_data(comp_data); + wasm_runtime_unload(reinterpret_cast(wasm_module)); + } + + public: + WASMModule *wasm_module = nullptr; + AOTCompData *comp_data = nullptr; + AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(compilation_aot_emit_memory_test, aot_check_memory_overflow) +{ + uint32 offset = 64; + uint32 bytes = 4; + + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes, false); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i32_load) +{ + uint32 align = 0; + uint32 offset = 1024; + uint32 bytes = 0; + bool sign = false; + bool atomic = false; + + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + bytes = (1 + (rand() % (4 - 1 + 1))); + printf("---%d", aot_compile_op_i32_load(comp_ctx, func_ctx, align, + offset, bytes, sign, atomic)); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i64_load) +{ + uint32 align = 0; + uint32 offset = 1024; + uint32 bytes = 0; + bool sign = false; + bool atomic = false; + + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + bytes = (1 + (rand() % (4 - 1 + 1))); + sign = !sign; + atomic = !atomic; + aot_compile_op_i64_load(comp_ctx, func_ctx, align, offset, bytes, sign, + atomic); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f32_load) +{ + uint32 align = 10; + uint32 offset = 10; + + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + aot_compile_op_f32_load(comp_ctx, func_ctx, align, offset); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f64_load) +{ + uint32 align = 10; + uint32 offset = 10; + + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + aot_compile_op_f64_load(comp_ctx, func_ctx, align, offset); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i32_store) +{ + uint32 align = 0; + uint32 offset = 0; + uint32 bytes = 0; + bool atomic = false; + + EXPECT_FALSE(aot_compile_op_i32_store(comp_ctx, func_ctx, align, offset, + bytes, atomic)); + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + bytes = (1 + (rand() % (4 - 1 + 1))); + offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + align = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + atomic = !atomic; + + EXPECT_FALSE(aot_compile_op_i32_store(comp_ctx, func_ctx, align, offset, + bytes, atomic)); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i64_store) +{ + uint32 align = 0; + uint32 offset = 0; + uint32 bytes = 0; + bool atomic = false; + + EXPECT_FALSE(aot_compile_op_i64_store(comp_ctx, func_ctx, align, offset, + bytes, atomic)); + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + bytes = (1 + (rand() % (8 - 1 + 1))); + offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + align = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + atomic = !atomic; + + EXPECT_FALSE(aot_compile_op_i64_store(comp_ctx, func_ctx, align, offset, + bytes, atomic)); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f32_store) +{ + uint32 align = 0; + uint32 offset = 0; + + EXPECT_FALSE(aot_compile_op_f32_store(comp_ctx, func_ctx, align, offset)); + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + align = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + + EXPECT_FALSE( + aot_compile_op_f32_store(comp_ctx, func_ctx, align, offset)); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f64_store) +{ + uint32 align = 0; + uint32 offset = 0; + + EXPECT_FALSE(aot_compile_op_f64_store(comp_ctx, func_ctx, align, offset)); + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + align = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + + EXPECT_FALSE( + aot_compile_op_f64_store(comp_ctx, func_ctx, align, offset)); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_size) +{ + aot_compile_op_memory_size(comp_ctx, func_ctx); +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_grow) +{ + aot_compile_op_memory_grow(comp_ctx, func_ctx); +} + +#if WASM_ENABLE_BULK_MEMORY != 0 +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_init) +{ + uint32 seg_index = 0; + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + seg_index = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + aot_compile_op_memory_init(comp_ctx, func_ctx, seg_index); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_data_drop) +{ + uint32 seg_index = 0; + + /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */ + for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + seg_index = (1 + (rand() % (0xFFFFFFFF - 1 + 1))); + aot_compile_op_data_drop(comp_ctx, func_ctx, seg_index); + } +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_copy) +{ + aot_compile_op_memory_copy(comp_ctx, func_ctx); +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_fill) +{ + aot_compile_op_memory_fill(comp_ctx, func_ctx); +} +#endif + +#if WASM_ENABLE_SHARED_MEMORY != 0 +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_atomic_rmw) +{ + uint8 atomic_op = LLVMAtomicRMWBinOpAdd; + uint8 op_type = VALUE_TYPE_I32; + uint32 align = 4; + uint32 offset = 64; + uint32 bytes = 4; + + aot_compile_op_atomic_rmw(comp_ctx, func_ctx, atomic_op, op_type, align, + offset, bytes); +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_atomic_cmpxchg) +{ + + uint8 op_type = VALUE_TYPE_I32; + uint32 align = 4; + uint32 offset = 64; + uint32 bytes = 4; + + aot_compile_op_atomic_cmpxchg(comp_ctx, func_ctx, op_type, align, offset, + bytes); +} + +TEST_F(compilation_aot_emit_memory_test, aot_compile_op_atomic_wait) +{ + + uint8 op_type = VALUE_TYPE_I32; + uint32 align = 4; + uint32 offset = 64; + uint32 bytes = 4; + + aot_compile_op_atomic_wait(comp_ctx, func_ctx, op_type, align, offset, + bytes); +} + +TEST_F(compilation_aot_emit_memory_test, aot_compiler_op_atomic_notify) +{ + + uint32 align = 4; + uint32 offset = 64; + uint32 bytes = 4; + + aot_compiler_op_atomic_notify(comp_ctx, func_ctx, align, offset, bytes); +} +#endif diff --git a/tests/unit/compilation/aot_emit_numberic_test.cc b/tests/unit/compilation/aot_emit_numberic_test.cc new file mode 100644 index 000000000..f7e6e8ee7 --- /dev/null +++ b/tests/unit/compilation/aot_emit_numberic_test.cc @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot_llvm.h" +#include "aot_emit_numberic.h" +#include "aot_compiler.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_emit_numberic_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_numberic_test_suite, aot_compile_op_functions) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + + EXPECT_EQ(false, + aot_compile_op_f32_arithmetic(comp_ctx, func_ctx, FLOAT_SUB)); + EXPECT_EQ(false, aot_compile_op_f32_copysign(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_f32_math(comp_ctx, func_ctx, FLOAT_NEG)); + EXPECT_EQ(false, + aot_compile_op_f64_arithmetic(comp_ctx, func_ctx, FLOAT_SUB)); + EXPECT_EQ(false, aot_compile_op_f64_copysign(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_f64_math(comp_ctx, func_ctx, FLOAT_NEG)); + EXPECT_EQ(false, aot_compile_op_i32_clz(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i32_ctz(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i32_popcnt(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i32_shift(comp_ctx, func_ctx, INT_SHR_S)); + EXPECT_EQ(false, aot_compile_op_i64_arithmetic(comp_ctx, func_ctx, INT_SUB, + nullptr)); + EXPECT_EQ(false, aot_compile_op_i64_bitwise(comp_ctx, func_ctx, INT_OR)); + EXPECT_EQ(false, aot_compile_op_i64_clz(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i64_ctz(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i64_popcnt(comp_ctx, func_ctx)); + EXPECT_EQ(false, aot_compile_op_i64_shift(comp_ctx, func_ctx, INT_SHR_S)); +} diff --git a/tests/unit/compilation/aot_emit_parametric_test.cc b/tests/unit/compilation/aot_emit_parametric_test.cc new file mode 100644 index 000000000..f9dabe1c8 --- /dev/null +++ b/tests/unit/compilation/aot_emit_parametric_test.cc @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot_llvm.h" +#include "aot_emit_parametric.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_emit_parametric_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_parametric_test_suite, aot_compile_op_select) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + + EXPECT_FALSE(aot_compile_op_select(comp_ctx, func_ctx, true)); + EXPECT_FALSE(aot_compile_op_select(comp_ctx, func_ctx, false)); +} + +TEST_F(aot_emit_parametric_test_suite, aot_compile_op_drop) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + func_ctx->block_stack.block_list_end = nullptr; + + EXPECT_FALSE(aot_compile_op_drop(comp_ctx, func_ctx, true)); + EXPECT_FALSE(aot_compile_op_drop(comp_ctx, func_ctx, false)); +} diff --git a/tests/unit/compilation/aot_emit_table_test.cc b/tests/unit/compilation/aot_emit_table_test.cc new file mode 100644 index 000000000..fc4bfe2f1 --- /dev/null +++ b/tests/unit/compilation/aot_emit_table_test.cc @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot_llvm.h" +#include "aot_emit_table.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_emit_table_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_emit_table_test_suite, get_tbl_inst_offset) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTFuncContext *func_ctx = nullptr; + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + + EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 6)); + EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 1)); + EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 0)); + ((AOTCompData *)comp_ctx->comp_data)->import_table_count = 1; + AOTImportTable import_tables_test; + ((AOTCompData *)comp_ctx->comp_data)->import_tables = &import_tables_test; + EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 6)); +} diff --git a/tests/unit/compilation/aot_emit_variable_test.cc b/tests/unit/compilation/aot_emit_variable_test.cc new file mode 100644 index 000000000..11cc238f0 --- /dev/null +++ b/tests/unit/compilation/aot_emit_variable_test.cc @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "aot_emit_variable.h" + +#define DEFAULT_CYCLE_TIMES 0xFFFF +#define DEFAULT_MAX_RAND_NUM 0xFFFFFFFF + +class compilation_aot_emit_variable_test : public testing::Test +{ + protected: + virtual void SetUp() {} + virtual void TearDown() {} + + public: + AOTCompContext comp_ctx = { 0 }; + AOTFuncContext func_ctx = { 0 }; +}; + +TEST_F(compilation_aot_emit_variable_test, aot_compile_op_get_local) +{ + AOTCompContext *pcomp_ctx = &comp_ctx; + AOTFuncContext *pfunc_ctx = &func_ctx; + uint32 local_idx = 0; + + // aot_compile_op_get_local(NULL, pfunc_ctx, local_idx); + + // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + // local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + // aot_compile_op_get_local(pcomp_ctx, pfunc_ctx, local_idx); + // } +} + +TEST_F(compilation_aot_emit_variable_test, aot_compile_op_set_local) +{ + + AOTCompContext *pcomp_ctx = &comp_ctx; + AOTFuncContext *pfunc_ctx = &func_ctx; + uint32 local_idx = 0; + + // aot_compile_op_set_local(pcomp_ctx, pfunc_ctx, local_idx); + + // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + // local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + // aot_compile_op_set_local(pcomp_ctx, pfunc_ctx, local_idx); + // } +} + +TEST_F(compilation_aot_emit_variable_test, aot_compile_op_tee_local) +{ + + AOTCompContext *pcomp_ctx = &comp_ctx; + AOTFuncContext *pfunc_ctx = &func_ctx; + uint32 local_idx = 0; + + // aot_compile_op_tee_local(pcomp_ctx, pfunc_ctx, local_idx); + + // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + // local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + // aot_compile_op_tee_local(pcomp_ctx, pfunc_ctx, local_idx); + // } +} + +TEST_F(compilation_aot_emit_variable_test, aot_compile_op_get_global) +{ + AOTCompContext *pcomp_ctx = &comp_ctx; + AOTFuncContext *pfunc_ctx = &func_ctx; + uint32 global_idx = 0; + + // aot_compile_op_get_global(pcomp_ctx, pfunc_ctx, global_idx); + + // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + // local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + // aot_compile_op_get_global(pcomp_ctx, pfunc_ctx, global_idx); + // } +} + +TEST_F(compilation_aot_emit_variable_test, aot_compile_op_set_global) +{ + AOTCompContext *pcomp_ctx = &comp_ctx; + AOTFuncContext *pfunc_ctx = &func_ctx; + uint32 global_idx = 0; + bool is_aux_stack = false; + + // aot_compile_op_set_global(pcomp_ctx, pfunc_ctx, global_idx, + // is_aux_stack); + + // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) { + // is_aux_stack = is_aux_stack ? false : ture; + // local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1))); + // aot_compile_op_set_global(pcomp_ctx, pfunc_ctx, + // global_idx,is_aux_stack); + // } +} \ No newline at end of file diff --git a/tests/unit/compilation/aot_llvm_test.cc b/tests/unit/compilation/aot_llvm_test.cc new file mode 100644 index 000000000..dcebe04b4 --- /dev/null +++ b/tests/unit/compilation/aot_llvm_test.cc @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "aot_llvm.h" +#include "aot_compiler.h" + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static char *WASM_FILE; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class aot_llvm_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE = strdup((CWD + MAIN_WASM).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + static void TearDownTestCase() { free(WASM_FILE); } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(aot_llvm_test_suite, aot_functions) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTCompOption option = { 0 }; + AOTFuncContext *func_ctx = nullptr; + WASMValue wasm_value; + LLVMTypeRef param_types[1]; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + + param_types[0] = F64_TYPE; + EXPECT_TRUE(aot_call_llvm_intrinsic(comp_ctx, func_ctx, "f32_demote_f64", + F32_TYPE, param_types, 0)); + + /* Test function aot_get_native_symbol_index. */ + AOTNativeSymbol elem_insert_1; + elem_insert_1.index = -1; + bh_list_insert(&comp_ctx->native_symbols, &elem_insert_1); + + AOTNativeSymbol elem_insert_2; + strcpy(elem_insert_2.symbol, "f64#_test"); + elem_insert_2.index = -1; + bh_list_insert(&comp_ctx->native_symbols, &elem_insert_2); + comp_ctx->pointer_size = sizeof(uint32); + strcpy(comp_ctx->target_arch, "i386"); + EXPECT_NE(-1, aot_get_native_symbol_index(comp_ctx, "f64#_test")); +} + +TEST_F(aot_llvm_test_suite, wasm_type_to_llvm_type) {} + +TEST_F(aot_llvm_test_suite, aot_build_zero_function_ret) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTCompOption option = { 0 }; + AOTFuncContext *func_ctx = nullptr; + AOTFuncType func_type; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = false; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + func_ctx = comp_ctx->func_ctxes[1]; + + func_type.result_count = 1; + func_type.param_count = 0; + func_type.types[func_type.param_count] = VALUE_TYPE_I32; + EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type)); + func_type.types[func_type.param_count] = VALUE_TYPE_I64; + EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type)); + func_type.types[func_type.param_count] = VALUE_TYPE_F32; + EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type)); + func_type.types[func_type.param_count] = VALUE_TYPE_F64; + EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type)); + func_type.types[func_type.param_count] = VALUE_TYPE_V128; + EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type)); + /* THe current optimization, if not actually use ref_types in wasm module, + * it will set to false, so test false condition */ + func_type.types[func_type.param_count] = VALUE_TYPE_FUNCREF; + EXPECT_DEATH(aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type), + ".*"); + func_type.types[func_type.param_count] = VALUE_TYPE_EXTERNREF; + EXPECT_DEATH(aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type), + ".*"); + func_type.types[func_type.param_count] = 0xFF; + EXPECT_DEATH(aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type), + ".*"); +} + +TEST_F(aot_llvm_test_suite, aot_destroy_comp_context) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTCompOption option = { 0 }; + AOTFuncContext *func_ctx = nullptr; + AOTFuncType func_type; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + AOTNativeSymbol elem_insert_1; + elem_insert_1.index = -1; + bh_list_insert(&comp_ctx->native_symbols, &elem_insert_1); + aot_destroy_comp_context(comp_ctx); + + aot_destroy_comp_context(nullptr); +} + +TEST_F(aot_llvm_test_suite, aot_create_comp_context) +{ + const char *wasm_file = WASM_FILE; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + char error_buf[128] = { 0 }; + wasm_module_t wasm_module = nullptr; + + struct AOTCompData *comp_data = nullptr; + struct AOTCompContext *comp_ctx = nullptr; + AOTCompOption option = { 0 }; + + option.opt_level = 3; + option.size_level = 3; + option.output_format = AOT_FORMAT_FILE; + /* default value, enable or disable depends on the platform */ + option.bounds_checks = 2; + option.enable_simd = true; + option.enable_aux_stack_check = true; + option.enable_bulk_memory = true; + option.enable_ref_types = true; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false); + EXPECT_NE(nullptr, comp_data); + + option.enable_thread_mgr = true; + option.enable_tail_call = true; + option.is_indirect_mode = true; + option.disable_llvm_intrinsics = true; + option.disable_llvm_lto = true; + option.is_jit_mode = true; + + option.target_arch = (char *)"arm"; + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + option.output_format = 100; + comp_ctx = aot_create_comp_context(comp_data, &option); + + // Test every target_arch. + option.is_jit_mode = false; + option.target_arch = (char *)"arm"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"armeb"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"thumb"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"thumbeb"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"aarch64"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"aarch64_be"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_arch = (char *)"help"; + comp_ctx = aot_create_comp_context(comp_data, &option); + + // Test every target_abi. + option.target_arch = (char *)"arm"; + option.target_abi = (char *)"test"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_abi = (char *)"help"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.target_abi = (char *)"msvc"; + option.target_arch = (char *)"i386"; + comp_ctx = aot_create_comp_context(comp_data, &option); + + option.cpu_features = (char *)"test"; + comp_ctx = aot_create_comp_context(comp_data, &option); + option.is_sgx_platform = true; + comp_ctx = aot_create_comp_context(comp_data, &option); + comp_data->func_count = 0; + comp_ctx = aot_create_comp_context(comp_data, &option); +} diff --git a/tests/unit/compilation/wasm-apps/main.wasm b/tests/unit/compilation/wasm-apps/main.wasm new file mode 100644 index 0000000000000000000000000000000000000000..28af80e4052ce6e62666bfaccdc27e7275eaf542 GIT binary patch literal 1217 zcmcIjOK;Oa5T4n!orl}>5g{l&uz`ZwLzA?rQc|QsS}q8|0U<6ea{bsOZelywPEbzn z1&RN_0sa-gf+Hs`%qFQQ9H190@9fO(%(vg{&VZc+2mrXIpRp{%>a; zG8`Mj*bmbV05^1GoN1blLqyayM8=FV&#?Vv)6Ag#DX%2yxwknZkUCiMyg)_e7HSj}8)kM6WlSITHrA0MOtC1Ft4^Cf9tf%z$ zrz)q@_f)CYT#IK~Es0%#!1k%MRN5}6V9=+D+|czR+bZX~Y@J}?D;DSEsl=#|r(tlN zL!6O6@UG=abZS@GxC1-vim{9nKMKW8qgt=l#bz%}hsi;$*7eig$f>$fP#X-!GqF94 zqjTw|qT}s&58d5Peb4jcZo`qX-fy^+S7LDL(9v=HtKjo_3}6^vll6ts)RklG<+H8b)+uGA)pZtFUm;ft$ literal 0 HcmV?d00001 diff --git a/tests/unit/custom-section/CMakeLists.txt b/tests/unit/custom-section/CMakeLists.txt new file mode 100644 index 000000000..1529d0ea6 --- /dev/null +++ b/tests/unit/custom-section/CMakeLists.txt @@ -0,0 +1,65 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-custom-section) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_LIBC_BUILTIN 0) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LAZY_JIT 0) +set (WAMR_BUILD_AOT 1) + +add_definitions(-DWASM_ENABLE_WAMR_COMPILER=1) +add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1) +add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1) + +# Feature to test +set (WAMR_BUILD_LOAD_CUSTOM_SECTION 1) + +include (../unit_common.cmake) + +set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") +if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif () +set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include (${IWASM_DIR}/compilation/iwasm_compl.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} + ) + +# Automatically build wasm-apps for this test +add_subdirectory(wasm-apps) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable (custom_section_test ${unit_test_sources}) + +target_link_libraries (custom_section_test ${LLVM_AVAILABLE_LIBS} gtest_main ) + +gtest_discover_tests(custom_section_test) diff --git a/tests/unit/custom-section/custom_section_test.cc b/tests/unit/custom-section/custom_section_test.cc new file mode 100644 index 000000000..9bf04664a --- /dev/null +++ b/tests/unit/custom-section/custom_section_test.cc @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "bh_platform.h" +#include +#include "test_helper.h" +#include "aot_export.h" + +class CustomSectionTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<1 * 1024 * 1024> runtime; +}; + +TEST_F(CustomSectionTest, get_custom_section_from_wasm_module_t) +{ + uint32_t length, len_from_aot; + const uint8_t *content, *content_from_aot; + std::ifstream wasm_file("wasm-apps/app.wasm", std::ios::binary); + std::vector buffer(std::istreambuf_iterator(wasm_file), + {}); + { + WAMRModule module(buffer.data(), buffer.size()); + aot_comp_data_t comp_data = NULL; + aot_comp_context_t comp_ctx = NULL; + std::vector sections_to_emit{ + "name", + ".debug_info", + ".debug_abbrev", + /* skip ".debug_line" section in AoT module */ + ".debug_str", + "producers", + }; + + AOTCompOption option = { 0 }; + option.custom_sections = (char **)sections_to_emit.data(); + option.custom_sections_count = 5; + + { + /* Compile an AoT module */ + comp_data = aot_create_comp_data(module.get(), NULL, false); + EXPECT_NE(comp_data, nullptr); + + comp_ctx = aot_create_comp_context(comp_data, &option); + EXPECT_NE(comp_ctx, nullptr); + + EXPECT_TRUE(aot_compile_wasm(comp_ctx)); + + EXPECT_TRUE(aot_emit_aot_file(comp_ctx, comp_data, "temp.aot")); + } + + std::ifstream aot_file("temp.aot", std::ios::binary); + std::vector aot_buffer( + std::istreambuf_iterator(aot_file), {}); + WAMRModule aot_module(aot_buffer.data(), aot_buffer.size()); + + /* name */ + content = + wasm_runtime_get_custom_section(module.get(), "name", &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + /* TODO: aot_emit_name_section don't + EMIT_U32(AOT_CUSTOM_SECTION_RAW);* + EMIT_STR("name"); + but instead + EMIT_U32(AOT_CUSTOM_SECTION_NAME); + can't use get_custom_section to get it + */ + // content_from_aot = wasm_runtime_get_custom_section( + // aot_module.get(), "name", &len_from_aot); + // EXPECT_NE(content_from_aot, nullptr); + // EXPECT_EQ(len_from_aot, length); + // EXPECT_EQ(memcmp(content_from_aot, content, length), 0); + + /* .debug_info */ + content = wasm_runtime_get_custom_section(module.get(), ".debug_info", + &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), ".debug_info", &len_from_aot); + EXPECT_NE(content_from_aot, nullptr); + EXPECT_EQ(len_from_aot, length); + EXPECT_EQ(memcmp(content_from_aot, content, length), 0); + + /* .debug_abbrev */ + content = wasm_runtime_get_custom_section(module.get(), ".debug_abbrev", + &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), ".debug_abbrev", &len_from_aot); + EXPECT_NE(content_from_aot, nullptr); + EXPECT_EQ(len_from_aot, length); + EXPECT_EQ(memcmp(content_from_aot, content, length), 0); + + /* .debug_line */ + content = wasm_runtime_get_custom_section(module.get(), ".debug_line", + &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), ".debug_line", &len_from_aot); + EXPECT_EQ(content_from_aot, nullptr); + + /* .debug_str */ + content = wasm_runtime_get_custom_section(module.get(), ".debug_str", + &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), ".debug_str", &len_from_aot); + EXPECT_NE(content_from_aot, nullptr); + EXPECT_EQ(len_from_aot, length); + EXPECT_EQ(memcmp(content_from_aot, content, length), 0); + + /* producers */ + content = + wasm_runtime_get_custom_section(module.get(), "producers", &length); + EXPECT_NE(content, nullptr); + EXPECT_GT(length, 0); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), "producers", &len_from_aot); + EXPECT_NE(content_from_aot, nullptr); + EXPECT_EQ(len_from_aot, length); + EXPECT_EQ(memcmp(content_from_aot, content, length), 0); + + /* Not exist */ + content = wasm_runtime_get_custom_section(module.get(), "producers1", + &length); + EXPECT_EQ(content, nullptr); + + content_from_aot = wasm_runtime_get_custom_section( + aot_module.get(), "producers1", &len_from_aot); + EXPECT_EQ(content_from_aot, nullptr); + } +} diff --git a/tests/unit/custom-section/wasm-apps/CMakeLists.txt b/tests/unit/custom-section/wasm-apps/CMakeLists.txt new file mode 100644 index 000000000..a539dd236 --- /dev/null +++ b/tests/unit/custom-section/wasm-apps/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project(wasm-apps-custom-section) + +# Add -g option so there will be debugger related custom sections +add_custom_target(app.wasm ALL + COMMAND /opt/wasi-sdk/bin/clang -g -nostdlib + -Wl,--no-entry,--export-all + -o ${CMAKE_CURRENT_BINARY_DIR}/app.wasm + ${CMAKE_CURRENT_LIST_DIR}/app.c +) diff --git a/tests/unit/custom-section/wasm-apps/app.c b/tests/unit/custom-section/wasm-apps/app.c new file mode 100644 index 000000000..3820e3c7c --- /dev/null +++ b/tests/unit/custom-section/wasm-apps/app.c @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +int +main(int argc, char const *argv[]) +{ + return 0; +} diff --git a/tests/unit/gc/CMakeLists.txt b/tests/unit/gc/CMakeLists.txt new file mode 100644 index 000000000..e0f70d142 --- /dev/null +++ b/tests/unit/gc/CMakeLists.txt @@ -0,0 +1,51 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-wamr-gc) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_GC 1) +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${LIB_HOST_AGENT_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} +) + +add_executable (gc_test ${unit_test_sources}) +target_link_libraries (gc_test gtest_main) + +add_custom_command(TARGET gc_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/*.was* + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copy wasm files to directory ${CMAKE_CURRENT_BINARY_DIR}" +) + +#gtest_discover_tests(gc_test) \ No newline at end of file diff --git a/tests/unit/gc/gc_test.cc b/tests/unit/gc/gc_test.cc new file mode 100644 index 000000000..196ddba65 --- /dev/null +++ b/tests/unit/gc/gc_test.cc @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "bh_platform.h" +#include "bh_read_file.h" +#include "wasm_export.h" + +class WasmGCTest : public testing::Test +{ + private: + std::string get_binary_path() + { + char cwd[1024] = { 0 }; + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + return NULL; + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); + } + + protected: + void SetUp() + { + CWD = get_binary_path(); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + + cleanup = true; + } + + void TearDown() + { + if (cleanup) { + wasm_runtime_destroy(); + } + } + + public: + bool load_wasm_file(const char *wasm_file) + { + const char *file; + unsigned char *wasm_file_buf; + uint32 wasm_file_size; + + file = strdup((CWD + "/" + wasm_file).c_str()); + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size); + if (!wasm_file_buf) + return false; + + module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + if (!module) + return false; + + return true; + } + + public: + std::string CWD; + RuntimeInitArgs init_args; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_function_inst_t func_inst = NULL; + wasm_exec_env_t exec_env = NULL; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + bool cleanup = true; +}; + +TEST_F(WasmGCTest, Test_app1) +{ + ASSERT_TRUE(load_wasm_file("test1.wasm")); + ASSERT_TRUE(load_wasm_file("test2.wasm")); + ASSERT_TRUE(load_wasm_file("test3.wasm")); + ASSERT_TRUE(load_wasm_file("test4.wasm")); + ASSERT_TRUE(load_wasm_file("test5.wasm")); + ASSERT_TRUE(load_wasm_file("test6.wasm")); + + ASSERT_TRUE(load_wasm_file("struct1.wasm")); + ASSERT_TRUE(load_wasm_file("struct2.wasm")); + ASSERT_TRUE(load_wasm_file("struct3.wasm")); + + ASSERT_TRUE(load_wasm_file("func1.wasm")); + ASSERT_TRUE(load_wasm_file("func2.wasm")); +} diff --git a/tests/unit/gc/wasm-apps/func1.wasm b/tests/unit/gc/wasm-apps/func1.wasm new file mode 100644 index 0000000000000000000000000000000000000000..51b316b54edacd385cb79b8d54e8ebe886eb0c20 GIT binary patch literal 106 zcmZQbEY4+QU|?YEY-ng;U`k+MNMK6OVqk6paTyueJHRwcNosKk0|VD~FmEG>6ksl3 s&S%VH%wPq&S7B8VPq^|1kw=UEXH&NhTk4(QVNW}9kZmk0cPtN<^TWy literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/func1.wast b/tests/unit/gc/wasm-apps/func1.wast new file mode 100644 index 000000000..1b4941787 --- /dev/null +++ b/tests/unit/gc/wasm-apps/func1.wast @@ -0,0 +1,35 @@ +(module + (type $t (func)) + + (func (export "test") (param structref i31ref) + (local funcref) + (local funcref) + (local funcref) + (local externref) + (local externref) + (local externref) + (local anyref) + (local eqref) + (local structref) + (local arrayref) + (local i31ref) + (local (ref null 0)) + (local (ref null 0)) + (local (ref null 0)) + (local (ref null 1)) + (local (ref null func)) + (local (ref null 0)) + (local (ref null extern)) + (local (ref null any)) + (local (ref null eq)) + (local (ref null i31)) + (local (ref null struct)) + + local.get 0 + ref.test null array + drop + local.get 1 + ref.cast i31 + drop + ) +) diff --git a/tests/unit/gc/wasm-apps/func2.wasm b/tests/unit/gc/wasm-apps/func2.wasm new file mode 100644 index 0000000000000000000000000000000000000000..e5d852ce4664d9109bc5ae6e0c5f7da48096d746 GIT binary patch literal 470 zcmcJKO=`q23`U=l$)+dhsz>ON;iMMtn~{e0(kf z$k*e3=Y51xqA}r+RpHTk{>JMo6g)Z)`ut}Aj z8&@(bArn>-3lpA*jXmnE;+bvs@%k2s> literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/func2.wast b/tests/unit/gc/wasm-apps/func2.wast new file mode 100644 index 000000000..bfe588dd5 --- /dev/null +++ b/tests/unit/gc/wasm-apps/func2.wast @@ -0,0 +1,78 @@ +(module + (type $t0 (func)) + (type $t1 (func (param (ref null 1)))) + (type $t2 (func (param funcref externref (ref func)(ref extern) + anyref eqref structref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 1) (ref $t0) (ref null func) + (ref null extern) (ref null 2) (ref null $t0)) + (result (ref null func)))) + (type $t3 (func (param i32 i32) (result (ref null 3)))) + + (type $t4 (func)) + (type $t5 (func (param (ref null 3)))) + (type $t6 (func (param funcref externref (ref func)(ref extern) + anyref eqref structref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)) + (result (ref null func)))) + (type $t7 (func (param i32 i32) (result (ref null 4)))) + + (type $t11 (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null struct) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + + (type $t12 (struct)) + (type $t13 (struct (field))) + (type $t14 (struct (field i8))) + (type $t15 (struct (field i8 i8 i8 i8))) + (type $t16 (struct (field $x1 i32) (field $y1 i32))) + (type $t17 (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type $t18 (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type $t19 (struct (field $x2 i32) (field f32 f64) (field $y2 i32))) + + (type $t20 (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func)(ref extern) + anyref eqref structref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + + (type $t21 (struct)) + (type $t22 (struct (field))) + (type $t23 (struct (field i8))) + (type $t24 (struct (field i8 i8 i8 i8))) + (type $t25 (struct (field $x3 i32) (field $y3 i32))) + (type $t26 (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type $t27 (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type $t28 (struct (field $x4 i32) (field f32 f64) (field $y4 i32))) + + (type $t31 (array i8)) + (type $t32 (array i16)) + (type $t33 (array i32)) + (type $t34 (array i64)) + (type $t35 (array f32)) + (type $t36 (array f64)) + (type $t37 (array anyref)) + (type $t38 (array (ref i31))) + (type $t39 (array (ref 0))) + (type $t40 (array (ref null 1))) + (type $t43 (array (mut i8))) + (type $t44 (array (mut i16))) + (type $t45 (array (mut i32))) + (type $t46 (array (mut i64))) + (type $t47 (array (mut i32))) + (type $t48 (array (mut i64))) + (type $t49 (array (mut anyref))) + (type $t50 (array (mut (ref struct)))) + (type $t51 (array (mut (ref 0)))) + (type $t52 (array (mut (ref null i31)))) +) diff --git a/tests/unit/gc/wasm-apps/global1.wasm b/tests/unit/gc/wasm-apps/global1.wasm new file mode 100644 index 0000000000000000000000000000000000000000..706cc954c48e64ac555113486c195338e876633a GIT binary patch literal 554 zcmd6k!EM7Z3`HO9B!_r`o;pJ(qTP!Rk}L`6DTZSO?WJ3EC8Ha3lTuE*Ku-llQuz4) zlY)4DnFNrpx7&@UK?*}tRw+YsU1S*!UVIZIGz)}nY>A&!`Qb=t>1)VLf0(&P-xLb{ z+5D~F{i8XVJ_!A>VzW6$)0BO>vH#UJI-?h~peuSs7c`=Nv;?(B=q!2>Eu!mhjba2# oM4hy+H~VHeojz(mWj^T=Tk0ZP>?XFc8*6cFt~V_~Ui`xFqZ&{Tb0trK11dux-=#)eZEyj;Fj-$P?r!P(p SRyHP>1#RDEjM=pKcbx}0=@RMy literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/struct1.wast b/tests/unit/gc/wasm-apps/struct1.wast new file mode 100644 index 000000000..3ce6fde6b --- /dev/null +++ b/tests/unit/gc/wasm-apps/struct1.wast @@ -0,0 +1,10 @@ +(module + (type (struct)) + (type (struct (field))) + (type (struct (field i8))) + (type (struct (field i8 i8 i8 i8))) + (type (struct (field $x1 i32) (field $y1 i32))) + (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32))) +) diff --git a/tests/unit/gc/wasm-apps/struct2.wasm b/tests/unit/gc/wasm-apps/struct2.wasm new file mode 100644 index 0000000000000000000000000000000000000000..497a96441938f39943904cfb416a6bcc60893952 GIT binary patch literal 234 zcmaisF%H5o5CnI9wj*$pC-@2QqL?D0h)5G8L}AGdB6R$Lg1_;FG}x9xOS8APH@7%U zCj#Irr3BkaL}Ww&$G`!M*~OrSk_KjxxquCoXrqm-TL!TxxaM7MTE_kYm}7tLc2Jus t&*HDpKfj0FernOJX#K8L@K^+J_cd8T~Ud8Iiy p3=A-lVweac*AlSO9uUdMn8TpJ@SB-|QHr}4A>hdHn~i~y8vtg|A3y*A literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/struct3.wast b/tests/unit/gc/wasm-apps/struct3.wast new file mode 100644 index 000000000..b7678ba78 --- /dev/null +++ b/tests/unit/gc/wasm-apps/struct3.wast @@ -0,0 +1,9 @@ +(module + (type $t (struct (field i32 (mut i32)))) + (func (export "struct.get-null") + (local (ref null $t)) (drop (struct.get $t 1 (local.get 0))) + ) + (func (export "struct.set-null") + (local (ref null $t)) (struct.set $t 1 (local.get 0) (i32.const 0)) + ) +) diff --git a/tests/unit/gc/wasm-apps/table1.wasm b/tests/unit/gc/wasm-apps/table1.wasm new file mode 100644 index 0000000000000000000000000000000000000000..f43b425398e0addf187cb0dcc315aff6fc251cbe GIT binary patch literal 560 zcmd6kJx;_h5QV=8fRxxof=mDoCj49&_^9r#SXQAXM2-L+|nR9yx_N)RK){ zBs3lTmD)Z{+@;9M!b~RNGd>X+=@|%E@dMwH!7z_C@iX@Pa3R#Rd&orFOq|hHg+hBZ zecMm{XiCNpLVMY<$rPh;%2D02|5Z0Sp?9>PE4rXF8d2Zd1hq%#BzhMuqU-M(#S&~H qI!N=m**D)Z*Th5QW#qNT4LEbvnXNA45-#G#1GdW(F;AVD>b?QRrG>5l literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/table1.wast b/tests/unit/gc/wasm-apps/table1.wast new file mode 100644 index 000000000..8e0061835 --- /dev/null +++ b/tests/unit/gc/wasm-apps/table1.wast @@ -0,0 +1,108 @@ +(module + (type $ftype0 (func (param i32))) + (type $ftype1 (func (param i32 i64) (result i32))) + (type $ftype2 (func (param f32 f64) (result f64))) + (type $t0 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2)))) + (type $t1 (func (param funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 3) (ref null $t0)) + (result (ref null func)))) + (type $t2 (func (param i32 i32) (result (ref null 4)))) + + ;; Duplicated types + (type $t3 (func)) + (type $t4 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2)))) + (type $t5 (func (param funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 3) (ref null $t0)) + (result (ref null func)))) + (type $t6 (func (param i32 i32) (result (ref null 4)))) + + (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + (type (struct)) + (type (struct (field))) + (type (struct (field i8))) + (type (struct (field i8 i8 i8 i8))) + (type (struct (field $x1 i32) (field $y1 i32))) + (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32))) + + ;; Duplicated types + (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64 + funcref externref (ref func)(ref extern) + anyref eqref arrayref i31ref + (ref null 0) (ref null 2) (ref null func) (ref null extern) + (ref null any) (ref null eq) (ref null i31) (ref null array) + (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func) + (ref null extern) (ref null 5) (ref null $t0)))) + + (type (struct)) + (type (struct (field))) + (type (struct (field i8))) + (type (struct (field i8 i8 i8 i8))) + (type (struct (field $x3 i32) (field $y3 i32))) + (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type (struct (field $x4 i32) (field f32 f64) (field $y4 i32))) + + (type (array i8)) + (type (array i16)) + (type (array i32)) + (type (array i64)) + (type (array f32)) + (type (array f64)) + (type (array anyref)) + (type (array (ref array))) + (type (array (ref 0))) + (type (array (ref null 1))) + (type (array (mut i8))) + (type (array (mut i16))) + (type (array (mut i32))) + (type (array (mut i64))) + (type (array (mut i32))) + (type (array (mut i64))) + (type (array (mut anyref))) + (type (array (mut (ref array)))) + (type (array (mut (ref 0)))) + (type (array (mut (ref null i31)))) + + (table 10 funcref) + (table 20 externref) + ;; non-defaultable element type + ;; (table 30 (ref func)) + ;; (table 40 (ref extern)) + (table 50 anyref) + (table 60 eqref) + (table 100 arrayref) + (table 100 i31ref) + (table 100 (ref null 0)) + (table 100 (ref null 2)) + (table 100 (ref null func)) + (table 100 (ref null extern)) + (table 100 (ref null any)) + (table 100 (ref null eq)) + (table 100 (ref null i31)) + (table 100 (ref null array)) + ;; non-defaultable element type + ;; (table 100 (ref 0)) + ;; (table 100 (ref $t0)) + ;; (table 100 (ref 3)) + ;; (table 100 (ref $t0)) + (table 100 (ref null func)) + (table 100 (ref null extern)) + (table 100 (ref null 5)) + (table 100 (ref null $t0)) +) diff --git a/tests/unit/gc/wasm-apps/test1.wasm b/tests/unit/gc/wasm-apps/test1.wasm new file mode 100644 index 0000000000000000000000000000000000000000..d907e457f589c37ecdb58ceac4ac65fd12e46af4 GIT binary patch literal 647 zcmd5%NlwE+5Uh3x2VTJ&P;x;$A}?s0L+r#g9$VsMEAiyOr@2vMgAgA;sMXb@nyOy# z`qmi$`*^?I@KOQQeE_kf(NH}NeeBw%KAulMFAnS(*|BBAnn#{_3J4a8FAYIs@msbT zdRkSaB-x)0Djz3|mTblq7YyjZ0qhacp+SvSry>-~Pv+W%CA2@d$(TK1tK(4SunFbe zgf+?{A)$QG4Apf;ltcck-)3%7&nQn?Hjw(?ZR8VtgeUk6zrru@2xp_L;VMF1WMyEk5-?0O0*sX!s^Kq*bEo1%#u6Jzu^o&r697nzN3 zz(A3N|9|hBe`emm-)$HG_EDB4j0ND~_5ll)(tl(}?N#wHG`;&?6w(B&3|0!u{CuR| z)?*PDV3Rxuy&~8Zp4hL~-ko3g;Nuqh;sDKV+h7a5Ta0h6VO+F}yCUB&3k=R%;^(=4 zfcfu^a4(h^p0%mEA6>S6JxFk01Ub#z9sft{(X)CF)4*W;JgL``lz=U3b5V&YTvkP- zyb4G)*OU&qE;%DJT*wKhV&Fh#u@;8=~7m*bh2{$32vo(v1c8GOajLz>FHL)zgiPt*L6YV zdbzAV>`d$3!*+MQeZCXdP~NXMPaDzZ`^_w$RwO~9%3MN|;G#M_wNVw&s2-R_EdU?2 z1d6EDT-qPRiCl!5M^y~U5?oFokw7AWL;{Hf zW9m!AzI=xsKKCHegG3J!JxKI020D2HXPKQOoFtqioFtsazzKK)XO*2KoFtqioFtsa zz=^4BN1bhzvm|9VO3D(FGRL2~aprDPoQ4kGjt-{waN@H8F2N_12^GS54ZP({R>mt* z@D&{Cf+m<@f)OTIgLbLL1ZOb88WXIsEc+Qc6Ra`8h7jkiwC^v&|CSv8+D$WVsU6j9 ZR1DU|kW9ro?vQoUHVdocneEkX_6yM(<=+4R literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/test3.wast b/tests/unit/gc/wasm-apps/test3.wast new file mode 100644 index 000000000..4df02ce8f --- /dev/null +++ b/tests/unit/gc/wasm-apps/test3.wast @@ -0,0 +1,146 @@ +(module + (type $t0 (sub (struct))) + (type $t1 (sub $t0 (struct (field i32)))) + (type $t1' (sub $t0 (struct (field i32)))) + (type $t2 (sub $t1 (struct (field i32 i32)))) + (type $t2' (sub $t1' (struct (field i32 i32)))) + (type $t3 (sub $t0 (struct (field i32 i32)))) + (type $t0' (sub $t0 (struct))) + (type $t4 (sub $t0' (struct (field i32 i32)))) + + (table 20 (ref null struct)) + + (func $init + (table.set (i32.const 0) (struct.new_canon_default $t0)) + (table.set (i32.const 10) (struct.new_canon_default $t0)) + (table.set (i32.const 1) (struct.new_canon_default $t1)) + (table.set (i32.const 11) (struct.new_canon_default $t1')) + (table.set (i32.const 2) (struct.new_canon_default $t2)) + (table.set (i32.const 12) (struct.new_canon_default $t2')) + (table.set (i32.const 3) (struct.new_canon_default $t3)) + (table.set (i32.const 4) (struct.new_canon_default $t4)) + ) + + (func (export "test-sub") + (call $init) + (block $l + ;; must hold + (br_if $l (i32.eqz (ref.test null $t0 (ref.null struct)))) + (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test null $t0 (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 0))))) + (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 2))))) + (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 3))))) + (br_if $l (i32.eqz (ref.test null $t0 (table.get (i32.const 4))))) + + (br_if $l (i32.eqz (ref.test null $t1 (ref.null struct)))) + (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test null $t1 (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test null $t1 (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test null $t1 (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test null $t2 (ref.null struct)))) + (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test null $t2 (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test null $t2 (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test null $t3 (ref.null struct)))) + (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test null $t3 (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test null $t3 (table.get (i32.const 3))))) + + (br_if $l (i32.eqz (ref.test null $t4 (ref.null struct)))) + (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test null $t4 (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test null $t4 (table.get (i32.const 4))))) + + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 0))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 2))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 3))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 4))))) + + (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test $t2 (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test $t3 (table.get (i32.const 3))))) + + (br_if $l (i32.eqz (ref.test $t4 (table.get (i32.const 4))))) + + ;; must not hold + (br_if $l (ref.test $t0 (ref.null struct))) + (br_if $l (ref.test $t1 (ref.null struct))) + (br_if $l (ref.test $t2 (ref.null struct))) + (br_if $l (ref.test $t3 (ref.null struct))) + (br_if $l (ref.test $t4 (ref.null struct))) + + (br_if $l (ref.test $t1 (table.get (i32.const 0)))) + (br_if $l (ref.test $t1 (table.get (i32.const 3)))) + (br_if $l (ref.test $t1 (table.get (i32.const 4)))) + + (br_if $l (ref.test $t2 (table.get (i32.const 0)))) + (br_if $l (ref.test $t2 (table.get (i32.const 1)))) + (br_if $l (ref.test $t2 (table.get (i32.const 3)))) + (br_if $l (ref.test $t2 (table.get (i32.const 4)))) + + (br_if $l (ref.test $t3 (table.get (i32.const 0)))) + (br_if $l (ref.test $t3 (table.get (i32.const 1)))) + (br_if $l (ref.test $t3 (table.get (i32.const 2)))) + (br_if $l (ref.test $t3 (table.get (i32.const 4)))) + + (br_if $l (ref.test $t4 (table.get (i32.const 0)))) + (br_if $l (ref.test $t4 (table.get (i32.const 1)))) + (br_if $l (ref.test $t4 (table.get (i32.const 2)))) + (br_if $l (ref.test $t4 (table.get (i32.const 3)))) + + (return) + ) + (unreachable) + ) + + (func (export "test-canon") + (call $init) + (block $l + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 0))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 2))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 3))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 4))))) + + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 10))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 11))))) + (br_if $l (i32.eqz (ref.test $t0 (table.get (i32.const 12))))) + + (br_if $l (i32.eqz (ref.test $t1' (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test $t1' (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 11))))) + (br_if $l (i32.eqz (ref.test $t1 (table.get (i32.const 12))))) + + (br_if $l (i32.eqz (ref.test $t2' (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test $t2 (table.get (i32.const 12))))) + + (return) + ) + (unreachable) + ) +) diff --git a/tests/unit/gc/wasm-apps/test4.wasm b/tests/unit/gc/wasm-apps/test4.wasm new file mode 100644 index 0000000000000000000000000000000000000000..b4841a82cb878091351cbe6e43bbcdef6e88341f GIT binary patch literal 299 zcmZQbEY4+QU|?YEZD?p!Z5?qq__ba>{DX^ literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/test4.wast b/tests/unit/gc/wasm-apps/test4.wast new file mode 100644 index 000000000..8bf02e430 --- /dev/null +++ b/tests/unit/gc/wasm-apps/test4.wast @@ -0,0 +1,46 @@ +(module + (type $ft (func)) + (type $st (struct)) + (type $at (array i8)) + + (table 10 anyref) + + (elem declare func $f) + (func $f) + + (func (export "init") (param $x externref) + (table.set (i32.const 0) (ref.null any)) + (table.set (i32.const 1) (i31.new (i32.const 7))) + (table.set (i32.const 2) (struct.new_canon_default $st)) + (table.set (i32.const 3) (array.new_canon_default $at (i32.const 0))) + (table.set (i32.const 4) (extern.internalize (local.get $x))) + (table.set (i32.const 5) (ref.null i31)) + (table.set (i32.const 6) (ref.null struct)) + (table.set (i32.const 7) (ref.null none)) + ) + + (func (export "ref_cast_non_null") (param $i i32) + (drop (ref.as_non_null (table.get (local.get $i)))) + (drop (ref.cast null any (table.get (local.get $i)))) + ) + (func (export "ref_cast_null") (param $i i32) + (drop (ref.cast null any (table.get (local.get $i)))) + (drop (ref.cast null struct (table.get (local.get $i)))) + (drop (ref.cast null array (table.get (local.get $i)))) + (drop (ref.cast null i31 (table.get (local.get $i)))) + (drop (ref.cast null none (table.get (local.get $i)))) + ) + (func (export "ref_cast_i31") (param $i i32) + (drop (ref.cast i31 (table.get (local.get $i)))) + (drop (ref.cast null i31 (table.get (local.get $i)))) + ) + (func (export "ref_cast_struct") (param $i i32) + (drop (ref.cast struct (table.get (local.get $i)))) + (drop (ref.cast null struct (table.get (local.get $i)))) + ) + (func (export "ref_cast_array") (param $i i32) + (drop (ref.cast array (table.get (local.get $i)))) + (drop (ref.cast null array (table.get (local.get $i)))) + ) +) + diff --git a/tests/unit/gc/wasm-apps/test5.wasm b/tests/unit/gc/wasm-apps/test5.wasm new file mode 100644 index 0000000000000000000000000000000000000000..050ead4ae9fde01db1690721be8f931206be8d43 GIT binary patch literal 512 zcmaKoF;c@o3`M`R4mREtDX6w5T@JA&U2b3k!=xe<4s}e1OK=s28Lq%#sMrQcmPsnA zr!W04t&L6pNC4<_7zSLf(P2&K=x_pce1K}63Y-dQUySM&2(P*%G)+@kMO$3eZ`$K# z|IqJO{qr5Dweo(md)k59pQA?J)r5?~SR%J0s4$6&g;~IbgJ52`5`@AtK~=b3B7VGR ze1WfRxk1XfhLN1?49;q#yUj%@n~RcnO@&EWa+b0s>+wRCOPW=xTd6*!`u^s=J5LPm n^L@Ea@!P(CA%EaJ_|M|jebG5T&#^y9XmdGi^XUPV>yY9vVfuIE literal 0 HcmV?d00001 diff --git a/tests/unit/gc/wasm-apps/test5.wast b/tests/unit/gc/wasm-apps/test5.wast new file mode 100644 index 000000000..895473ce3 --- /dev/null +++ b/tests/unit/gc/wasm-apps/test5.wast @@ -0,0 +1,85 @@ +(module + (type $t0 (sub (struct))) + (type $t1 (sub $t0 (struct (field i32)))) + (type $t1' (sub $t0 (struct (field i32)))) + (type $t2 (sub $t1 (struct (field i32 i32)))) + (type $t2' (sub $t1' (struct (field i32 i32)))) + (type $t3 (sub $t0 (struct (field i32 i32)))) + (type $t0' (sub $t0 (struct))) + (type $t4 (sub $t0' (struct (field i32 i32)))) + + (table 20 (ref null struct)) + + (func $init + (table.set (i32.const 0) (struct.new_canon_default $t0)) + (table.set (i32.const 10) (struct.new_canon_default $t0)) + (table.set (i32.const 1) (struct.new_canon_default $t1)) + (table.set (i32.const 11) (struct.new_canon_default $t1')) + (table.set (i32.const 2) (struct.new_canon_default $t2)) + (table.set (i32.const 12) (struct.new_canon_default $t2')) + (table.set (i32.const 3) (struct.new_canon_default $t3)) + (table.set (i32.const 4) (struct.new_canon_default $t4)) + ) + + (func (export "test-sub") + (call $init) + + (drop (ref.cast null $t0 (ref.null struct))) + (drop (ref.cast null $t0 (table.get (i32.const 0)))) + (drop (ref.cast null $t0 (table.get (i32.const 1)))) + (drop (ref.cast null $t0 (table.get (i32.const 2)))) + (drop (ref.cast null $t0 (table.get (i32.const 3)))) + (drop (ref.cast null $t0 (table.get (i32.const 4)))) + + (drop (ref.cast null $t0 (ref.null struct))) + (drop (ref.cast null $t1 (table.get (i32.const 1)))) + (drop (ref.cast null $t1 (table.get (i32.const 2)))) + + (drop (ref.cast null $t0 (ref.null struct))) + (drop (ref.cast null $t2 (table.get (i32.const 2)))) + + (drop (ref.cast null $t0 (ref.null struct))) + (drop (ref.cast null $t3 (table.get (i32.const 3)))) + + (drop (ref.cast null $t4 (table.get (i32.const 4)))) + + (drop (ref.cast $t0 (table.get (i32.const 0)))) + (drop (ref.cast $t0 (table.get (i32.const 1)))) + (drop (ref.cast $t0 (table.get (i32.const 2)))) + (drop (ref.cast $t0 (table.get (i32.const 3)))) + (drop (ref.cast $t0 (table.get (i32.const 4)))) + + (drop (ref.cast $t1 (table.get (i32.const 1)))) + (drop (ref.cast $t1 (table.get (i32.const 2)))) + + (drop (ref.cast $t2 (table.get (i32.const 2)))) + + (drop (ref.cast $t3 (table.get (i32.const 3)))) + + (drop (ref.cast $t4 (table.get (i32.const 4)))) + ) + + (func (export "test-canon") + (call $init) + + (drop (ref.cast $t0 (table.get (i32.const 0)))) + (drop (ref.cast $t0 (table.get (i32.const 1)))) + (drop (ref.cast $t0 (table.get (i32.const 2)))) + (drop (ref.cast $t0 (table.get (i32.const 3)))) + (drop (ref.cast $t0 (table.get (i32.const 4)))) + + (drop (ref.cast $t0 (table.get (i32.const 10)))) + (drop (ref.cast $t0 (table.get (i32.const 11)))) + (drop (ref.cast $t0 (table.get (i32.const 12)))) + + (drop (ref.cast $t1' (table.get (i32.const 1)))) + (drop (ref.cast $t1' (table.get (i32.const 2)))) + + (drop (ref.cast $t1 (table.get (i32.const 11)))) + (drop (ref.cast $t1 (table.get (i32.const 12)))) + + (drop (ref.cast $t2' (table.get (i32.const 2)))) + + (drop (ref.cast $t2 (table.get (i32.const 12)))) + ) +) diff --git a/tests/unit/gc/wasm-apps/test6.wasm b/tests/unit/gc/wasm-apps/test6.wasm new file mode 100644 index 0000000000000000000000000000000000000000..b1abc14729ffe04acd72180963e77174e24912ab GIT binary patch literal 197 zcmXYpu?@m75Jmr83^t@g4B#g0;SD?ign}YSMnX{0*b;P6W?>8JG<0m@2HQz-|J{Gm z9ga6g0O%b;z{=u)G~}^=z*25gPFxlZuAud= us83E9jBW=*<2fZ88FgYcQy5kHA~KR*PLKw1!>Oxzsr&Luqk*Od-}( +#include "gtest/gtest.h" +#include "wasm_runtime_common.h" +#include "bh_platform.h" + +// To use a test fixture, derive a class from testing::Test. +class InterpreterTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() { wasm_runtime_destroy(); } + + public: + char global_heap_buf[512 * 1024]; + RuntimeInitArgs init_args; +}; + +TEST_F(InterpreterTest, wasm_runtime_is_built_in_module) +{ + bool ret = wasm_runtime_is_built_in_module("env"); + ASSERT_TRUE(ret); + + ret = ret = wasm_runtime_is_built_in_module("env1"); + ASSERT_FALSE(ret); +} \ No newline at end of file diff --git a/tests/unit/libc-builtin/CMakeLists.txt b/tests/unit/libc-builtin/CMakeLists.txt new file mode 100644 index 000000000..4d88760e7 --- /dev/null +++ b/tests/unit/libc-builtin/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-libc-builtin) + +add_definitions (-DRUN_ON_LINUX) + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ) + +add_executable (libc_builtin_test ${unit_test_sources}) + +target_link_libraries (libc_builtin_test gtest_main) + +gtest_discover_tests(libc_builtin_test) diff --git a/tests/unit/libc-builtin/func_types.h b/tests/unit/libc-builtin/func_types.h new file mode 100644 index 000000000..c653ee9c8 --- /dev/null +++ b/tests/unit/libc-builtin/func_types.h @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#pragma once + +#include "bh_platform.h" +#include "wasm_export.h" + +extern "C" { +typedef char *_va_list; + +typedef int (*printf_func_type)(wasm_exec_env_t exec_env, const char *format, + _va_list va_args); + +typedef int (*sprintf_func_type)(wasm_exec_env_t exec_env, char *str, + const char *format, _va_list va_args); + +typedef int (*snprintf_func_type)(wasm_exec_env_t exec_env, char *str, + uint32 size, const char *format, + _va_list va_args); + +typedef int (*puts_func_type)(wasm_exec_env_t exec_env, const char *str); + +typedef int (*putchar_func_type)(wasm_exec_env_t exec_env, int c); + +typedef uint32 (*strdup_func_type)(wasm_exec_env_t exec_env, const char *str); + +typedef uint32 (*_strdup_func_type)(wasm_exec_env_t exec_env, const char *str); + +typedef int32 (*memcmp_func_type)(wasm_exec_env_t exec_env, const void *s1, + const void *s2, uint32 size); + +typedef uint32 (*memcpy_func_type)(wasm_exec_env_t exec_env, void *dst, + const void *src, uint32 size); + +typedef uint32 (*memmove_func_type)(wasm_exec_env_t exec_env, void *dst, + void *src, uint32 size); + +typedef uint32 (*memset_func_type)(wasm_exec_env_t exec_env, void *s, int32 c, + uint32 size); + +typedef uint32 (*strchr_func_type)(wasm_exec_env_t exec_env, const char *s, + int32 c); + +typedef int32 (*strcmp_func_type)(wasm_exec_env_t exec_env, const char *s1, + const char *s2); + +typedef int32 (*strncmp_func_type)(wasm_exec_env_t exec_env, const char *s1, + const char *s2, uint32 size); + +typedef uint32 (*strcpy_func_type)(wasm_exec_env_t exec_env, char *dst, + const char *src); + +typedef uint32 (*strncpy_func_type)(wasm_exec_env_t exec_env, char *dst, + const char *src, uint32 size); + +typedef uint32 (*strlen_func_type)(wasm_exec_env_t exec_env, const char *s); + +typedef uint32 (*malloc_func_type)(wasm_exec_env_t exec_env, uint32 size); + +typedef uint32 (*calloc_func_type)(wasm_exec_env_t exec_env, uint32 nmemb, + uint32 size); + +typedef uint32 (*realloc_func_type)(wasm_exec_env_t exec_env, uint32 ptr, + uint32 new_size); + +typedef void (*free_func_type)(wasm_exec_env_t exec_env, void *ptr); + +typedef int32 (*atoi_func_type)(wasm_exec_env_t exec_env, const char *s); + +typedef void (*exit_func_type)(wasm_exec_env_t exec_env, int32 status); + +typedef int32 (*strtol_func_type)(wasm_exec_env_t exec_env, const char *nptr, + char **endptr, int32 base); + +typedef uint32 (*strtoul_func_type)(wasm_exec_env_t exec_env, const char *nptr, + char **endptr, int32 base); + +typedef uint32 (*memchr_func_type)(wasm_exec_env_t exec_env, const void *s, + int32 c, uint32 n); + +typedef int32 (*strncasecmp_func_type)(wasm_exec_env_t exec_env, const char *s1, + const char *s2, uint32 n); +typedef uint32 (*strspn_func_type)(wasm_exec_env_t exec_env, const char *s, + const char *accept); + +typedef uint32 (*strcspn_func_type)(wasm_exec_env_t exec_env, const char *s, + const char *reject); + +typedef uint32 (*strstr_func_type)(wasm_exec_env_t exec_env, const char *s, + const char *find); + +typedef int32 (*isupper_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isalpha_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isspace_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isgraph_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isprint_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isdigit_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isxdigit_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*tolower_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*toupper_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef int32 (*isalnum_func_type)(wasm_exec_env_t exec_env, int32 c); + +typedef void (*setTempRet0_func_type)(wasm_exec_env_t exec_env, + uint32 temp_ret); + +typedef uint32 (*getTempRet0_func_type)(wasm_exec_env_t exec_env); + +typedef uint32 (*llvm_bswap_i16_func_type)(wasm_exec_env_t exec_env, + uint32 data); + +typedef uint32 (*llvm_bswap_i32_func_type)(wasm_exec_env_t exec_env, + uint32 data); + +typedef uint32 (*bitshift64Lshr_func_type)(wasm_exec_env_t exec_env, + uint32 uint64_part0, + uint32 uint64_part1, uint32 bits); + +typedef uint32 (*bitshift64Shl_func_type)(wasm_exec_env_t exec_env, + uint32 int64_part0, + uint32 int64_part1, uint32 bits); + +typedef void (*llvm_stackrestore_func_type)(wasm_exec_env_t exec_env, + uint32 llvm_stack); + +typedef uint32 (*llvm_stacksave_func_type)(wasm_exec_env_t exec_env); + +typedef uint32 (*emscripten_memcpy_big_func_type)(wasm_exec_env_t exec_env, + void *dst, const void *src, + uint32 size); + +typedef void (*abort_func_type)(wasm_exec_env_t exec_env, int32 code); + +typedef void (*abortStackOverflow_func_type)(wasm_exec_env_t exec_env, + int32 code); + +typedef void (*nullFunc_X_func_type)(wasm_exec_env_t exec_env, int32 code); + +typedef uint32 (*__cxa_allocate_exception_func_type)(wasm_exec_env_t exec_env, + uint32 thrown_size); + +typedef void (*__cxa_begin_catch_func_type)(wasm_exec_env_t exec_env, + void *exception_object); + +typedef void (*__cxa_throw_func_type)(wasm_exec_env_t exec_env, + void *thrown_exception, void *tinfo, + uint32 table_elem_idx); + +struct timespec_app { + int64 tv_sec; + int32 tv_nsec; +}; + +typedef uint32 (*clock_gettime_func_type)(wasm_exec_env_t exec_env, + uint32 clk_id, + struct timespec_app *ts_app); + +typedef uint64 (*clock_func_type)(wasm_exec_env_t exec_env); +} diff --git a/tests/unit/libc-builtin/libc_builtin_test.cc b/tests/unit/libc-builtin/libc_builtin_test.cc new file mode 100644 index 000000000..6598f7a8b --- /dev/null +++ b/tests/unit/libc-builtin/libc_builtin_test.cc @@ -0,0 +1,1412 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "func_types.h" +#include "test_helper.h" +#include "wasm_export.h" +#include "gtest/gtest.h" +#include + +#include "../interpreter/wasm.h" + +void *func_ptr; +#define CALL_FUNC(name, ...) \ + ((name##_func_type)get_func(#name))(dummy_exec_env.get(), ##__VA_ARGS__) + +extern "C" { +extern uint32_t +get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis); + +extern bool +wasm_native_lookup_libc_builtin_global(const char *module_name, + const char *global_name, + WASMGlobalImport *global); +} + +class LibcBuiltinTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() + { + n_native_symbols = get_libc_builtin_export_apis(&native_symbols); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; + DummyExecEnv dummy_exec_env; + static NativeSymbol *native_symbols; + static uint32_t n_native_symbols; + + static void *get_func(const char *name) + { + int32_t i; + + for (i = 0; i < n_native_symbols; i++) { + if (strcmp(native_symbols[i].symbol, name) == 0) { + return native_symbols[i].func_ptr; + } + } + + return NULL; + } +}; + +NativeSymbol *LibcBuiltinTest::native_symbols; +uint32_t LibcBuiltinTest::n_native_symbols; + +static const char very_long_string[] = + R"(2mwa9vxDhuuvO47XePZvc4DAMdR8dzgKrmRNAM3qVoedFhG7GYyhlC4JiuSdrw8G + 7vrPoCLGlVlGwMw7ATDL3bA5Filds8krTxS7h8ioq6CY4UmKl1zjHlmnOYRO3Wmp + ylp21RrG8LzfHFerFyKFxA1GB93OuTFcasO2n9uQljCx8h5KRolbvjdHVnado4B6 + 3zNV990V7T7LIJHwZKb0RGg0fFo4GQd6Mfdl6aD3UlpKBIxjbonyeaQBY7hPZB8R + J1JV5iw2PWB2BJEGoGhTvlc0a9FxmeqWIjpnU3yNEg2lD3NjZU627pTFcoAy5GCz + wDyF5QzcvtAgWBR95kRpDtV21CRyQ6HteorX1aHemoMYWOLIvX52stUTAnOImMD8 + tIw6xwkOZx5fs3x9m540pPnRDiihLn2XuQ1PLPwA6orWOGm3dBKthqsycTqaIl0L + 0gpycKbVYFHmakfgEyP9fyMziLT11B6EPzomHQAYgTVUdDl9u63P6sQCeaPwAYsY + gus28uK9YYjpXgOOziG8ocBddvids1iLJLdbiAqKyHaVY4IBLVWU3F74tKGF7TeI + DGAfvpzHls19VM9bKReBfCmDgbib7mCpYEFAQCmu5my0C8QrJlUoOgiljIO0x3sH + ByNf4k9OfhzYi1V4cvDnMELVrk0fyZWmIxDvig7nfzI57OltT28pughPBlLxTn8X + xyMNVYn1dD6Wpp7sqOBjxWGWmdrjleyin0iQ05UbfioHazvLKHtDfm5P2WwVejm6)"; + +TEST_F(LibcBuiltinTest, puts) +{ + char ll_string[2048]; + + /* Capture the stdout */ + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(puts, "Hello Wrold"), strlen("Hello Wrold\n")); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "Hello Wrold\n"); + + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(puts, "c"), strlen("c\n")); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "c\n"); + + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(puts, very_long_string), strlen(very_long_string) + 1); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + std::string(very_long_string) + "\n"); + + memset(ll_string, 0xAA, sizeof(ll_string)); + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(puts, ll_string), strlen(ll_string) + 1); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + std::string(ll_string) + "\n"); +} + +TEST_F(LibcBuiltinTest, printf) +{ + WAMRVaList empty_va_list(dummy_exec_env.get()); + + /* Capture the stdout */ + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", empty_va_list.get()), + strlen("Hello Wrold")); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "Hello Wrold"); + + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(printf, "c", empty_va_list.get()), strlen("c")); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "c"); + + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(printf, very_long_string, empty_va_list.get()), + strlen(very_long_string)); + EXPECT_EQ(testing::internal::GetCapturedStdout(), very_long_string); + + /* type */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(20); //%d 20 + va_list.add(65); //%i 65 + va_list.add(10); //%O 12 + va_list.add(10); //%u 10 + va_list.add(255); //%x ff + va_list.add(255); //%X FF + va_list.add(3.14); //%f 3.14 + va_list.add(3.14); //%F 3.14 + va_list.add(0.000001); //%e 1.000000e-06 + va_list.add(0.000001); //%E 1.000000E-06 + va_list.add(0.000001); //%g 1e-06 + va_list.add(0.000001); //%G 1E-06 + va_list.add("Hello World"); //%s Hello World + + testing::internal::CaptureStdout(); + /* clang-format off */ + EXPECT_EQ(CALL_FUNC(printf, "%d, %i, %o, %u, %x, %X, %f, %F, %e, %E, %g, %G, %s", va_list.get()), 97); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + "20, 65, 12, 10, ff, FF, 3.140000, 3.140000, 1.000000e-06, 1.000000E-06, 1e-06, 1E-06, Hello World"); + /* clang-format on */ + } + + /* %c */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add('C'); //%c C + // va_list.add("Hello"); //%p + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(printf, "%c", va_list.get()), 1); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "C"); + } + + /* %p */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add("Hello"); + testing::internal::CaptureStdout(); + EXPECT_EQ(CALL_FUNC(printf, "%p", va_list.get()), 7); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "0x200a8"); + } + + { + /* clang-format off */ + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(20); //%td + va_list.add(20); //%zd + va_list.add(20); //%ld + + va_list.add(20L); //%jd + + testing::internal::CaptureStdout(); + + EXPECT_EQ(CALL_FUNC(printf, "%td, %zd, %ld, %jd", va_list.get()), 14); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + "20, 20, 20, 20"); + /* clang-format on */ + } + + /* %% */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + EXPECT_TRUE(CALL_FUNC(printf, "%%", va_list.get())); + } + + /* %n */ + { + /* Construct a va_list to call printf */ + WAMRVaList empty_va_list(dummy_exec_env.get()); + + /* Capture the stdout */ + testing::internal::CaptureStdout(); + CALL_FUNC(printf, "0123%n", empty_va_list.get()); + EXPECT_EQ(testing::internal::GetCapturedStdout(), "0123"); + } + + /* flag */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + /*%-*/ + va_list.add(20); //%-d 20 + va_list.add(20); //%d 20 + + /*%+*/ + va_list.add(20); //%+d +20 + va_list.add(-20); //%+d -20 + + /*% */ + va_list.add(20); //% d 20 + va_list.add(-20); //% d -20 + + /*%#*/ + va_list.add(20); //%#o 024 + va_list.add(255); //%#x 0xff + va_list.add(255); //%#X 0xFF + va_list.add(3.14); //%#.f 3. + va_list.add(3.14); //%#.lf 3. + va_list.add(3.14); //%#.e 3.e+00 + va_list.add(3.14); //%#.E 3.E+00 + va_list.add(3.14); //%#.g 3. + va_list.add(3.14); //%#.G 3. + va_list.add(20); //%#.a %a + va_list.add(20); //%#.A %A + + /*%0*/ + va_list.add(20); //%03d 020 + + testing::internal::CaptureStdout(); + /* clang-format off */ + EXPECT_EQ(CALL_FUNC(printf, "%-d, %d, %+d, %+d, % d, % d, %#o, %#x, %#X, %#.f, %#.lf, %#.e, %#.E, %#.g, %#.G, %#.a, %#.A, %03d", va_list.get()), 88); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + "20, 20, +20, -20, 20, -20, 024, 0xff, 0XFF, 3., 3., 3.e+00, 3.E+00, 3., 3., %a, %A, 020"); + /* clang-format on */ + } + + /* precision */ + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(20); //%d 20 + va_list.add(20); //%.1d 20 + va_list.add(20); //%.2d 20 + va_list.add(20); //%.3d 020 + va_list.add(20); //%.4d 0020 + va_list.add(20); //%.5d 00020 + va_list.add(20); //%.6d 000020 + va_list.add(20); //%.7d 0000020 + va_list.add(20); //%.8d 00000020 + va_list.add(20); //%.9d 000000020 + testing::internal::CaptureStdout(); + /* clang-format off */ + EXPECT_EQ(CALL_FUNC(printf, "%d, %.1d, %.2d, %.3d, %.4d, %.5d, %.6d, %.7d, %.8d, %.9d", va_list.get()), 66); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + "20, 20, 20, 020, 0020, 00020, 000020, 0000020, 00000020, 000000020"); + /* clang-format on */ + } + + /*length*/ + { + /* clang-format off */ + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(0x7F); //%hhd 127 -char + va_list.add(0xFF); //%hhu.1d 255 -unsiged char + va_list.add(0x7FFF); //%hd 32767 -sing short int + va_list.add(0xFFFF); //%hu 65535 -unsiged short + va_list.add(0x7FFFFFFF); //%ld 2147483647 - sing long + va_list.add(0xFFFFFFFF); //%lu 4294967295 -unsigned long + va_list.add(0x7FFFFFFFFFFFFFFF); //%lld 9223372036854775807 sing long long + va_list.add(0xFFFFFFFFFFFFFFFF);//%llu 18446744073709551615 unsiged long long + + testing::internal::CaptureStdout(); + + EXPECT_EQ(CALL_FUNC(printf, "%hhd, %hhu, %hd, %hu, %ld, %lu, %lld, %llu", va_list.get()), 89); + EXPECT_EQ(testing::internal::GetCapturedStdout(), + "127, 255, 32767, 65535, 2147483647, 4294967295, 9223372036854775807, 18446744073709551615"); + /* clang-format on */ + } + + EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", 0), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", NULL), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_EQ(CALL_FUNC(printf, "Hello Wrold", (char *)-1), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_EQ(CALL_FUNC(printf, (char *)-1, (char *)-1), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); +} + +TEST_F(LibcBuiltinTest, sprintf) +{ + const char *buf; + const char *str = "Hello Wrold"; + const char *str_sig = "c"; + const char *str_f = "20, 3.140000, Hello World"; + const char *str_long = "eqwewerwerqwer34were"; // test ok + // const char *str_long = "TDSFGAWE%#$TERFQ@$%$@!%$@!RS!$#@$%" + // "WAWAAEWAFSDNGFUTKNZDAERQWYNZREWGHAH"; + // //fail + + WAMRVaList empty_va_list(dummy_exec_env.get()); + + AppData buf_app{ dummy_exec_env.get(), buf }; + AppData str_app{ dummy_exec_env.get(), str }; + AppData str_sig_app{ dummy_exec_env.get(), str_sig }; + AppData str_long_app{ dummy_exec_env.get(), str_long }; + + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_app.get_native_addr(), 0), + 0); + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_app.get_native_addr(), NULL), + 0); + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_app.get_native_addr(), (char *)-1), + 0); + + EXPECT_FALSE(CALL_FUNC(sprintf, (char *)-1, + (char *)str_app.get_native_addr(), + empty_va_list.get())); + + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_app.get_native_addr(), empty_va_list.get()), + strlen(str)); + EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(), + str_app.get_native_addr(), strlen(str)), + 0); + + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_sig_app.get_native_addr(), + empty_va_list.get()), + strlen(str_sig)); + EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(), + str_sig_app.get_native_addr(), strlen(str_sig)), + 0); + + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + (char *)str_long_app.get_native_addr(), + empty_va_list.get()), + strlen(str_long)); + EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(), + str_long_app.get_native_addr(), strlen(str_long)), + 0); + + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(20); + va_list.add(3.14); + va_list.add("Hello World"); + + /* This is like printf("%d, %f, %s", 20, 3.14, "Hello World") */ + EXPECT_EQ(CALL_FUNC(sprintf, (char *)buf_app.get_native_addr(), + "%d, %f, %s", va_list.get()), + 25); + EXPECT_EQ(CALL_FUNC(memcmp, buf_app.get_native_addr(), str_f, 25), 0); + } +} + +TEST_F(LibcBuiltinTest, snprintf) +{ + char buf[1024]; + char buf1[10]; + + WAMRVaList empty_va_list(dummy_exec_env.get()); + + EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", 0), + 0); + EXPECT_EQ( + CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", NULL), + 0); + EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", + (char *)-1), + 0); + + EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen("Hello Wrold"), "Hello Wrold", + empty_va_list.get()), + strlen("Hello Wrold")); + EXPECT_EQ(CALL_FUNC(memcmp, buf, "Hello Wrold", strlen("Hello Wrold")), 0); + + EXPECT_EQ(CALL_FUNC(snprintf, buf, strlen(very_long_string), + very_long_string, empty_va_list.get()), + strlen(very_long_string)); + { + /* Construct a va_list to call printf */ + WAMRVaList va_list(dummy_exec_env.get()); + + va_list.add(20); + va_list.add(3.14); + va_list.add("Hello World"); + + EXPECT_EQ(CALL_FUNC(snprintf, buf, 25, "%d, %f, %s", va_list.get()), + 25); + } +} + +TEST_F(LibcBuiltinTest, putchar) +{ + char ch; + + for (ch = 'a'; ch <= 'z'; ch++) + EXPECT_EQ(CALL_FUNC(putchar, ch), 1); + + for (ch = '0'; ch <= '9'; ch++) + EXPECT_EQ(CALL_FUNC(putchar, ch), 1); + + for (ch = 0; ch < 127; ch++) + EXPECT_EQ(CALL_FUNC(putchar, ch), 1); +} + +TEST_F(LibcBuiltinTest, strdup) +{ + const char *src = "Hello World!"; + + AppData src_app{ dummy_exec_env.get(), src }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(strdup, NULL), 0); + + EXPECT_GE(CALL_FUNC(strdup, (char *)src_app.get_native_addr()), 0); +} + +TEST_F(LibcBuiltinTest, _strdup) +{ + const char *src = "Hello World!"; + + AppData src_app{ dummy_exec_env.get(), src }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(_strdup, NULL), 0); + + EXPECT_GE(CALL_FUNC(_strdup, (char *)src_app.get_native_addr()), 0); +} + +TEST_F(LibcBuiltinTest, memcmp) +{ + const char *a = "aBcDeF"; + const char *b = "AbCdEf"; + const char *c = "aacdef"; + const char *d = "aBcDeF"; + + AppData a_app{ dummy_exec_env.get(), a }; + AppData b_app{ dummy_exec_env.get(), b }; + AppData c_app{ dummy_exec_env.get(), c }; + AppData d_app{ dummy_exec_env.get(), d }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(memcmp, (void *)-1, d_app.get_native_addr(), 0), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + /* size = 0 */ + EXPECT_EQ( + CALL_FUNC(memcmp, a_app.get_native_addr(), d_app.get_native_addr(), 0), + 0); + + // /* s1>s2 */ + EXPECT_GT(CALL_FUNC(memcmp, a_app.get_native_addr(), + b_app.get_native_addr(), strlen(a)), + 0); + // /* s1s2*/ + EXPECT_GT(CALL_FUNC(strcmp, (char *)b_app.get_native_addr(), + (char *)a_app.get_native_addr()), + 0); + /*s1s2*/ + EXPECT_GT(CALL_FUNC(strncmp, (char *)b_app.get_native_addr(), + (char *)a_app.get_native_addr(), strlen(a)), + 0); + /*s1s2*/ + EXPECT_GT(CALL_FUNC(strncmp, (char *)b_app.get_native_addr(), + (char *)a_app.get_native_addr(), 3), + 0); + /*s1= UINT32_MAX */ + EXPECT_EQ(CALL_FUNC(calloc, 1, 0xffffffff), 0); + + /* nmemb = 1 size=0xffffffff-1 total_size >= UINT32_MAX-1 */ + EXPECT_EQ(CALL_FUNC(calloc, 1, (0xffffffff - 1)), 0); + + /* nmemb = 1 size = 0 total_size = 0 */ + /* According to Linux man page: + If nmemb or size is 0, then calloc() returns either NULL, or a unique + pointer value that can later be successfully passed to free() */ + EXPECT_GE(CALL_FUNC(calloc, 1, 0), 0); + + /* nmemb = 10 size = 1024 total_size < UINT32_MAX */ + EXPECT_GT(CALL_FUNC(calloc, 10, 1024), 0); +} + +TEST_F(LibcBuiltinTest, realloc) +{ + unsigned int ptr = 0; + + // ptr = 0; + // EXPECT_EQ(CALL_FUNC(realloc, ptr, 1024), 0); + + // ptr = 1; + // EXPECT_GT(CALL_FUNC(realloc, ptr, 1024), 0); + + // ptr = 3; + // EXPECT_GT(CALL_FUNC(realloc, ptr, 1024), 0); + + /* If ptr is NULL, then the call is equivalent to malloc(size), for all + * values of size */ + ptr = CALL_FUNC(realloc, ptr, 1024); + EXPECT_EQ(ptr, ptr); + EXPECT_EQ(CALL_FUNC(realloc, ptr, 10), ptr); + EXPECT_EQ(CALL_FUNC(realloc, ptr, 15), ptr); + + ptr = CALL_FUNC(realloc, ptr, 2048); + EXPECT_EQ(ptr, ptr); + + /* If size is equal to zero, and ptr is not NULL, then + the call is equivalent to free(ptr) */ + CALL_FUNC(realloc, ptr, 0); +} + +TEST_F(LibcBuiltinTest, free) +{ + const char *src; + const char *s = "Hello World!"; + + AppMemory src_mem{ dummy_exec_env.get(), 15 }; + AppData s_app{ dummy_exec_env.get(), s }; + + CALL_FUNC(free, (char *)0xFFFFFFFF); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + CALL_FUNC(free, (char *)-1); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + CALL_FUNC(free, NULL); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + memset((char *)src_mem.get_native_addr(), '\0', 15); + strcpy((char *)src_mem.get_native_addr(), (char *)s_app.get_native_addr()); + EXPECT_EQ(CALL_FUNC(memcmp, (char *)src_mem.get_native_addr(), + s_app.get_native_addr(), 15), + 0); + + /* free */ + CALL_FUNC(free, (char *)src_mem.get_native_addr()); + EXPECT_NE(CALL_FUNC(memcmp, (char *)src_mem.get_native_addr(), + s_app.get_native_addr(), 15), + 0); +} + +TEST_F(LibcBuiltinTest, atoi) +{ + char *src = (char *)"123"; + char *src1 = (char *)"-123"; + + AppData src_app{ dummy_exec_env.get(), src }; + AppData src1_app{ dummy_exec_env.get(), src1 }; + + EXPECT_EQ(CALL_FUNC(atoi, (char *)src_app.get_native_addr()), 123); + EXPECT_EQ(CALL_FUNC(atoi, (char *)src1_app.get_native_addr()), -123); +} + +TEST_F(LibcBuiltinTest, exit) +{ + CALL_FUNC(exit, 3); + EXPECT_STREQ(dummy_exec_env.get_exception(), "Exception: env.exit(3)"); + dummy_exec_env.clear_exception(); +} + +TEST_F(LibcBuiltinTest, strtol) +{ + char str[20] = "20"; + char str1[20] = "-20"; + char buffer[20] = "0x31"; + char buffer1[20] = "10379cend$3"; + char *ptr; + + AppData src_app{ dummy_exec_env.get(), str }; + AppData src1_app{ dummy_exec_env.get(), str1 }; + AppData buffer_app{ dummy_exec_env.get(), buffer }; + AppData buffer1_app{ dummy_exec_env.get(), buffer1 }; + AppMemory ptr_app{ dummy_exec_env.get(), 20 }; + + CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 10); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + CALL_FUNC(strtol, (char *)src_app.get_native_addr(), &ptr, 10); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 2), 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 8), 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 10), + 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 16), + 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), NULL, 32), + 0); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 2), + 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 8), + 16); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 20); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 16), + 32); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 32), + 64); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 2), + 0); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 8), + -16); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + -20); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 16), + -32); + EXPECT_EQ(CALL_FUNC(strtol, (char *)src1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 32), + -64); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 0), + 49); + EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 16), + 49); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 0); + + EXPECT_EQ(CALL_FUNC(strtol, (char *)buffer1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 10379); + // EXPECT_STREQ((char *)ptr_app.get_native_addr(), "cend$3"); + + uint32_t str_app_addr = *(uint32_t *)ptr_app.get_native_addr(); + EXPECT_GT(str_app_addr, 0); + char *str_native_addr = (char *)dummy_exec_env.app_to_native(str_app_addr); + EXPECT_NE(str_native_addr, nullptr); + EXPECT_STREQ(str_native_addr, "cend$3"); +} + +TEST_F(LibcBuiltinTest, strtoul) +{ + char str[20] = "20"; + char buffer[20] = "0x31"; + char buffer1[20] = "10379cend$3"; + char *ptr; + + AppData src_app{ dummy_exec_env.get(), str }; + AppData buffer_app{ dummy_exec_env.get(), buffer }; + AppData buffer1_app{ dummy_exec_env.get(), buffer1 }; + AppMemory ptr_app{ dummy_exec_env.get(), 20 }; + + CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 10); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), &ptr, 10); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 2), + 0); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 8), + 0); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 10), + 0); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 16), + 0); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), NULL, 32), + 0); + + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 2), + 0); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 8), + 16); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 20); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 16), + 32); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)src_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 32), + 64); + + EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 0), + 49); + EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 16), + 49); + + EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 0); + + EXPECT_EQ(CALL_FUNC(strtoul, (char *)buffer1_app.get_native_addr(), + (char **)ptr_app.get_native_addr(), 10), + 10379); + + uint32_t str_app_addr = *(uint32_t *)ptr_app.get_native_addr(); + EXPECT_GT(str_app_addr, 0); + char *str_native_addr = (char *)dummy_exec_env.app_to_native(str_app_addr); + EXPECT_NE(str_native_addr, nullptr); + EXPECT_STREQ(str_native_addr, "cend$3"); +} + +TEST_F(LibcBuiltinTest, memchr) +{ + const char src[] = "Hello World."; + char ch = 'o'; + + AppData src_app{ dummy_exec_env.get(), src }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(memchr, (char *)-1, ch, strlen(src)), 0); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: out of bounds memory access"); + dummy_exec_env.clear_exception(); + + EXPECT_GE(CALL_FUNC(memchr, src_app.get_native_addr(), ch, strlen(src)), 0); +} + +TEST_F(LibcBuiltinTest, strncasecmp) +{ + const char *src1 = "Hello World."; + const char *src2 = "hel"; + const char *src3 = "HELLO WORLD."; + + AppData src1_app{ dummy_exec_env.get(), src1 }; + AppData src2_app{ dummy_exec_env.get(), src2 }; + AppData src3_app{ dummy_exec_env.get(), src3 }; + + EXPECT_GT(CALL_FUNC(strncasecmp, (char *)src1_app.get_native_addr(), + (char *)src2_app.get_native_addr(), 4), + 0); + + EXPECT_LT(CALL_FUNC(strncasecmp, (char *)src2_app.get_native_addr(), + (char *)src1_app.get_native_addr(), 4), + 0); + + EXPECT_EQ(CALL_FUNC(strncasecmp, (char *)src1_app.get_native_addr(), + (char *)src3_app.get_native_addr(), strlen(src1)), + 0); +} + +TEST_F(LibcBuiltinTest, strspn) +{ + const char *src1 = "Hello world!"; + const char *src2 = "abcd"; + const char *src3 = "l"; + const char *src4 = "Hell"; + const char *src5 = "Helo"; + + AppData src1_app{ dummy_exec_env.get(), src1 }; + AppData src2_app{ dummy_exec_env.get(), src2 }; + AppData src3_app{ dummy_exec_env.get(), src3 }; + AppData src4_app{ dummy_exec_env.get(), src4 }; + AppData src5_app{ dummy_exec_env.get(), src5 }; + + EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(), + (char *)src2_app.get_native_addr()), + 0); + + EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(), + (char *)src3_app.get_native_addr()), + 0); + + EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(), + (char *)src4_app.get_native_addr()), + 4); + + EXPECT_EQ(CALL_FUNC(strspn, (char *)src1_app.get_native_addr(), + (char *)src5_app.get_native_addr()), + 5); +} + +TEST_F(LibcBuiltinTest, strcspn) +{ + const char *src1 = "Hello world!"; + const char *src2 = ".?"; + const char *src3 = "llo"; + const char *src4 = "http://www.baidu.com/"; + const char *src5 = "?.,:\"\'-!"; + + AppData src1_app{ dummy_exec_env.get(), src1 }; + AppData src2_app{ dummy_exec_env.get(), src2 }; + AppData src3_app{ dummy_exec_env.get(), src3 }; + AppData src4_app{ dummy_exec_env.get(), src4 }; + AppData src5_app{ dummy_exec_env.get(), src5 }; + + EXPECT_EQ(CALL_FUNC(strcspn, (char *)src1_app.get_native_addr(), + (char *)src2_app.get_native_addr()), + 12); + + EXPECT_EQ(CALL_FUNC(strcspn, (char *)src1_app.get_native_addr(), + (char *)src3_app.get_native_addr()), + 2); + + EXPECT_EQ(CALL_FUNC(strcspn, (char *)src4_app.get_native_addr(), + (char *)src5_app.get_native_addr()), + 4); +} + +TEST_F(LibcBuiltinTest, strstr) +{ + const char *src1 = "Hello world!"; + const char *src2 = "abcd"; + const char *src3 = "Hello"; + const char *src4 = "H"; + const char *src5 = "llo"; + + AppData src1_app{ dummy_exec_env.get(), src1 }; + AppData src2_app{ dummy_exec_env.get(), src2 }; + AppData src3_app{ dummy_exec_env.get(), src3 }; + AppData src4_app{ dummy_exec_env.get(), src4 }; + AppData src5_app{ dummy_exec_env.get(), src5 }; + + EXPECT_EQ(CALL_FUNC(strstr, (char *)src1_app.get_native_addr(), + (char *)src2_app.get_native_addr()), + 0); + + EXPECT_EQ(CALL_FUNC(strstr, (char *)src3_app.get_native_addr(), + (char *)src1_app.get_native_addr()), + 0); + + EXPECT_GT(CALL_FUNC(strstr, (char *)src1_app.get_native_addr(), + (char *)src4_app.get_native_addr()), + 0); + + EXPECT_GT(CALL_FUNC(strstr, (char *)src1_app.get_native_addr(), + (char *)src5_app.get_native_addr()), + 0); +} + +TEST_F(LibcBuiltinTest, isupper) +{ + EXPECT_FALSE(CALL_FUNC(isupper, 'a')); + + EXPECT_FALSE(CALL_FUNC(isupper, 97)); + + EXPECT_FALSE(CALL_FUNC(isupper, '0')); + + EXPECT_FALSE(CALL_FUNC(isupper, '.')); + + EXPECT_TRUE(CALL_FUNC(isupper, 'A')); + + EXPECT_TRUE(CALL_FUNC(isupper, 65)); +} + +TEST_F(LibcBuiltinTest, isalpha) +{ + EXPECT_FALSE(CALL_FUNC(isalpha, '0')); + + EXPECT_FALSE(CALL_FUNC(isalpha, 0)); + + EXPECT_FALSE(CALL_FUNC(isalpha, '?')); + + EXPECT_TRUE(CALL_FUNC(isalpha, 'A')); + + EXPECT_TRUE(CALL_FUNC(isalpha, 'a')); +} + +TEST_F(LibcBuiltinTest, isspace) +{ + EXPECT_FALSE(CALL_FUNC(isspace, '0')); + + EXPECT_FALSE(CALL_FUNC(isspace, 0)); + + EXPECT_FALSE(CALL_FUNC(isspace, '?')); + + EXPECT_TRUE(CALL_FUNC(isspace, ' ')); + EXPECT_TRUE(CALL_FUNC(isspace, '\t')); + EXPECT_TRUE(CALL_FUNC(isspace, '\n')); + EXPECT_TRUE(CALL_FUNC(isspace, '\v')); + EXPECT_TRUE(CALL_FUNC(isspace, '\f')); + EXPECT_TRUE(CALL_FUNC(isspace, '\r')); +} + +TEST_F(LibcBuiltinTest, isgraph) +{ + /* ASCII 0x00-0x20 */ + EXPECT_FALSE(CALL_FUNC(isgraph, 0x00)); + EXPECT_FALSE(CALL_FUNC(isgraph, 0x20)); + + /* ASCII 0x7F */ + EXPECT_FALSE(CALL_FUNC(isgraph, 0x7F)); + EXPECT_FALSE(CALL_FUNC(isgraph, 0x80)); + + /* ASCII 0x21-0x7E */ + EXPECT_TRUE(CALL_FUNC(isgraph, 0x21)); + EXPECT_TRUE(CALL_FUNC(isgraph, 0x7E)); +} + +TEST_F(LibcBuiltinTest, isprint) +{ + /* ASCII 0x00-0x1F */ + EXPECT_FALSE(CALL_FUNC(isprint, 0x00)); + EXPECT_FALSE(CALL_FUNC(isprint, 0x1F)); + + /* ASCII 0x7F */ + EXPECT_FALSE(CALL_FUNC(isprint, 0x7F)); + EXPECT_FALSE(CALL_FUNC(isprint, 0x80)); + + /* ASCII 0x20-0x7E */ + EXPECT_TRUE(CALL_FUNC(isprint, 0x20)); + EXPECT_TRUE(CALL_FUNC(isprint, 0x7E)); +} + +TEST_F(LibcBuiltinTest, isdigit) +{ + /* ASCII 0x00-0x2F */ + EXPECT_FALSE(CALL_FUNC(isdigit, 0x00)); + EXPECT_FALSE(CALL_FUNC(isdigit, 0x2F)); + + /* ASCII 0x3A-0x7F */ + EXPECT_FALSE(CALL_FUNC(isdigit, 0x3A)); + EXPECT_FALSE(CALL_FUNC(isdigit, 0x7F)); + + /* ASCII 0x30-0x39 */ + EXPECT_TRUE(CALL_FUNC(isdigit, 0x30)); + EXPECT_TRUE(CALL_FUNC(isdigit, 0x39)); +} + +TEST_F(LibcBuiltinTest, isxdigit) +{ + char str[] = "-FFEE"; + char str1[] = "FFEE"; + + EXPECT_FALSE(CALL_FUNC(isxdigit, str[0])); + EXPECT_TRUE(CALL_FUNC(isxdigit, str1[0])); + + /* ASCII 0x00-0x2F */ + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x00)); + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x2F)); + + /* ASCII 0x3A-0x40 */ + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x3A)); + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x40)); + + /* ASCII 0x49-0x60 */ + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x49)); + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x60)); + + /* ASCII 0x67-0x7F */ + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x67)); + EXPECT_FALSE(CALL_FUNC(isxdigit, 0x7F)); + + /* ASCII 0x30-0x39 */ + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x30)); + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x39)); + + /* ASCII 0x41-0x46 */ + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x41)); + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x46)); + + /* ASCII 0x61-0x66 */ + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x61)); + EXPECT_TRUE(CALL_FUNC(isxdigit, 0x66)); +} + +TEST_F(LibcBuiltinTest, tolower) +{ + char src[] = "aBcDeFgH12345;!#$"; + char dest[sizeof(src)]; + int i; + + for (i = 0; i < sizeof(src); i++) { + dest[i] = CALL_FUNC(tolower, (src[i])); + } + EXPECT_STREQ(dest, "abcdefgh12345;!#$"); +} + +TEST_F(LibcBuiltinTest, toupper) +{ + char src[] = "aBcDeFgH12345;!#$"; + char dest[sizeof(src)]; + int i; + + for (i = 0; i < sizeof(src); i++) { + dest[i] = CALL_FUNC(toupper, (src[i])); + } + EXPECT_STREQ(dest, "ABCDEFGH12345;!#$"); +} + +TEST_F(LibcBuiltinTest, isalnum) +{ + char src[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678" + "9!\"#$%&'()*+,-./:;<=>?@[^_'{|}~"; + int i; + int isalnum_cnt = 0; + + for (i = 0; i < sizeof(src); i++) { + if (CALL_FUNC(isalnum, (src[i]))) + isalnum_cnt++; + } + EXPECT_EQ(isalnum_cnt, 62); +} + +TEST_F(LibcBuiltinTest, emscripten_memcpy_big) +{ + const char *src = "Hell World"; + char *dest; + + AppData src_app{ dummy_exec_env.get(), src }; + AppData dest_app{ dummy_exec_env.get(), dest }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(emscripten_memcpy_big, (void *)-1, + src_app.get_native_addr(), 0), + 0); + + CALL_FUNC(emscripten_memcpy_big, dest_app.get_native_addr(), + src_app.get_native_addr(), strlen(src)); + EXPECT_EQ(CALL_FUNC(memcmp, dest_app.get_native_addr(), + src_app.get_native_addr(), strlen(src)), + 0); +} + +TEST_F(LibcBuiltinTest, abort) +{ + CALL_FUNC(abort, 33); + EXPECT_STREQ(dummy_exec_env.get_exception(), "Exception: env.abort(33)"); + dummy_exec_env.clear_exception(); +} + +TEST_F(LibcBuiltinTest, abortStackOverflow) +{ + CALL_FUNC(abortStackOverflow, 33); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: env.abortStackOverflow(33)"); + dummy_exec_env.clear_exception(); +} + +TEST_F(LibcBuiltinTest, nullFunc_X) +{ + CALL_FUNC(nullFunc_X, 33); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: env.nullFunc_X(33)"); + dummy_exec_env.clear_exception(); +} + +TEST_F(LibcBuiltinTest, __cxa_allocate_exception) +{ + EXPECT_NE(CALL_FUNC(__cxa_allocate_exception, 0x0), 0x0); + EXPECT_EQ(CALL_FUNC(__cxa_allocate_exception, 0xFFFF), 0x0); +} + +TEST_F(LibcBuiltinTest, __cxa_begin_catch) +{ + /* 无函数原型 */ +} + +TEST_F(LibcBuiltinTest, __cxa_throw) +{ + void *excepton; + void *tinfo; + + CALL_FUNC(__cxa_throw, excepton, tinfo, 1); + EXPECT_STREQ(dummy_exec_env.get_exception(), + "Exception: exception thrown by stdc++"); + dummy_exec_env.clear_exception(); +} + +struct timespec_app app; +TEST_F(LibcBuiltinTest, clock_gettime) +{ + struct timespec_app *tsapp; + tsapp = &app; + + AppMemory tsapp_app{ dummy_exec_env.get(), sizeof(struct timespec_app) }; + + /* exception */ + EXPECT_EQ(CALL_FUNC(clock_gettime, 0, (struct timespec_app *)-1), -1); + + EXPECT_EQ(CALL_FUNC(clock_gettime, 100, NULL), -1); + + EXPECT_EQ(CALL_FUNC(clock_gettime, 100, 0), -1); + + EXPECT_EQ(CALL_FUNC(clock_gettime, 10, + (struct timespec_app *)tsapp_app.get_native_addr()), + 0); +} + +TEST_F(LibcBuiltinTest, clock) +{ + EXPECT_GE(CALL_FUNC(clock), 0); +} + +WASMGlobalImport glb; +TEST_F(LibcBuiltinTest, wasm_native_lookup_libc_builtin_global) +{ + const char *module_name = "module name"; + const char *global_name = "global name"; + + const char *module_name1 = "global"; + const char *global_name1 = "NaN"; + const char *global_name2 = "Infinity"; + WASMGlobalImport *global = &glb; + + EXPECT_FALSE( + wasm_native_lookup_libc_builtin_global(NULL, global_name, global)); + EXPECT_FALSE( + wasm_native_lookup_libc_builtin_global(module_name, NULL, global)); + EXPECT_FALSE( + wasm_native_lookup_libc_builtin_global(module_name, global_name, NULL)); + EXPECT_FALSE(wasm_native_lookup_libc_builtin_global(module_name, + global_name, global)); + EXPECT_FALSE(wasm_native_lookup_libc_builtin_global(module_name, + global_name1, global)); + + EXPECT_TRUE(wasm_native_lookup_libc_builtin_global(module_name1, + global_name1, global)); + + EXPECT_TRUE(wasm_native_lookup_libc_builtin_global(module_name1, + global_name2, global)); +} diff --git a/tests/unit/linear-memory-aot/CMakeLists.txt b/tests/unit/linear-memory-aot/CMakeLists.txt new file mode 100644 index 000000000..549b70ad6 --- /dev/null +++ b/tests/unit/linear-memory-aot/CMakeLists.txt @@ -0,0 +1,78 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-linear-memory-aot) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) +set (WAMR_BUILD_MEMORY_PROFILING 1) +set (WAMR_BUILD_INTERP 0) +set (WAMR_BUILD_AOT 1) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${LIB_HOST_AGENT_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} +) + +# Test case: .aot file with hardware bound check. +add_executable (linear_memory_test_aot ${unit_test_sources}) +target_link_libraries (linear_memory_test_aot gtest_main) +gtest_discover_tests(linear_memory_test_aot) +target_compile_definitions(linear_memory_test_aot PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=0) + +# Ensure that aot compiled is completed before linear_memory_test_aot is built +set(dummy_output "${CMAKE_CURRENT_BINARY_DIR}/dummy_output") + +add_custom_command(OUTPUT ${dummy_output} + COMMAND ./build_aot.sh + COMMAND ${CMAKE_COMMAND} -E touch ${dummy_output} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/build_aot.sh + COMMENT "Executing script to compile aot files" + VERBATIM +) + +add_custom_target( + RunBuildAot ALL + DEPENDS ${dummy_output} +) + +add_dependencies(linear_memory_test_aot RunBuildAot) + +add_custom_command(TARGET linear_memory_test_aot POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/build/*.aot + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copy aot files to the directory: build/linear-memory-aot." +) + +# Test case: .aot file with no hardware bound check. +add_executable (linear_memory_test_aot_no_hw_bound ${unit_test_sources}) +target_link_libraries (linear_memory_test_aot_no_hw_bound gtest_main) +gtest_discover_tests(linear_memory_test_aot_no_hw_bound) +target_compile_definitions(linear_memory_test_aot_no_hw_bound PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=1) diff --git a/tests/unit/linear-memory-aot/build_aot.sh b/tests/unit/linear-memory-aot/build_aot.sh new file mode 100755 index 000000000..8f2b29ede --- /dev/null +++ b/tests/unit/linear-memory-aot/build_aot.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +# Define a list of .wasm files +file_names=("mem_grow_out_of_bounds_01" "mem_grow_out_of_bounds_02" + "mem_page_01" "mem_page_02" "mem_page_03" "mem_page_05" + "mem_page_07" "mem_page_08" "mem_page_09" "mem_page_10" + "mem_page_12" "mem_page_14" "mem_page_16" "mem_page_20" "out_of_bounds") + +WORKDIR="$PWD" +WAMRC_ROOT_DIR="${WORKDIR}/../../../wamr-compiler" +WAMRC="${WAMRC_ROOT_DIR}/build/wamrc" +WAST2WASM="/opt/wabt/bin/wat2wasm" + +# build wamrc if not exist +if [ ! -s "$WAMRC" ]; then + cd $WAMRC_ROOT_DIR + if [ -d "$WAMRC/build" ]; then + rm -r build + fi + cmake -B build && cmake --build build -j $(nproc) + cd $WORKDIR +fi + +# error if not exist +if [ ! -s "$WAST2WASM" ]; then + echo "please install wabt first" && exit -1 +fi + +# Iterate over the files array +rm -r build +mkdir build +for file_name in "${file_names[@]}"; do + # wast to wasm + $WAST2WASM "${file_name}.wast" -o "build/${file_name}.wasm" + # compile the aot files, x86-64, x86-32, no_hw_bounds, no_hw_bounds_x32 + $WAMRC -o "build/${file_name}.aot" "build/${file_name}.wasm" + $WAMRC --target=i386 -o "build/${file_name}_32.aot" "build/${file_name}.wasm" + $WAMRC --bounds-checks=1 -o "build/${file_name}_no_hw_bounds.aot" "build/${file_name}.wasm" + $WAMRC --bounds-checks=1 --target=i386 -o "build/${file_name}_no_hw_bounds_32.aot" "build/${file_name}.wasm" +done diff --git a/tests/unit/linear-memory-aot/linear_memory_aot_test.cc b/tests/unit/linear-memory-aot/linear_memory_aot_test.cc new file mode 100644 index 000000000..dafdbb791 --- /dev/null +++ b/tests/unit/linear-memory-aot/linear_memory_aot_test.cc @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "wasm_runtime_common.h" + +static std::string CWD; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +#if WASM_DISABLE_HW_BOUND_CHECK != 0 +#define TEST_SUITE_NAME linear_memory_test_suite_aot_no_hw_bound +#else +#define TEST_SUITE_NAME linear_memory_test_suite_aot +#endif + +class TEST_SUITE_NAME : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() { CWD = get_binary_path(); } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +struct ret_env { + wasm_exec_env_t exec_env; + wasm_module_t aot_module; + wasm_module_inst_t aot_module_inst; + unsigned char *aot_file_buf; + char error_buf[128]; +}; + +struct ret_env +load_aot(char *aot_file_tested, unsigned int app_heap_size) +{ + std::string aot_mem_page = aot_file_tested; + const char *aot_file = strdup((CWD + aot_mem_page).c_str()); + wasm_module_inst_t aot_module_inst = nullptr; + wasm_module_t aot_module = nullptr; + wasm_exec_env_t exec_env = nullptr; + unsigned char *aot_file_buf = nullptr; + unsigned int aot_file_size = 0; + unsigned int stack_size = 16 * 1024, heap_size = app_heap_size; + char error_buf[128] = { 0 }; + struct ret_env ret_module_env; + + memset(ret_module_env.error_buf, 0, 128); + aot_file_buf = + (unsigned char *)bh_read_file_to_buffer(aot_file, &aot_file_size); + if (!aot_file_buf) { + goto fail; + } + + aot_module = wasm_runtime_load(aot_file_buf, aot_file_size, error_buf, + sizeof(error_buf)); + if (!aot_module) { + memcpy(ret_module_env.error_buf, error_buf, 128); + goto fail; + } + + aot_module_inst = wasm_runtime_instantiate( + aot_module, stack_size, heap_size, error_buf, sizeof(error_buf)); + if (!aot_module_inst) { + memcpy(ret_module_env.error_buf, error_buf, 128); + goto fail; + } + + exec_env = wasm_runtime_create_exec_env(aot_module_inst, stack_size); + +fail: + ret_module_env.exec_env = exec_env; + ret_module_env.aot_module = aot_module; + ret_module_env.aot_module_inst = aot_module_inst; + ret_module_env.aot_file_buf = aot_file_buf; + + return ret_module_env; +} + +void +destroy_module_env(struct ret_env module_env) +{ + if (module_env.exec_env) { + wasm_runtime_destroy_exec_env(module_env.exec_env); + } + + if (module_env.aot_module_inst) { + wasm_runtime_deinstantiate(module_env.aot_module_inst); + } + + if (module_env.aot_module) { + wasm_runtime_unload(module_env.aot_module); + } + + if (module_env.aot_file_buf) { + wasm_runtime_free(module_env.aot_file_buf); + } +} + +TEST_F(TEST_SUITE_NAME, test_aot_mem_page_count) +{ + struct ret_env tmp_module_env; + const unsigned int num_normal_aot = 9; + const unsigned int num_error_aot = 2; + +#if UINTPTR_MAX == UINT64_MAX + const char *aot_file_normal[num_normal_aot] = { + "/mem_page_01.aot", "/mem_page_02.aot", "/mem_page_05.aot", + "/mem_page_07.aot", "/mem_page_08.aot", "/mem_page_09.aot", + "/mem_page_10.aot", "/mem_page_12.aot", "/mem_page_14.aot" + }; + + const char *aot_file_error[num_error_aot] = { "/mem_page_03.aot", + "/mem_page_16.aot" }; +#else + const char *aot_file_normal[num_normal_aot] = { + "/mem_page_01_32.aot", "/mem_page_02_32.aot", "/mem_page_05_32.aot", + "/mem_page_07_32.aot", "/mem_page_08_32.aot", "/mem_page_09_32.aot", + "/mem_page_10_32.aot", "/mem_page_12_32.aot", "/mem_page_14_32.aot" + }; + + const char *aot_file_error[num_error_aot] = { "/mem_page_03_32.aot", + "/mem_page_16_32.aot" }; +#endif + + // Test normal wasm file. + for (int i = 0; i < num_normal_aot; i++) { +#if UINTPTR_MAX != UINT64_MAX + // 32 bit do not load this wasm. + if ((0 == strcmp("/mem_page_14_32.aot", aot_file_normal[i]))) { + continue; + } +#endif + + tmp_module_env = load_aot((char *)aot_file_normal[i], 16 * 1024); + EXPECT_NE(nullptr, tmp_module_env.aot_module); + EXPECT_NE(nullptr, tmp_module_env.aot_file_buf); + + destroy_module_env(tmp_module_env); + } + + // Test error wasm file. + for (int i = 0; i < num_error_aot; i++) { + tmp_module_env = load_aot((char *)aot_file_error[i], 16 * 1024); + if (0 != strlen(tmp_module_env.error_buf)) { + /* 3 and 16 are for legit for loader, the init and max page count + * can be 65536, but they can't allocate any host managed heap, so + * instantiating errors */ + EXPECT_EQ(0, strncmp("AOT module instantiate failed", + (const char *)tmp_module_env.error_buf, 29)); + printf("%s\n", tmp_module_env.error_buf); + } + + destroy_module_env(tmp_module_env); + } +} + +TEST_F(TEST_SUITE_NAME, test_aot_about_app_heap) +{ + struct ret_env tmp_module_env; + + // Test case: init_page_count = 65536, app heap size = 1. +#if UINTPTR_MAX == UINT64_MAX + tmp_module_env = load_aot((char *)"/mem_page_03.aot", 1); +#else + tmp_module_env = load_aot((char *)"/mem_page_03_32.aot", 1); +#endif + EXPECT_EQ( + 0, strncmp("AOT module", (const char *)tmp_module_env.error_buf, 10)); + destroy_module_env(tmp_module_env); + + // Test case: init_page_count = 65535, app heap size = 65537. +#if UINTPTR_MAX == UINT64_MAX + tmp_module_env = load_aot((char *)"/mem_page_20.aot", 65537); +#else + tmp_module_env = load_aot((char *)"/mem_page_20_32.aot", 65537); +#endif + EXPECT_EQ( + 0, strncmp("AOT module", (const char *)tmp_module_env.error_buf, 10)); + destroy_module_env(tmp_module_env); +} + +TEST_F(TEST_SUITE_NAME, test_throw_exception_out_of_bounds) +{ + struct ret_env tmp_module_env; + WASMFunctionInstanceCommon *func = nullptr; + bool ret = false; + uint32 argv[1] = { 9999 * 64 * 1024 }; + const char *exception = nullptr; + + /* TODO: use no_hw_bounds version when disable */ +#if UINTPTR_MAX == UINT64_MAX + tmp_module_env = load_aot((char *)"/out_of_bounds.aot", 16 * 1024); +#else + tmp_module_env = load_aot((char *)"/out_of_bounds_32.aot", 16 * 1024); +#endif + func = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, "load"); + if (!func) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = wasm_runtime_call_wasm(tmp_module_env.exec_env, func, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + } + + exception = wasm_runtime_get_exception(tmp_module_env.aot_module_inst); + EXPECT_EQ(0, + strncmp("Exception: out of bounds memory access", exception, 38)); + +failed_out_of_bounds: + destroy_module_env(tmp_module_env); +} + +TEST_F(TEST_SUITE_NAME, test_mem_grow_out_of_bounds) +{ + struct ret_env tmp_module_env; + WASMFunctionInstanceCommon *func_mem_grow = nullptr; + WASMFunctionInstanceCommon *func_mem_size = nullptr; + bool ret = false; + uint32 argv[1] = { 65535 }; + const char *exception = nullptr; + + /* TODO: use no_hw_bounds version when disable */ + // Test case: module((memory 2)), memory.grow 65535, then memory.size. +#if UINTPTR_MAX == UINT64_MAX + tmp_module_env = load_aot((char *)"/mem_grow_out_of_bounds_01.aot", 0); +#else + tmp_module_env = load_aot((char *)"/mem_grow_out_of_bounds_01_32.aot", 0); +#endif + + func_mem_grow = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, + "mem_grow"); + if (!func_mem_grow) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + func_mem_size = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, + "mem_size"); + if (!func_mem_size) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_EQ(-1, argv[0]); + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_EQ(2, argv[0]); + + // Test case: wasm_runtime_instantiate(heap_size=32768), memory.grow 65534, + // memory.grow 1. + destroy_module_env(tmp_module_env); + +#if UINTPTR_MAX == UINT64_MAX + tmp_module_env = load_aot((char *)"/mem_grow_out_of_bounds_02.aot", 32768); +#else + tmp_module_env = + load_aot((char *)"/mem_grow_out_of_bounds_02_32.aot", 32768); +#endif + + func_mem_grow = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, + "mem_grow"); + if (!func_mem_grow) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + func_mem_size = wasm_runtime_lookup_function(tmp_module_env.aot_module_inst, + "mem_size"); + if (!func_mem_size) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + EXPECT_EQ(2, argv[0]); + + argv[0] = 65534; + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + +#if UINTPTR_MAX == UINT64_MAX + EXPECT_EQ(2, argv[0]); +#else + EXPECT_EQ(-1, argv[0]); +#endif + + argv[0] = 1; + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + +#if UINTPTR_MAX == UINT64_MAX + EXPECT_EQ(-1, argv[0]); +#else + EXPECT_EQ(2, argv[0]); +#endif + +failed_out_of_bounds: + destroy_module_env(tmp_module_env); +} diff --git a/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_01.wast b/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_01.wast new file mode 100644 index 000000000..296455d86 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_01.wast @@ -0,0 +1,16 @@ +(module + (type $0 (func (result i32))) + (type $1 (func (param i32) (result i32))) + (memory 2) + (export "mem_grow" (func $6)) + (export "mem_size" (func $7)) + + (func $6 (type $1) (param $0 i32) (result i32) + local.get $0 + memory.grow + ) + + (func $7 (type $0) (result i32) + memory.size + ) +) diff --git a/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_02.wast b/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_02.wast new file mode 100644 index 000000000..7faceae49 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_grow_out_of_bounds_02.wast @@ -0,0 +1,16 @@ +(module + (type $0 (func (result i32))) + (type $1 (func (param i32) (result i32))) + (memory 1) + (export "mem_grow" (func $6)) + (export "mem_size" (func $7)) + + (func $6 (type $1) (param $0 i32) (result i32) + local.get $0 + memory.grow + ) + + (func $7 (type $0) (result i32) + memory.size + ) +) diff --git a/tests/unit/linear-memory-aot/mem_page_01.wast b/tests/unit/linear-memory-aot/mem_page_01.wast new file mode 100644 index 000000000..aa3aeed76 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_01.wast @@ -0,0 +1 @@ +(module (memory 0)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_02.wast b/tests/unit/linear-memory-aot/mem_page_02.wast new file mode 100644 index 000000000..eb1fba88e --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_02.wast @@ -0,0 +1 @@ +(module (memory 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_03.wast b/tests/unit/linear-memory-aot/mem_page_03.wast new file mode 100644 index 000000000..f3e09dcf4 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_03.wast @@ -0,0 +1 @@ +(module (memory 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_05.wast b/tests/unit/linear-memory-aot/mem_page_05.wast new file mode 100644 index 000000000..7551af514 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_05.wast @@ -0,0 +1 @@ +(module (memory 0 0)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_07.wast b/tests/unit/linear-memory-aot/mem_page_07.wast new file mode 100644 index 000000000..709e6ca05 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_07.wast @@ -0,0 +1 @@ +(module (memory 1 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_08.wast b/tests/unit/linear-memory-aot/mem_page_08.wast new file mode 100644 index 000000000..abf081802 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_08.wast @@ -0,0 +1 @@ +(module (memory 0 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_09.wast b/tests/unit/linear-memory-aot/mem_page_09.wast new file mode 100644 index 000000000..47b38fde5 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_09.wast @@ -0,0 +1 @@ +(module (memory 1 256)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_10.wast b/tests/unit/linear-memory-aot/mem_page_10.wast new file mode 100644 index 000000000..523f9e674 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_10.wast @@ -0,0 +1 @@ +(module (memory 0 65535)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_12.wast b/tests/unit/linear-memory-aot/mem_page_12.wast new file mode 100644 index 000000000..d82dabb59 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_12.wast @@ -0,0 +1 @@ +(module (memory 0 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_14.wast b/tests/unit/linear-memory-aot/mem_page_14.wast new file mode 100644 index 000000000..9779bf234 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_14.wast @@ -0,0 +1 @@ +(module (memory 65535 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_16.wast b/tests/unit/linear-memory-aot/mem_page_16.wast new file mode 100644 index 000000000..94068a4e9 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_16.wast @@ -0,0 +1 @@ +(module (memory 65536 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/mem_page_20.wast b/tests/unit/linear-memory-aot/mem_page_20.wast new file mode 100644 index 000000000..0d4b6ebd6 --- /dev/null +++ b/tests/unit/linear-memory-aot/mem_page_20.wast @@ -0,0 +1 @@ +(module (memory 65535)) \ No newline at end of file diff --git a/tests/unit/linear-memory-aot/out_of_bounds.wast b/tests/unit/linear-memory-aot/out_of_bounds.wast new file mode 100644 index 000000000..89854b924 --- /dev/null +++ b/tests/unit/linear-memory-aot/out_of_bounds.wast @@ -0,0 +1,10 @@ +(module + (type $1 (func (param i32) (result i32))) + (memory $3 0) + (export "load" (func $4)) + + (func $4 (type $1) (param $0 i32) (result i32) + local.get $0 + i32.load + ) +) diff --git a/tests/unit/linear-memory-aot/readme b/tests/unit/linear-memory-aot/readme new file mode 100644 index 000000000..a9ec33833 --- /dev/null +++ b/tests/unit/linear-memory-aot/readme @@ -0,0 +1,2 @@ +build 64 bit target: cmake .. +build 32 bit target: cmake .. -DWAMR_BUILD_TARGET=X86_32 \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/CMakeLists.txt b/tests/unit/linear-memory-wasm/CMakeLists.txt new file mode 100644 index 000000000..03e1616d7 --- /dev/null +++ b/tests/unit/linear-memory-wasm/CMakeLists.txt @@ -0,0 +1,59 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-linear-memory-wasm) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) +set (WAMR_BUILD_MEMORY_PROFILING 1) +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 0) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${LIB_HOST_AGENT_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} +) + +# Test case: .wasm file with hardware bound check. +add_executable (linear_memory_test_wasm ${unit_test_sources}) +target_link_libraries (linear_memory_test_wasm gtest_main) +gtest_discover_tests(linear_memory_test_wasm) +target_compile_definitions(linear_memory_test_wasm PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=0) + +add_custom_command(TARGET linear_memory_test_wasm POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_LIST_DIR}/wasm_files/* + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copy wasm files to the directory: build/linear-memory-wasm." +) + +# Test case: .wasm file with no hardware bound check. +add_executable (linear_memory_test_wasm_no_hw_bound ${unit_test_sources}) +target_link_libraries (linear_memory_test_wasm_no_hw_bound gtest_main) +gtest_discover_tests(linear_memory_test_wasm_no_hw_bound) +target_compile_definitions(linear_memory_test_wasm_no_hw_bound PRIVATE WAMR_DISABLE_HW_BOUND_CHECK=1) diff --git a/tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc b/tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc new file mode 100644 index 000000000..77eb53d7e --- /dev/null +++ b/tests/unit/linear-memory-wasm/linear_memory_wasm_test.cc @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_read_file.h" +#include "wasm_runtime_common.h" + +static std::string CWD; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +#if WASM_DISABLE_HW_BOUND_CHECK != 0 +#define TEST_SUITE_NAME linear_memory_test_suite_wasm_no_hw_bound +#else +#define TEST_SUITE_NAME linear_memory_test_suite_wasm +#endif + +class TEST_SUITE_NAME : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() { CWD = get_binary_path(); } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +struct ret_env { + wasm_exec_env_t exec_env; + wasm_module_t wasm_module; + wasm_module_inst_t wasm_module_inst; + unsigned char *wasm_file_buf; + char error_buf[128]; +}; + +struct ret_env +load_wasm(char *wasm_file_tested, unsigned int app_heap_size) +{ + std::string wasm_mem_page = wasm_file_tested; + const char *wasm_file = strdup((CWD + wasm_mem_page).c_str()); + wasm_module_inst_t wasm_module_inst = nullptr; + wasm_module_t wasm_module = nullptr; + wasm_exec_env_t exec_env = nullptr; + unsigned char *wasm_file_buf = nullptr; + unsigned int wasm_file_size = 0; + unsigned int stack_size = 16 * 1024, heap_size = app_heap_size; + char error_buf[128] = { 0 }; + struct ret_env ret_module_env; + + memset(ret_module_env.error_buf, 0, 128); + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + if (!wasm_file_buf) { + goto fail; + } + + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + if (!wasm_module) { + memcpy(ret_module_env.error_buf, error_buf, 128); + goto fail; + } + + wasm_module_inst = wasm_runtime_instantiate( + wasm_module, stack_size, heap_size, error_buf, sizeof(error_buf)); + if (!wasm_module_inst) { + memcpy(ret_module_env.error_buf, error_buf, 128); + goto fail; + } + + exec_env = wasm_runtime_create_exec_env(wasm_module_inst, stack_size); + +fail: + ret_module_env.exec_env = exec_env; + ret_module_env.wasm_module = wasm_module; + ret_module_env.wasm_module_inst = wasm_module_inst; + ret_module_env.wasm_file_buf = wasm_file_buf; + + return ret_module_env; +} + +void +destroy_module_env(struct ret_env module_env) +{ + if (module_env.exec_env) { + wasm_runtime_destroy_exec_env(module_env.exec_env); + } + + if (module_env.wasm_module_inst) { + wasm_runtime_deinstantiate(module_env.wasm_module_inst); + } + + if (module_env.wasm_module) { + wasm_runtime_unload(module_env.wasm_module); + } + + if (module_env.wasm_file_buf) { + wasm_runtime_free(module_env.wasm_file_buf); + } +} + +TEST_F(TEST_SUITE_NAME, test_wasm_mem_page_count) +{ + struct ret_env tmp_module_env; + unsigned int num_normal_wasm = 9; + unsigned int num_error_wasm = 10; + const char *wasm_file_normal[num_normal_wasm] = { + "/wasm_mem_page_01.wasm", "/wasm_mem_page_02.wasm", + "/wasm_mem_page_05.wasm", "/wasm_mem_page_07.wasm", + "/wasm_mem_page_08.wasm", "/wasm_mem_page_09.wasm", + "/wasm_mem_page_10.wasm", "/wasm_mem_page_12.wasm", + "/wasm_mem_page_14.wasm" + }; + + const char *wasm_file_error[num_error_wasm] = { + "/wasm_mem_page_03.wasm", "/wasm_mem_page_04.wasm", + "/wasm_mem_page_06.wasm", "/wasm_mem_page_11.wasm", + "/wasm_mem_page_13.wasm", "/wasm_mem_page_15.wasm", + "/wasm_mem_page_16.wasm", "/wasm_mem_page_17.wasm", + "/wasm_mem_page_18.wasm", "/wasm_mem_page_19.wasm" + }; + + // Test normal wasm file. + for (int i = 0; i < num_normal_wasm; i++) { +#if UINTPTR_MAX != UINT64_MAX + // 32 bit do not load this wasm. + if ((0 == strcmp("/wasm_mem_page_12.wasm", wasm_file_normal[i])) + || (0 == strcmp("/wasm_mem_page_14.wasm", wasm_file_normal[i]))) { + continue; + } +#endif + tmp_module_env = load_wasm((char *)wasm_file_normal[i], 16 * 1024); + EXPECT_NE(nullptr, tmp_module_env.wasm_module); + EXPECT_NE(nullptr, tmp_module_env.wasm_file_buf); + +#if WASM_DISABLE_HW_BOUND_CHECK == 0 + EXPECT_NE(nullptr, tmp_module_env.exec_env); + EXPECT_NE(nullptr, tmp_module_env.wasm_module_inst); +#endif + destroy_module_env(tmp_module_env); + } + + // Test error wasm file. + for (int i = 0; i < num_error_wasm; i++) { + tmp_module_env = load_wasm((char *)wasm_file_error[i], 16 * 1024); + + if (0 != strlen(tmp_module_env.error_buf)) { + EXPECT_EQ(0, strncmp("WASM module", + (const char *)tmp_module_env.error_buf, 11)); + } + + destroy_module_env(tmp_module_env); + } +} + +TEST_F(TEST_SUITE_NAME, test_wasm_about_app_heap) +{ + struct ret_env tmp_module_env; + + // Test case: init_page_count = 65536, app heap size = 1. + tmp_module_env = load_wasm((char *)"/wasm_mem_page_03.wasm", 1); + EXPECT_EQ(0, strncmp("WASM module instantiate failed", + (const char *)tmp_module_env.error_buf, 30)); + destroy_module_env(tmp_module_env); + + // Test case: init_page_count = 65535, app heap size = 65537. + tmp_module_env = load_wasm((char *)"/wasm_mem_page_20.wasm", 65537); + EXPECT_EQ(0, strncmp("WASM module instantiate failed", + (const char *)tmp_module_env.error_buf, 30)); + destroy_module_env(tmp_module_env); +} + +TEST_F(TEST_SUITE_NAME, test_throw_exception_out_of_bounds) +{ + struct ret_env tmp_module_env; + WASMFunctionInstanceCommon *func = nullptr; + bool ret = false; + uint32 argv[1] = { 9999 * 64 * 1024 }; + const char *exception = nullptr; + + tmp_module_env = load_wasm((char *)"/out_of_bounds.wasm", 16 * 1024); + func = + wasm_runtime_lookup_function(tmp_module_env.wasm_module_inst, "load"); + if (!func) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = wasm_runtime_call_wasm(tmp_module_env.exec_env, func, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + } + + exception = wasm_runtime_get_exception(tmp_module_env.wasm_module_inst); + EXPECT_EQ(0, + strncmp("Exception: out of bounds memory access", exception, 38)); + +failed_out_of_bounds: + destroy_module_env(tmp_module_env); +} + +TEST_F(TEST_SUITE_NAME, test_mem_grow_out_of_bounds) +{ + struct ret_env tmp_module_env; + WASMFunctionInstanceCommon *func_mem_grow = nullptr; + WASMFunctionInstanceCommon *func_mem_size = nullptr; + bool ret = false; + // after refactor, the 65536 pages to one 4G page optimization is removed + // the size can be 65536 now, so use 2 + 65535 to test OOB + uint32 argv[1] = { 65535 }; + const char *exception = nullptr; + + // Test case: module((memory 2)), memory.grow 65535, then memory.size. + tmp_module_env = load_wasm((char *)"/mem_grow_out_of_bounds_01.wasm", 0); + func_mem_grow = wasm_runtime_lookup_function( + tmp_module_env.wasm_module_inst, "mem_grow"); + if (!func_mem_grow) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + func_mem_size = wasm_runtime_lookup_function( + tmp_module_env.wasm_module_inst, "mem_size"); + if (!func_mem_size) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_EQ(-1, argv[0]); + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_EQ(2, argv[0]); + + // Test case: wasm_runtime_instantiate(heap_size=32768), memory.grow 65535, + // memory.grow 1. + destroy_module_env(tmp_module_env); + tmp_module_env = + load_wasm((char *)"/mem_grow_out_of_bounds_02.wasm", 32768); + func_mem_grow = wasm_runtime_lookup_function( + tmp_module_env.wasm_module_inst, "mem_grow"); + if (!func_mem_grow) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + func_mem_size = wasm_runtime_lookup_function( + tmp_module_env.wasm_module_inst, "mem_size"); + if (!func_mem_size) { + printf("\nFailed to wasm_runtime_lookup_function!\n"); + goto failed_out_of_bounds; + } + + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_size, 0, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + EXPECT_EQ(2, argv[0]); + + argv[0] = 65535; + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_NE(2, argv[0]); + + argv[0] = 1; + ret = + wasm_runtime_call_wasm(tmp_module_env.exec_env, func_mem_grow, 1, argv); + if (!ret) { + printf("\nFailed to wasm_runtime_call_wasm!\n"); + goto failed_out_of_bounds; + } + + EXPECT_EQ(2, argv[0]); + +failed_out_of_bounds: + destroy_module_env(tmp_module_env); +} diff --git a/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_01.wast b/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_01.wast new file mode 100644 index 000000000..296455d86 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_01.wast @@ -0,0 +1,16 @@ +(module + (type $0 (func (result i32))) + (type $1 (func (param i32) (result i32))) + (memory 2) + (export "mem_grow" (func $6)) + (export "mem_size" (func $7)) + + (func $6 (type $1) (param $0 i32) (result i32) + local.get $0 + memory.grow + ) + + (func $7 (type $0) (result i32) + memory.size + ) +) diff --git a/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_02.wast b/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_02.wast new file mode 100644 index 000000000..7faceae49 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_grow_out_of_bounds_02.wast @@ -0,0 +1,16 @@ +(module + (type $0 (func (result i32))) + (type $1 (func (param i32) (result i32))) + (memory 1) + (export "mem_grow" (func $6)) + (export "mem_size" (func $7)) + + (func $6 (type $1) (param $0 i32) (result i32) + local.get $0 + memory.grow + ) + + (func $7 (type $0) (result i32) + memory.size + ) +) diff --git a/tests/unit/linear-memory-wasm/mem_page_01.wast b/tests/unit/linear-memory-wasm/mem_page_01.wast new file mode 100644 index 000000000..aa3aeed76 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_01.wast @@ -0,0 +1 @@ +(module (memory 0)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_02.wast b/tests/unit/linear-memory-wasm/mem_page_02.wast new file mode 100644 index 000000000..eb1fba88e --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_02.wast @@ -0,0 +1 @@ +(module (memory 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_03.wast b/tests/unit/linear-memory-wasm/mem_page_03.wast new file mode 100644 index 000000000..f3e09dcf4 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_03.wast @@ -0,0 +1 @@ +(module (memory 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_04.wast b/tests/unit/linear-memory-wasm/mem_page_04.wast new file mode 100644 index 000000000..b476caa2e --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_04.wast @@ -0,0 +1 @@ +(module (memory 65537)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_05.wast b/tests/unit/linear-memory-wasm/mem_page_05.wast new file mode 100644 index 000000000..7551af514 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_05.wast @@ -0,0 +1 @@ +(module (memory 0 0)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_06.wast b/tests/unit/linear-memory-wasm/mem_page_06.wast new file mode 100644 index 000000000..eae97baa2 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_06.wast @@ -0,0 +1 @@ +(module (memory 1 0)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_07.wast b/tests/unit/linear-memory-wasm/mem_page_07.wast new file mode 100644 index 000000000..709e6ca05 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_07.wast @@ -0,0 +1 @@ +(module (memory 1 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_08.wast b/tests/unit/linear-memory-wasm/mem_page_08.wast new file mode 100644 index 000000000..abf081802 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_08.wast @@ -0,0 +1 @@ +(module (memory 0 1)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_09.wast b/tests/unit/linear-memory-wasm/mem_page_09.wast new file mode 100644 index 000000000..47b38fde5 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_09.wast @@ -0,0 +1 @@ +(module (memory 1 256)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_10.wast b/tests/unit/linear-memory-wasm/mem_page_10.wast new file mode 100644 index 000000000..523f9e674 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_10.wast @@ -0,0 +1 @@ +(module (memory 0 65535)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_11.wast b/tests/unit/linear-memory-wasm/mem_page_11.wast new file mode 100644 index 000000000..1d9cf77cf --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_11.wast @@ -0,0 +1 @@ +(module (memory 65535 0)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_12.wast b/tests/unit/linear-memory-wasm/mem_page_12.wast new file mode 100644 index 000000000..d82dabb59 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_12.wast @@ -0,0 +1 @@ +(module (memory 0 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_13.wast b/tests/unit/linear-memory-wasm/mem_page_13.wast new file mode 100644 index 000000000..e3c1f1e21 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_13.wast @@ -0,0 +1 @@ +(module (memory 65536 0)) ;; Should report an error. diff --git a/tests/unit/linear-memory-wasm/mem_page_14.wast b/tests/unit/linear-memory-wasm/mem_page_14.wast new file mode 100644 index 000000000..9779bf234 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_14.wast @@ -0,0 +1 @@ +(module (memory 65535 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_15.wast b/tests/unit/linear-memory-wasm/mem_page_15.wast new file mode 100644 index 000000000..d2862b9bb --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_15.wast @@ -0,0 +1 @@ +(module (memory 65536 65535)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_16.wast b/tests/unit/linear-memory-wasm/mem_page_16.wast new file mode 100644 index 000000000..94068a4e9 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_16.wast @@ -0,0 +1 @@ +(module (memory 65536 65536)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_17.wast b/tests/unit/linear-memory-wasm/mem_page_17.wast new file mode 100644 index 000000000..d5a19eff2 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_17.wast @@ -0,0 +1 @@ +(module (memory 65537 65537)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_18.wast b/tests/unit/linear-memory-wasm/mem_page_18.wast new file mode 100644 index 000000000..d5793de6a --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_18.wast @@ -0,0 +1 @@ +(module (memory 65537 65535)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_19.wast b/tests/unit/linear-memory-wasm/mem_page_19.wast new file mode 100644 index 000000000..8cf0a39f6 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_19.wast @@ -0,0 +1 @@ +(module (memory 65535 65537)) ;; Should report an error. \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/mem_page_20.wast b/tests/unit/linear-memory-wasm/mem_page_20.wast new file mode 100644 index 000000000..0d4b6ebd6 --- /dev/null +++ b/tests/unit/linear-memory-wasm/mem_page_20.wast @@ -0,0 +1 @@ +(module (memory 65535)) \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/out_of_bounds.wast b/tests/unit/linear-memory-wasm/out_of_bounds.wast new file mode 100644 index 000000000..89854b924 --- /dev/null +++ b/tests/unit/linear-memory-wasm/out_of_bounds.wast @@ -0,0 +1,10 @@ +(module + (type $1 (func (param i32) (result i32))) + (memory $3 0) + (export "load" (func $4)) + + (func $4 (type $1) (param $0 i32) (result i32) + local.get $0 + i32.load + ) +) diff --git a/tests/unit/linear-memory-wasm/readme b/tests/unit/linear-memory-wasm/readme new file mode 100644 index 000000000..a9ec33833 --- /dev/null +++ b/tests/unit/linear-memory-wasm/readme @@ -0,0 +1,2 @@ +build 64 bit target: cmake .. +build 32 bit target: cmake .. -DWAMR_BUILD_TARGET=X86_32 \ No newline at end of file diff --git a/tests/unit/linear-memory-wasm/wasm_files/mem_grow_out_of_bounds_01.wasm b/tests/unit/linear-memory-wasm/wasm_files/mem_grow_out_of_bounds_01.wasm new file mode 100644 index 0000000000000000000000000000000000000000..544ed91e81f24415ebe3b31d49ba258fbcd97e73 GIT binary patch literal 70 zcmZQbEY4+QU|?Y6VoG3OtWRL9XRK#tW@2PuWoBexVi#xP$W6_SPcO literal 0 HcmV?d00001 diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_02.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_02.wasm new file mode 100644 index 0000000000000000000000000000000000000000..67d6849c74838975793d0355a2fcc483d91b53ef GIT binary patch literal 13 UcmZQbEY4+QU|?WnW@KOl01f^DO#lD@ literal 0 HcmV?d00001 diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_03.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_03.wasm new file mode 100644 index 0000000000000000000000000000000000000000..5c82427261437804479ea013acb216837af33b1a GIT binary patch literal 15 WcmZQbEY4+QU|?WnWn^e*U;zLVB?3|a literal 0 HcmV?d00001 diff --git a/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_04.wasm b/tests/unit/linear-memory-wasm/wasm_files/wasm_mem_page_04.wasm new file mode 100644 index 0000000000000000000000000000000000000000..6f2d7eb15e502576a113677b03ef203ffc7f7ec6 GIT binary patch literal 15 WcmZQbEY4+QU|?WnWn^e +#include +#include + +extern "C" { +// TODO: won't work, for non static function create_perf_map have goto statement jump to label ‘quit’ +// #include "aot_perf_map.c" + +// simply copy the function +struct func_info { + uint32 idx; + void *ptr; +}; + +static int +compare_func_ptrs(const void *f1, const void *f2) +{ + return (intptr_t)((struct func_info *)f1)->ptr + - (intptr_t)((struct func_info *)f2)->ptr; +} + +static struct func_info * +sort_func_ptrs(const AOTModule *module, char *error_buf, uint32 error_buf_size) +{ + uint64 content_len; + struct func_info *sorted_func_ptrs; + unsigned i; + + content_len = (uint64)sizeof(struct func_info) * module->func_count; + sorted_func_ptrs = wasm_runtime_malloc(content_len); + if (!sorted_func_ptrs) { + snprintf(error_buf, error_buf_size, + "allocate memory failed when creating perf map"); + return NULL; + } + + for (i = 0; i < module->func_count; i++) { + sorted_func_ptrs[i].idx = i; + sorted_func_ptrs[i].ptr = module->func_ptrs[i]; + } + + qsort(sorted_func_ptrs, module->func_count, sizeof(struct func_info), + compare_func_ptrs); + + return sorted_func_ptrs; +} + +void * +wasm_runtime_malloc(unsigned int size) +{ + return malloc(size); +} + +void +wasm_runtime_free(void* ptr) +{ + return free(ptr); +} + +int +b_memcpy_s(void *s1, unsigned int s1max, const void *s2, unsigned int n) +{ + return memcpy(s1, s2, n); +} +} + +TEST(TestSortFuncPtrs, qsort) +{ + void *p = sort_func_ptrs; + ASSERT_NE(p, nullptr); + + void *funcs[5] = { + (void *)0x1024, (void *)0x10, (void *)0x24, (void *)0x102, (void *)0x4, + }; + + AOTModule module = { 0 }; + module.func_count = 5; + module.func_ptrs = &funcs[0]; + + char buf[64] = { 0 }; + + struct func_info *sorted_funcs = sort_func_ptrs(&module, buf, 64); + // sorted + ASSERT_EQ((uintptr_t)(sorted_funcs[0].ptr), 0x4); + ASSERT_EQ((uintptr_t)(sorted_funcs[1].ptr), 0x10); + ASSERT_EQ((uintptr_t)(sorted_funcs[2].ptr), 0x24); + ASSERT_EQ((uintptr_t)(sorted_funcs[3].ptr), 0x102); + ASSERT_EQ((uintptr_t)(sorted_funcs[4].ptr), 0x1024); + + ASSERT_EQ(sorted_funcs[0].idx, 4); + ASSERT_EQ(sorted_funcs[1].idx, 1); + ASSERT_EQ(sorted_funcs[2].idx, 2); + ASSERT_EQ(sorted_funcs[3].idx, 3); + ASSERT_EQ(sorted_funcs[4].idx, 0); + + // don't change input + ASSERT_EQ((uintptr_t)(funcs[0]), 0x1024); + ASSERT_EQ((uintptr_t)(funcs[1]), 0x10); + ASSERT_EQ((uintptr_t)(funcs[2]), 0x24); + ASSERT_EQ((uintptr_t)(funcs[3]), 0x102); + ASSERT_EQ((uintptr_t)(funcs[4]), 0x4); + + wasm_runtime_free(sorted_funcs); +} \ No newline at end of file diff --git a/tests/unit/memory64/CMakeLists.txt b/tests/unit/memory64/CMakeLists.txt new file mode 100644 index 000000000..f3629a7c4 --- /dev/null +++ b/tests/unit/memory64/CMakeLists.txt @@ -0,0 +1,67 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.14) + +project(test-memory64) + +add_definitions(-DRUN_ON_LINUX) + +set(WAMR_BUILD_LIBC_WASI 1) +set(WAMR_BUILD_APP_FRAMEWORK 0) +# TODO: Currently only support classic interpreter mode +set(WAMR_BUILD_AOT 0) +set(WAMR_BUILD_INTERP 1) +set(WAMR_BUILD_FAST_INTERP 0) +set(WAMR_BUILD_JIT 0) +set(WAMR_BUILD_FAST_JIT 0) +set(WAMR_BUILD_MEMORY64 1) +set(WAMR_BUILD_SHARED_MEMORY 1) + +# if only load this CMake other than load it as subdirectory +# include(GoogleTest) +include(../unit_common.cmake) + +set(LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") + +if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message(FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif () + +set(CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include(${IWASM_DIR}/compilation/iwasm_compl.cmake) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +file(GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set(UNIT_SOURCE ${source_all}) + +aux_source_directory(. SRC_LIST) + +set(unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} + ) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable(memory64_test ${unit_test_sources}) + +target_link_libraries(memory64_test ${LLVM_AVAILABLE_LIBS} gtest_main) + +add_custom_command(TARGET memory64_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps/*.wasm + ${CMAKE_CURRENT_BINARY_DIR}/ + COMMENT "Copy test wasm files to the directory of google test" + ) + +gtest_discover_tests(memory64_test) diff --git a/tests/unit/memory64/memory64_atomic_test.cc b/tests/unit/memory64/memory64_atomic_test.cc new file mode 100644 index 000000000..2f9703890 --- /dev/null +++ b/tests/unit/memory64/memory64_atomic_test.cc @@ -0,0 +1,355 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "memory64_common.h" + +// To use a test fixture and Value Parameterized Tests, +// derive a class from testing::TestWithParam. +class memory64_atomic_test_suite : public testing::TestWithParam +{ + protected: + bool load_wasm_file(const char *wasm_file) + { + const char *file; + unsigned char *wasm_file_buf; + uint32 wasm_file_size; + + file = wasm_file; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size); + if (!wasm_file_buf) + goto fail; + + if (!(module = wasm_runtime_load(wasm_file_buf, wasm_file_size, + error_buf, sizeof(error_buf)))) { + printf("Load wasm module failed. error: %s\n", error_buf); + goto fail; + } + return true; + + fail: + if (!module) + wasm_runtime_unload(module); + + return false; + } + + bool init_exec_env() + { + if (!(module_inst = + wasm_runtime_instantiate(module, stack_size, heap_size, + error_buf, sizeof(error_buf)))) { + printf("Instantiate wasm module failed. error: %s\n", error_buf); + goto fail; + } + if (!(exec_env = + wasm_runtime_create_exec_env(module_inst, stack_size))) { + printf("Create wasm execution environment failed.\n"); + goto fail; + } + return true; + + fail: + if (exec_env) + wasm_runtime_destroy_exec_env(exec_env); + if (module_inst) + wasm_runtime_unload(module); + return false; + } + + void destory_exec_env() + { + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + } + + public: + // If your test fixture defines SetUpTestSuite() or TearDownTestSuite() + // they must be declared public rather than protected in order to use + // TEST_P. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the variables. + // Otherwise, this can be skipped. + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + ASSERT_TRUE(load_wasm_file("atomic_opcodes.wasm")); + ASSERT_TRUE(init_exec_env()); + + running_mode = GetParam(); + ASSERT_TRUE(wasm_runtime_set_running_mode(module_inst, running_mode)); + ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst)); + + for (auto &iter : func_map) { + iter.second = + wasm_runtime_lookup_function(module_inst, iter.first.c_str()); + ASSERT_TRUE(iter.second != NULL); + } + + cleanup = true; + } + + static void SetUpTestCase() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() + { + if (cleanup) { + destory_exec_env(); + wasm_runtime_destroy(); + cleanup = false; + } + } + + static void TearDownTestCase() {} + + RuntimeInitArgs init_args; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_exec_env_t exec_env = NULL; + RunningMode running_mode; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + uint32_t stack_size = 8092, heap_size = 8092; + bool cleanup = true; + std::unordered_map func_map = { + { "i32_atomic_store", nullptr }, + { "i32_atomic_store8", nullptr }, + { "i32_atomic_store16", nullptr }, + { "i64_atomic_store", nullptr }, + { "i64_atomic_store8", nullptr }, + { "i64_atomic_store16", nullptr }, + { "i64_atomic_store32", nullptr }, + { "i32_atomic_load", nullptr }, + { "i32_atomic_load8_u", nullptr }, + { "i32_atomic_load16_u", nullptr }, + { "i64_atomic_load", nullptr }, + { "i64_atomic_load8_u", nullptr }, + { "i64_atomic_load16_u", nullptr }, + { "i64_atomic_load32_u", nullptr }, + { "i32_atomic_rmw_add", nullptr }, + { "i32_atomic_rmw8_add_u", nullptr }, + { "i32_atomic_rmw16_add_u", nullptr }, + { "i64_atomic_rmw_add", nullptr }, + { "i64_atomic_rmw8_add_u", nullptr }, + { "i64_atomic_rmw16_add_u", nullptr }, + { "i64_atomic_rmw32_add_u", nullptr }, + { "i64_atomic_rmw_cmpxchg", nullptr }, + }; + uint32_t wasm_argv[6], i32; + uint64_t i64; +}; + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_st) +{ + // store at 0x2000, with value 0xbeefdead + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xcafedeadbeefdead); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + // check return value: 0xcafedeadbeefdead:i64 + i64 = 0xcafedeadbeefdead; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + // store at 0x2000, with value 0xbeefbeef + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xdeadbeef); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store32"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + // check return value: 0xcafedeaddeadbeef:i64 + i64 = 0xcafedeaddeadbeef; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + // store at 0x2000, with value 0xcafe + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xcafe); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store16"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + // check return value: 0xcafedeaddeadcafe:i64 + i64 = 0xcafedeaddeadcafe; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + // store at 0x2000, with value 0xcafe + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xaa); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store8"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + // check return value: 0xcafedeaddeadcaaa:i64 + i64 = 0xcafedeaddeadcaaa; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); +} + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i32_st) +{ + // store at 0x1000, with value 0xbeefbeef + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xaabbccdd); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_store"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2, + wasm_argv)); + // check return value: 0xaabbccdd:i32 + i32 = 0xaabbccdd; + ASSERT_EQ(i32, wasm_argv[0]); + + // store at 0x1000, with value 0xcafe + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xcafe); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_store16"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2, + wasm_argv)); + // check return value: 0xaabbcafe:i32 + i32 = 0xaabbcafe; + ASSERT_EQ(i32, wasm_argv[0]); + + PUT_I64_TO_ADDR(wasm_argv, 0x2000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xaa); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_store8"], + 4, wasm_argv)); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2, + wasm_argv)); + // check return value: 0xaabbcaaa:i32 + i32 = 0xaabbcaaa; + ASSERT_EQ(i32, wasm_argv[0]); +} + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_ld) +{ + // from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10 + PUT_I64_TO_ADDR(wasm_argv, 0x0); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + // check return value: 0x0807060504030201:i64 + i64 = 0x0807060504030201; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i64_atomic_load32_u"], 2, wasm_argv)); + // check return value: 0x0C0B0A09:i64 + i64 = 0x0C0B0A09; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i64_atomic_load16_u"], 2, wasm_argv)); + // check return value: 0x0A09:i64 + i64 = 0x0A09; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x0A); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load8_u"], + 2, wasm_argv)); + // check return value: 0x0B:i64 + i64 = 0x0B; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); +} + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i32_ld) +{ + // from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10 + PUT_I64_TO_ADDR(wasm_argv, 0x0); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2, + wasm_argv)); + // check return value: 0x04030201:i32 + i32 = 0x04030201; + ASSERT_EQ(i32, wasm_argv[0]); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i32_atomic_load16_u"], 2, wasm_argv)); + // check return value: 0x0A09:i32 + i32 = 0x0A09; + ASSERT_EQ(i32, wasm_argv[0]); + + PUT_I64_TO_ADDR(wasm_argv, 0xA); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load8_u"], + 2, wasm_argv)); + // check return value: 0x0B:i32 + i32 = 0x0B; + ASSERT_EQ(i32, wasm_argv[0]); +} + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_rmw_add) +{ + // from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10 + PUT_I64_TO_ADDR(wasm_argv, 0x8); + PUT_I64_TO_ADDR(wasm_argv + 2, 0x1010101020202020); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_rmw_add"], + 4, wasm_argv)); + i64 = 0x100F0E0D0C0B0A09; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + PUT_I64_TO_ADDR(wasm_argv + 2, 0x10103030); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i64_atomic_rmw32_add_u"], 4, wasm_argv)); + i64 = 0x2C2B2A29; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + PUT_I64_TO_ADDR(wasm_argv + 2, 0x1020); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i64_atomic_rmw16_add_u"], 4, wasm_argv)); + i64 = 0x5A59; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + PUT_I64_TO_ADDR(wasm_argv + 2, 0x30); + ASSERT_TRUE(wasm_runtime_call_wasm( + exec_env, func_map["i64_atomic_rmw8_add_u"], 4, wasm_argv)); + i64 = 0x79; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + i64 = 0x201F1E1D3C3B6AA9; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); +} + +TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_rmw_cmpxchg) +{ + // from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10 + PUT_I64_TO_ADDR(wasm_argv, 0x8); + // old + PUT_I64_TO_ADDR(wasm_argv + 2, 0x100F0E0D0C0B0A09); + // new + PUT_I64_TO_ADDR(wasm_argv + 4, 0xdeadcafebeefdead); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_rmw_cmpxchg"], + 6, wasm_argv)); + i64 = 0x100F0E0D0C0B0A09; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + PUT_I64_TO_ADDR(wasm_argv, 0x8); + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2, + wasm_argv)); + i64 = 0xdeadcafebeefdead; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); +} + +INSTANTIATE_TEST_CASE_P(RunningMode, memory64_atomic_test_suite, + testing::ValuesIn(running_mode_supported)); diff --git a/tests/unit/memory64/memory64_common.h b/tests/unit/memory64/memory64_common.h new file mode 100644 index 000000000..76c43a8e7 --- /dev/null +++ b/tests/unit/memory64/memory64_common.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef UNIT_TEST_MEMORY64_COMMON_H +#define UNIT_TEST_MEMORY64_COMMON_H + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "platform_common.h" +#include "wasm_runtime_common.h" +#include "bh_read_file.h" +#include "wasm_runtime.h" +#include "bh_platform.h" +#include "wasm_export.h" +#include +// #include "aot_runtime.h" + +namespace { + +std::vector running_mode_supported = { Mode_Interp, +#if WASM_ENABLE_FAST_JIT != 0 + Mode_Fast_JIT, +#endif +#if WASM_ENABLE_JIT != 0 + Mode_LLVM_JIT, +#endif +#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + Mode_Multi_Tier_JIT +#endif +}; + +static inline uint64 +GET_U64_FROM_ADDR(uint32 *addr) +{ + union { + uint64 val; + uint32 parts[2]; + } u; + u.parts[0] = addr[0]; + u.parts[1] = addr[1]; + return u.val; +} + +static inline void +PUT_U64_TO_ADDR(uint32 *addr, uint64 value) +{ + uint32 *addr_u32 = (uint32 *)(addr); + union { + float64 val; + uint32 parts[2]; + } u; + u.val = (value); + addr_u32[0] = u.parts[0]; + addr_u32[1] = u.parts[1]; +} + +} + +#endif // UNIT_TEST_MEMORY64_COMMON_H diff --git a/tests/unit/memory64/memory64_test.cc b/tests/unit/memory64/memory64_test.cc new file mode 100644 index 000000000..67315a594 --- /dev/null +++ b/tests/unit/memory64/memory64_test.cc @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "memory64_common.h" + +// To use a test fixture and Value Parameterized Tests, +// derive a class from testing::TestWithParam. +class memory64_test_suite : public testing::TestWithParam +{ + protected: + bool load_wasm_file(const char *wasm_file) + { + const char *file; + unsigned char *wasm_file_buf; + uint32 wasm_file_size; + + file = wasm_file; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size); + if (!wasm_file_buf) + goto fail; + + if (!(module = wasm_runtime_load(wasm_file_buf, wasm_file_size, + error_buf, sizeof(error_buf)))) { + printf("Load wasm module failed. error: %s\n", error_buf); + goto fail; + } + return true; + + fail: + if (!module) + wasm_runtime_unload(module); + + return false; + } + + bool init_exec_env() + { + if (!(module_inst = + wasm_runtime_instantiate(module, stack_size, heap_size, + error_buf, sizeof(error_buf)))) { + printf("Instantiate wasm module failed. error: %s\n", error_buf); + goto fail; + } + if (!(exec_env = + wasm_runtime_create_exec_env(module_inst, stack_size))) { + printf("Create wasm execution environment failed.\n"); + goto fail; + } + return true; + + fail: + if (exec_env) + wasm_runtime_destroy_exec_env(exec_env); + if (module_inst) + wasm_runtime_unload(module); + return false; + } + + void destory_exec_env() + { + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + } + + public: + // If your test fixture defines SetUpTestSuite() or TearDownTestSuite() + // they must be declared public rather than protected in order to use + // TEST_P. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + + cleanup = true; + } + + static void SetUpTestCase() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() + { + if (cleanup) { + wasm_runtime_destroy(); + cleanup = false; + } + } + + static void TearDownTestCase() {} + + RuntimeInitArgs init_args; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_exec_env_t exec_env = NULL; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + uint32_t stack_size = 8092, heap_size = 8092; + bool cleanup = true; +}; + +TEST_F(memory64_test_suite, wasm_runtime_is_running_mode_supported) +{ + // TODO: make sure the chosen running mode option is compiled, for memory64, + // currently only support classic interp mode + ASSERT_EQ(true, wasm_runtime_is_running_mode_supported( + static_cast(Mode_Default))); + for (auto running_mode : running_mode_supported) { + ASSERT_EQ(true, wasm_runtime_is_running_mode_supported(running_mode)); + } +} + +TEST_F(memory64_test_suite, page_exceed_u32_1) +{ + bool ret; + ret = load_wasm_file("page_exceed_u32.wasm"); + ASSERT_FALSE(ret); + ASSERT_TRUE(strcmp("WASM module load failed: integer too large", error_buf) + == 0); +} + +TEST_F(memory64_test_suite, page_exceed_u32_2) +{ + bool ret; + ret = load_wasm_file("page_exceed_u32_2.wasm"); + ASSERT_FALSE(ret); + ASSERT_TRUE(strcmp("WASM module load failed: integer too large", error_buf) + == 0); +} + +TEST_F(memory64_test_suite, page_u32_max) +{ + bool ret; + ret = load_wasm_file("page_u32_max.wasm"); + ASSERT_TRUE(ret); +} + +TEST_P(memory64_test_suite, memory_8GB) +{ + RunningMode running_mode = GetParam(); + wasm_function_inst_t touch_every_page_func, i64_store_offset_4GB, + i64_load_offset_4GB; + uint32_t wasm_argv[6], i32; + uint64_t i64; + bool ret; + + ret = load_wasm_file("8GB_memory.wasm"); + ASSERT_TRUE(ret); + ret = init_exec_env(); + ASSERT_TRUE(ret); + + ret = wasm_runtime_set_running_mode(module_inst, running_mode); + ASSERT_TRUE(ret); + ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst)); + + touch_every_page_func = + wasm_runtime_lookup_function(module_inst, "touch_every_page"); + ASSERT_TRUE(touch_every_page_func != NULL); + ret = wasm_runtime_call_wasm(exec_env, touch_every_page_func, 0, wasm_argv); + ASSERT_TRUE(ret); + // check return value: 0xfff8:i64,0x10000fff8:i64,0x1fff8:i32,0x1:i32 + i64 = 0xfff8; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + i64 = 0x10000fff8; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv + 2)); + i32 = 0x1fff8; + ASSERT_EQ(i32, wasm_argv[4]); + i32 = 0x1; + ASSERT_EQ(i32, wasm_argv[5]); + + // store at 0x100001000, with value 0xbeefdead + PUT_I64_TO_ADDR(wasm_argv, 0x1000); + PUT_I64_TO_ADDR(wasm_argv + 2, 0xbeefdead); + i64_store_offset_4GB = + wasm_runtime_lookup_function(module_inst, "i64_store_offset_4GB"); + ASSERT_TRUE(i64_store_offset_4GB != NULL); + ret = wasm_runtime_call_wasm(exec_env, i64_store_offset_4GB, 4, wasm_argv); + ASSERT_TRUE(ret); + + i64_load_offset_4GB = + wasm_runtime_lookup_function(module_inst, "i64_load_offset_4GB"); + ASSERT_TRUE(i64_load_offset_4GB != NULL); + ret = wasm_runtime_call_wasm(exec_env, i64_load_offset_4GB, 2, wasm_argv); + ASSERT_TRUE(ret); + // check return value: 0xbeefdead:i64 + i64 = 0xbeefdead; + ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv)); + + destory_exec_env(); +} + +TEST_P(memory64_test_suite, mem64_from_clang) +{ + RunningMode running_mode = GetParam(); + wasm_function_inst_t test_func; + uint32_t wasm_argv[1], i32; + bool ret; + + ret = load_wasm_file("mem64.wasm"); + ASSERT_TRUE(ret); + ret = init_exec_env(); + ASSERT_TRUE(ret); + + ret = wasm_runtime_set_running_mode(module_inst, running_mode); + ASSERT_TRUE(ret); + ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst)); + + test_func = + wasm_runtime_lookup_function(module_inst, "test"); + ASSERT_TRUE(test_func != NULL); + ret = wasm_runtime_call_wasm(exec_env, test_func, 0, wasm_argv); + ASSERT_TRUE(ret); + i32 = 0x109; + ASSERT_EQ(i32, wasm_argv[0]); + + destory_exec_env(); +} + +INSTANTIATE_TEST_CASE_P(RunningMode, memory64_test_suite, + testing::ValuesIn(running_mode_supported)); \ No newline at end of file diff --git a/tests/unit/memory64/wasm-apps/8GB_memory.wasm b/tests/unit/memory64/wasm-apps/8GB_memory.wasm new file mode 100644 index 0000000000000000000000000000000000000000..32028ff62bbbf3eb0d6196d925b2e01590fcdc83 GIT binary patch literal 249 zcmZQbEY4+QU|?XJ)X>ntz?{IqQdd`BpTJaC$B@8S$5_YQ0v2arWMb_Au^3q!8aRN6 z{UBIepd`OEIU_!`EVZaIz92C@m4QJd)668kxFo+QH9kKrtvIzL-o)LBfl(MFoRgoJ zf-K6!^#yFq8L-iebxuFz6&aWv6c`j3%$b3NQ-eZ{BA5m$P;la?4dG?rcKY$3S(BLo rNHsSIKp5=}0vb#VPJjMG82sG5AOnFK6&TH#fy@R0?rx}vCX^2Voc>7V literal 0 HcmV?d00001 diff --git a/tests/unit/memory64/wasm-apps/8GB_memory.wat b/tests/unit/memory64/wasm-apps/8GB_memory.wat new file mode 100644 index 000000000..10e355198 --- /dev/null +++ b/tests/unit/memory64/wasm-apps/8GB_memory.wat @@ -0,0 +1,53 @@ +(module + ;; Memory definition: 4 GB = 65536 + ;; 8 GB = 131072 + ;; 16 GB = 262144 + ;; 20 GB = 327680 + ;; 32 GB = 524288 + (memory (;0;) i64 131072 131072) + + ;; if touch too many pages more than physical memory can provide, + ;; the signal will kill the process + (func (export "touch_every_page") (result i64 i64 i32 i32) + (local $i i64) + i64.const 0x0000000000000ff8 + local.set $i + loop $loop + ;; a[i] = i + local.get $i + local.get $i + i64.store + local.get $i + i64.const 4096 + i64.add + local.set $i + local.get $i + ;; max boundary(exclusive) 8GB - 8 = 0x0000000200000000 - 8 + i64.const 0x0000000200000000 + i64.const 8 + i64.sub + i64.lt_u + br_if $loop + end + i64.const 0x000000000000fff8 + i64.load + i64.const 0x000000010000fff8 + i64.load + ;; lower 8 bytes of 0x000000010001fff8 -> 0x0001fff8 + i64.const 0x000000010001fff8 + i32.load + ;; higher 8 bytes of 0x000000010001fff8 -> 0x1 + i64.const 0x000000010001fffc + i32.load + return + ) + + ;; Function to test i64.atomic.store with i64 address + (func (export "i64_store_offset_4GB") (param $addr i64) (param $value i64) + (i64.store offset=0x100000000 (local.get $addr) (local.get $value)) + ) + + (func (export "i64_load_offset_4GB") (param $addr i64) (result i64) + (i64.load offset=0x100000000 (local.get $addr)) + ) +) \ No newline at end of file diff --git a/tests/unit/memory64/wasm-apps/atomic_opcodes.wasm b/tests/unit/memory64/wasm-apps/atomic_opcodes.wasm new file mode 100644 index 0000000000000000000000000000000000000000..fbdc587096da88e66f9e785c4734d440e0ba3804 GIT binary patch literal 820 zcmZXR$xg#C5QfLj)+R048ke209JsbcRnFXaiZp5wR3a+sA~>b5*N5QFTU3k`=AR@`tV#j^TP;9~=$A_LY>k zMKJ?M&E+J^H_(bT+hB~e?JF^&*;O;@W-r!kqPe3}{3sjfs_Dz}BQIt%I7*asgc+x3 z_SqrFxxa-#U89~7CdwMhl!zVjW=gCT_+JybJ*|*W%lFUe>kB0AH(@TMkdl3$g7+s+ zppmDfk;g_O&!pj88ZK}`3y1B4T14m*Bu1AIAr29uSC^8y#N+~(Ql>KMT1H*TU2de| jRvPYbLPxwV@z)&g(zzT3IcOsq=6vK-4+rIHFv>BRCe zpO9k?JmeF6bZ-6xA9Hk7a!%z9L5ub^sA>+Tr(d%h@1bE;U+vqLW!V}1MAz$e`{;>9 zQ%Ahhj<#&&I<{-8NT06T{_&rdSGW9sV&>OuqT6m{e{cVXmp?1ZIox}7XxZsXWxx9U z^GfyQx8InbA1#%rRGwB3tChXyPqpn;D&Or@UsS%XzS`3&@h++V)mdGS9NBes3%MDNvFA}l8)_K65(y6s2sJUci`rfBhg(~ zVu&JEmiVqM3B-{&5D(s^qzyN(`=u)kOd=`W=x$2NSCU2w>4x;63q65kkjW`adWk=U zUYt6Vz7U!Xp{H?L`qAH%0YV2cfWd|gA&a3vhB1u3qO!uk5oQ?02u5o%#!AOnX_w`B zEF9e8i^7G4k3%qCmI=ZpF@ebgnZndb;nQK#8O%ryxu)d#?`M$5nTDLjG|mPxi&<0n zoT)Y~^I`k~7NmeeQx+M&ghebhWEt~V4rB!@CjK1eaPFBD4J;<55Vnd{S;JaW)(P9d zIyM@zi4rygIgj%wo;10|YPYe4?V6AS?6jKen}B%gYkS|6oxI3T{B=BXCR&IPBxjuQS`i~3OT0!pI`36nIQ*S~i{k~~e8^r~_H)^T^!-CfcJ(wX9I zijDj4Eow<29Z*X>lJN`D%WZE!A)S&wKP_2qvw?&X%AgPZ>9Dy09t;$fQS~5i2aBq! zrD~N^T{1**3}XnxWjWE*0W~#d#L3_-g`I0iNcrq6Y(*U?$SJ(ra3KZOF;R@Hu+Z2uf^dbaN)o$s(_1CR6lXyi~oZ3 zk@uW>-ytDtG!f%@EHKm}YUqpP^}9|;f~N_i3A*2Q+#cOts0s3(Qy)7=Nu!Bwo_7bN zHie`~+LhOTbwbiSO&d+n{h{OTp}Qy4M25GSPb@ly#a^=58YpGy;}g!3{p^8}f?=^0 z!Koqx7--6%QPL1Igfm4(NaH95G1?&OBNz)fL11VUCTfk1L$cn=(PAA_O_?@1W|$)+ zy*)3c!+DW!&kIbL-deyprkdv{n6JqKQ44L>$wqDa$fpD_F+L0SC#s zlU9l-a+H*svTDj$V}`Xr*0C-dY-JOx*lci+Y~Xw#Ti7zKY=>p+U`IGMn&R{Axj@{7 zKrZ5NB|(!ms1H+`x^d+~kXJi||{4+{SIWL-<|X z#NCG6!yViU+DZ2h*v3OVz{8q6BI?m6&GXSf9^-M!^M0}UQH*(q=6kAWn&!}4 V+UHkU}OQ34FUi(u?1uR literal 0 HcmV?d00001 diff --git a/tests/unit/memory64/wasm-apps/page_exceed_u32_2.wat b/tests/unit/memory64/wasm-apps/page_exceed_u32_2.wat new file mode 100644 index 000000000..4db1b838d --- /dev/null +++ b/tests/unit/memory64/wasm-apps/page_exceed_u32_2.wat @@ -0,0 +1,4 @@ +(module + ;; u32 max pages is 4,294,967,295 + (memory i64 4294967296) +) \ No newline at end of file diff --git a/tests/unit/memory64/wasm-apps/page_u32_max.wasm b/tests/unit/memory64/wasm-apps/page_u32_max.wasm new file mode 100644 index 0000000000000000000000000000000000000000..caa8de4543ba54074d17aa8e9c1301f5d366f985 GIT binary patch literal 22 bcmZQbEY4+QU|?YFXlQ6)U}R +#include + +int +recursive(int a) +{ + if (a > 0) { + return recursive(a - 1) + 1; + } + else + return 0; +} + +int +testFunction(int *input, int length) +{ + int sum = 0; + for (int i = 0; i < length; ++i) { + sum += input[i]; + } + return sum; +} + +int +main(int argc, char **argv) +{ + + int arr[5] = { 1, 2, 3, 4, 5 }; + testFunction(arr, recursive(5)); + + char *buf; + + printf("Hello world!\n"); + + buf = malloc(1024); + if (!buf) { + printf("malloc buf failed\n"); + return -1; + } + + printf("buf ptr: %p\n", buf); + + snprintf(buf, 1024, "%s", "1234\n"); + printf("buf: %s", buf); + + free(buf); + return 0; +} diff --git a/tests/unit/running-modes/wasm_running_modes_test.cc b/tests/unit/running-modes/wasm_running_modes_test.cc new file mode 100644 index 000000000..9d6a9379c --- /dev/null +++ b/tests/unit/running-modes/wasm_running_modes_test.cc @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "platform_common.h" +#include "wasm_runtime_common.h" +#include "bh_read_file.h" +#include "wasm_runtime.h" +#include "bh_platform.h" +#include "wasm_export.h" +#include "aot_runtime.h" + +namespace { + +std::string CWD; +std::string TEST_WASM1 = "/hello.wasm"; +std::string TEST_WASM2 = "/mytest.wasm"; +char *WASM_FILE_1; +char *WASM_FILE_2; +std::vector running_mode_supportted = { Mode_Interp, +#if WASM_ENABLE_FAST_JIT != 0 + Mode_Fast_JIT, +#endif +#if WASM_ENABLE_JIT != 0 + Mode_LLVM_JIT, +#endif +#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 \ + && WASM_ENABLE_LAZY_JIT != 0 + Mode_Multi_Tier_JIT +#endif +}; + +// To use a test fixture and Value Parameterized Tests, +// derive a class from testing::TestWithParam. +class wasm_running_modes_test_suite : public testing::TestWithParam +{ + private: + std::string get_binary_path() + { + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); + } + + bool load_wasm_file(const char *wasm_file) + { + const char *file; + unsigned char *wasm_file_buf; + uint32 wasm_file_size; + + file = wasm_file; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size); + if (!wasm_file_buf) + goto fail; + + if (!(module = wasm_runtime_load(wasm_file_buf, wasm_file_size, + error_buf, sizeof(error_buf)))) { + printf("Load wasm module failed. error: %s\n", error_buf); + goto fail; + } + return true; + + fail: + if (!module) + wasm_runtime_unload(module); + + return false; + } + + bool init_exec_env() + { + if (!(module_inst = + wasm_runtime_instantiate(module, stack_size, heap_size, + error_buf, sizeof(error_buf)))) { + printf("Instantiate wasm module failed. error: %s\n", error_buf); + goto fail; + } + if (!(exec_env = + wasm_runtime_create_exec_env(module_inst, stack_size))) { + printf("Create wasm execution environment failed.\n"); + goto fail; + } + return true; + + fail: + if (exec_env) + wasm_runtime_destroy_exec_env(exec_env); + if (module_inst) + wasm_runtime_unload(module); + return false; + } + + void destory_exec_env() + { + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + } + + protected: + void run_wasm_basic( + char *filename, bool in_default_running_mode, + RunningMode running_mode = static_cast(Mode_Default)) + { + bool ret; + uint32_t wasm_argv[2]; + ret = load_wasm_file(filename); + ASSERT_TRUE(ret); + ret = init_exec_env(); + ASSERT_TRUE(ret); + + if (!in_default_running_mode) { + ret = wasm_runtime_set_running_mode(module_inst, running_mode); + ASSERT_TRUE(ret); + ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst)); + } + + wasm_function_inst_t echo2xback_func = + wasm_runtime_lookup_function(module_inst, "echo"); + ASSERT_TRUE(echo2xback_func != NULL); + + wasm_argv[0] = 5; + ret = wasm_runtime_call_wasm(exec_env, echo2xback_func, 1, wasm_argv); + ASSERT_TRUE(ret); + ASSERT_EQ(10, wasm_argv[0]); + + destory_exec_env(); + } + + void run_wasm_complex(char *filename1, char *filename2, + RunningMode default_running_mode, + RunningMode running_mode) + { + bool ret; + uint32_t wasm_argv[2]; + + /* run wasm file 1 in default running mode */ + wasm_runtime_set_default_running_mode(default_running_mode); + ret = load_wasm_file(filename1); + ASSERT_TRUE(ret); + ret = init_exec_env(); + ASSERT_TRUE(ret); + + uint8_t *buffer, *buffer2; + wasm_function_inst_t echo2xback_func, main; + + ASSERT_EQ(default_running_mode, + wasm_runtime_get_running_mode(module_inst)); + echo2xback_func = wasm_runtime_lookup_function(module_inst, "echo"); + ASSERT_TRUE(echo2xback_func != NULL); + wasm_argv[0] = 5; + ret = wasm_runtime_call_wasm(exec_env, echo2xback_func, 1, wasm_argv); + ASSERT_TRUE(ret); + ASSERT_EQ(10, wasm_argv[0]); + + destory_exec_env(); + + /* run wasm file 2 in running_mode */ + ret = load_wasm_file(filename2); + ASSERT_TRUE(ret); + ret = init_exec_env(); + ASSERT_TRUE(ret); + + ret = wasm_runtime_set_running_mode(module_inst, running_mode); + ASSERT_TRUE(ret); + ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst)); + main = wasm_runtime_lookup_function(module_inst, "__main_argc_argv"); + ASSERT_TRUE(main != NULL); + ret = wasm_runtime_call_wasm(exec_env, main, 2, wasm_argv); + ASSERT_TRUE(ret); + + destory_exec_env(); + } + + public: + // If your test fixture defines SetUpTestSuite() or TearDownTestSuite() + // they must be declared public rather than protected in order to use + // TEST_P. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() + { + CWD = get_binary_path(); + WASM_FILE_1 = strdup((CWD + TEST_WASM1).c_str()); + WASM_FILE_2 = strdup((CWD + TEST_WASM2).c_str()); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + + cleanup = true; + } + + static void SetUpTestCase() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() + { + if (cleanup) { + wasm_runtime_destroy(); + cleanup = false; + } + free(WASM_FILE_1); + free(WASM_FILE_2); + } + + static void TearDownTestCase() {} + + std::string CWD; + RuntimeInitArgs init_args; + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_exec_env_t exec_env = NULL; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + uint32_t stack_size = 8092, heap_size = 8092; + bool cleanup = true; +}; + +TEST_F(wasm_running_modes_test_suite, wasm_runtime_is_running_mode_supported) +{ + // normal situation + ASSERT_EQ(true, wasm_runtime_is_running_mode_supported( + static_cast(Mode_Default))); + for (auto running_mode : running_mode_supportted) { + ASSERT_EQ(true, wasm_runtime_is_running_mode_supported(running_mode)); + } + + // abnormal situation + ASSERT_EQ(false, wasm_runtime_is_running_mode_supported( + static_cast(-1))); + ASSERT_EQ(false, wasm_runtime_is_running_mode_supported( + static_cast(5))); + ASSERT_EQ(false, wasm_runtime_is_running_mode_supported( + static_cast(0xFF))); +} + +TEST_F(wasm_running_modes_test_suite, wasm_runtime_set_default_running_mode) +{ + // normal situation: only set up + ASSERT_EQ(true, wasm_runtime_set_default_running_mode( + static_cast(Mode_Default))); + for (auto running_mode : running_mode_supportted) { + ASSERT_EQ(true, wasm_runtime_set_default_running_mode(running_mode)); + } + + // abnormal situation + ASSERT_EQ(false, wasm_runtime_set_default_running_mode( + static_cast(-1))); + ASSERT_EQ(false, wasm_runtime_set_default_running_mode( + static_cast(5))); + ASSERT_EQ(false, wasm_runtime_set_default_running_mode( + static_cast(0xFF))); +} + +TEST_P(wasm_running_modes_test_suite, + wasm_runtime_set_default_running_mode_basic) +{ + RunningMode running_mode = GetParam(); + ASSERT_EQ(true, wasm_runtime_set_default_running_mode(running_mode)); + run_wasm_basic(WASM_FILE_1, true); +} + +TEST_P(wasm_running_modes_test_suite, + wasm_runtime_set_and_get_running_mode_basic) +{ + RunningMode running_mode = GetParam(); + run_wasm_basic(WASM_FILE_1, false, running_mode); +} + +TEST_P(wasm_running_modes_test_suite, + wasm_runtime_set_and_get_running_mode_complex) +{ + RunningMode default_running_mode = GetParam(); + for (auto running_mode : running_mode_supportted) { + run_wasm_complex(WASM_FILE_1, WASM_FILE_2, default_running_mode, + running_mode); + } +} + +INSTANTIATE_TEST_CASE_P(RunningMode, wasm_running_modes_test_suite, + testing::ValuesIn(running_mode_supportted)); + +} \ No newline at end of file diff --git a/tests/unit/runtime-common/CMakeLists.txt b/tests/unit/runtime-common/CMakeLists.txt new file mode 100644 index 000000000..f73756915 --- /dev/null +++ b/tests/unit/runtime-common/CMakeLists.txt @@ -0,0 +1,73 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project(test-runtime-common) + +add_definitions(-DRUN_ON_LINUX) + +set(WAMR_BUILD_LIBC_WASI 0) +set(WAMR_BUILD_APP_FRAMEWORK 0) + +include(../unit_common.cmake) + +set(LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") + +if(NOT EXISTS "${LLVM_SRC_ROOT}/build") + message(FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif() + +set(CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +file(GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set(UNIT_SOURCE ${source_all}) + +aux_source_directory(. SRC_LIST) + +set(unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} + ${UNCOMMON_SHARED_SOURCE} + ${SRC_LIST} +) + +add_executable(runtime_common_test ${unit_test_sources}) + +target_link_libraries(runtime_common_test ${LLVM_AVAILABLE_LIBS} gtest_main) + +# Ensure that aot compiled is completed before linear_memory_test_aot is built +set(dummy_output "${CMAKE_CURRENT_BINARY_DIR}/dummy_output") + +add_custom_command(OUTPUT ${dummy_output} + COMMAND ./build_aot.sh + COMMAND ${CMAKE_COMMAND} -E touch ${dummy_output} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/build_aot.sh + COMMENT "Executing script to compile aot files" + VERBATIM +) + +add_custom_target( + BuildAot ALL + DEPENDS ${dummy_output} +) + +add_dependencies(runtime_common_test BuildAot) + +add_custom_command(TARGET runtime_common_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/main.wasm ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/main.aot + ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copy main.wasm and main.aot to the directory: build/runtime-common." +) + +gtest_discover_tests(runtime_common_test) diff --git a/tests/unit/runtime-common/build_aot.sh b/tests/unit/runtime-common/build_aot.sh new file mode 100755 index 000000000..441d441b5 --- /dev/null +++ b/tests/unit/runtime-common/build_aot.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +# Define a list of .wasm files +file_names=("main") + +WORKDIR="$PWD" +WAMRC_ROOT_DIR="${WORKDIR}/../../../wamr-compiler" +WAMRC="${WAMRC_ROOT_DIR}/build/wamrc" +WAST2WASM="/opt/wabt/bin/wat2wasm" + +# build wamrc if not exist +if [ ! -s "$WAMRC" ]; then + cd $WAMRC_ROOT_DIR + if [ -d "$WAMRC/build" ]; then + rm -r build + fi + cmake -B build && cmake --build build -j $(nproc) + cd $WORKDIR +fi + +# Iterate over the files array +for file_name in "${file_names[@]}"; do + # compile wasm to aot + $WAMRC -o "wasm-apps/${file_name}.aot" "wasm-apps/${file_name}.wasm" +done + diff --git a/tests/unit/runtime-common/wasm-apps/main.aot b/tests/unit/runtime-common/wasm-apps/main.aot new file mode 100644 index 0000000000000000000000000000000000000000..79319145a9019df34a340da8f14f9a3f95e5175d GIT binary patch literal 1164 zcmah|L2J}d5Pq%7#&+%IP_WuVSJ;E6(gi8qixAji7E%#x^`P|;H?Q4bHwnpeyDGTF z1!)LMPu~0sp1kN`DYPQqihsbH2v+Dx1%*1_OV(0WH{#)8J(|r2EK@PZl28MwaM^oE>?xPJj#~B+ZGc@0DqaytxyBVyA;*uX0rHJI@ zP>M!vK!1PsIH6L56zg<4DGWY&K*54NQUeM@4-C6?C~c4hFQDL$6OX>%=L>SeYq1;) zLf4Z^1Y?-FPl5?Ws)1k%YWniq*V72{;0{?Zt{c~k1!MlI+1(wpl2zSI{HfXG#SQ_C zC$oFKQ-m@rZwlS#aN-|UvOLopA-`7HE<9Q%$4VZI)soBS&DbjGwd83VrSW5Qcw5!- zgkZ06u2%f5hq2{%bMg022-lLF8COf%D}*Us{#t&2kUMS0AIwCSG&8A|^nJZ|j!?$h z!v?!Ms%Tl2FVT?VGFRD+&QJr@wY+I|x5sW6H;qN(mcbXdW@EL^=Z{MpW^#!(TnEKu z4Gg=Rd$H8=TZM@=>dubJ$Mc#-m?QK5t1oYEsk?SCB$K_&>e!xSDzjHI3xm7DI|7UA zJ(*eDJDzi-$Q@SXHnKb!%I8>9H2v^iie;?8e2+`FDMBt5g{l&uz`ZwLzA?rQc|QsS}q8|0U<6ea{bsOZelywPEbzn z1&RN_0sa-gf+Hs`%qFQQ9H190@9fO(%(vg{&VZc+2mrXIpRp{%>a; zG8`Mj*bmbV05^1GoN1blLqyayM8=FV&#?Vv)6Ag#DX%2yxwknZkUCiMyg)_e7HSj}8)kM6WlSITHrA0MOtC1Ft4^Cf9tf%z$ zrz)q@_f)CYT#IK~Es0%#!1k%MRN5}6V9=+D+|czR+bZX~Y@J}?D;DSEsl=#|r(tlN zL!6O6@UG=abZS@GxC1-vim{9nKMKW8qgt=l#bz%}hsi;$*7eig$f>$fP#X-!GqF94 zqjTw|qT}s&58d5Peb4jcZo`qX-fy^+S7LDL(9v=HtKjo_3}6^vll6ts)RklG<+H8b)+uGA)pZtFUm;ft$ literal 0 HcmV?d00001 diff --git a/tests/unit/runtime-common/wasm_exec_env_test.cc b/tests/unit/runtime-common/wasm_exec_env_test.cc new file mode 100644 index 000000000..06c162b62 --- /dev/null +++ b/tests/unit/runtime-common/wasm_exec_env_test.cc @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "wasm_exec_env.h" + +class wasm_exec_env_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} +}; + +TEST_F(wasm_exec_env_test_suite, wasm_exec_env_create) +{ + EXPECT_EQ(nullptr, wasm_exec_env_create(nullptr, 0)); +} + +TEST_F(wasm_exec_env_test_suite, wasm_exec_env_create_internal) +{ + EXPECT_EQ(nullptr, wasm_exec_env_create_internal(nullptr, UINT32_MAX)); +} + +TEST_F(wasm_exec_env_test_suite, wasm_exec_env_pop_jmpbuf) +{ + WASMExecEnv exec_env; + + exec_env.jmpbuf_stack_top = nullptr; + EXPECT_EQ(nullptr, wasm_exec_env_pop_jmpbuf(&exec_env)); +} diff --git a/tests/unit/runtime-common/wasm_runtime_common_test.cc b/tests/unit/runtime-common/wasm_runtime_common_test.cc new file mode 100644 index 000000000..978b54022 --- /dev/null +++ b/tests/unit/runtime-common/wasm_runtime_common_test.cc @@ -0,0 +1,682 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "platform_common.h" +#include "wasm_runtime_common.h" +#include "bh_read_file.h" +#include "wasm_runtime.h" +#include "bh_platform.h" +#include "wasm_export.h" +#include "aot_runtime.h" + +using namespace std; + +extern "C" { +uint32 +wasm_runtime_module_realloc(WASMModuleInstanceCommon *module_inst, uint32 ptr, + uint32 size, void **p_native_addr); +bool +wasm_runtime_create_exec_env_and_call_wasm( + WASMModuleInstanceCommon *module_inst, WASMFunctionInstanceCommon *function, + uint32 argc, uint32 argv[]); +} + +static bh_list loading_module_list_head; +static bh_list *const loading_module_list = &loading_module_list_head; +static korp_mutex loading_module_list_lock; + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static std::string MAIN_AOT = "/main.aot"; +static char *WASM_FILE_1; +static char *AOT_FILE_1; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class wasm_runtime_common_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE_1 = strdup((CWD + MAIN_WASM).c_str()); + AOT_FILE_1 = strdup((CWD + MAIN_AOT).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() + { + free(WASM_FILE_1); + free(AOT_FILE_1); + } + + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_destroy) +{ + wasm_runtime_init(); + wasm_runtime_destroy(); +} + +static bool +reader_test(package_type_t module_type, const char *module_name, + uint8 **p_buffer, uint32 *p_size) +{ + return true; +} + +static void +destroyer_test(uint8 *buffer, uint32 size) +{} + +TEST_F(wasm_runtime_common_test_suite, + set_module_reader_get_module_reader_get_module_destroyer) +{ + wasm_runtime_set_module_reader(reader_test, destroyer_test); + EXPECT_EQ((module_reader)reader_test, wasm_runtime_get_module_reader()); + EXPECT_EQ((module_destroyer)destroyer_test, + wasm_runtime_get_module_destroyer()); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_register_module) +{ + const char *wasm_file = WASM_FILE_1; + wasm_module_t wasm_module = nullptr; + unsigned char *wasm_file_buf = nullptr; + unsigned int wasm_file_size = 0; + char error_buf[128] = { 0 }; + char module_name[] = "module_test"; + char module_name_1[] = "module_test_1"; + + // Normal situation. + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + EXPECT_NE(false, + wasm_runtime_register_module("module_test", wasm_module, + error_buf, sizeof(error_buf))); + + // Abnormal situation. + EXPECT_EQ(false, + wasm_runtime_register_module(nullptr, nullptr, nullptr, 0)); + EXPECT_EQ(false, wasm_runtime_register_module( + "module_test", nullptr, error_buf, sizeof(error_buf))); + EXPECT_EQ(false, wasm_runtime_register_module("module_test", wasm_module, + nullptr, sizeof(error_buf))); + EXPECT_EQ(false, wasm_runtime_register_module("module_test", wasm_module, + error_buf, 0)); + EXPECT_EQ(false, wasm_runtime_register_module( + nullptr, wasm_module, error_buf, sizeof(error_buf))); + EXPECT_EQ(false, wasm_runtime_register_module(nullptr, nullptr, error_buf, + sizeof(error_buf))); + + EXPECT_EQ(true, wasm_runtime_register_module(module_name, wasm_module, + error_buf, sizeof(error_buf))); + EXPECT_EQ(false, wasm_runtime_register_module_internal(nullptr, wasm_module, + NULL, 0, error_buf, + sizeof(error_buf))); + EXPECT_EQ(false, wasm_runtime_register_module_internal( + module_name_1, wasm_module, NULL, 0, error_buf, + sizeof(error_buf))); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_unregister_module) +{ + wasm_runtime_unregister_module(nullptr); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_find_module_registered) +{ + EXPECT_EQ(nullptr, wasm_runtime_find_module_registered("module_test")); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_is_module_registered) +{ + EXPECT_EQ(nullptr, wasm_runtime_find_module_registered("")); +} + +/* TODO: add thread safety test. */ +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_add_loading_module) +{ + EXPECT_EQ(true, wasm_runtime_add_loading_module(nullptr, nullptr, 0)); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_destroy_loading_module_list) +{ + os_mutex_init(&loading_module_list_lock); + wasm_runtime_destroy_loading_module_list(); + os_mutex_destroy(&loading_module_list_lock); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_is_built_in_module) +{ + EXPECT_EQ(true, wasm_runtime_is_built_in_module("env")); + EXPECT_EQ(true, wasm_runtime_is_built_in_module("wasi_unstable")); + EXPECT_EQ(true, wasm_runtime_is_built_in_module("wasi_snapshot_preview1")); + EXPECT_EQ(true, wasm_runtime_is_built_in_module("")); + EXPECT_EQ(false, wasm_runtime_is_built_in_module("test")); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_read_v128) +{ + unsigned char buf[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + unsigned char ret1[8] = { 0 }; + unsigned char ret2[8] = { 0 }; + + wasm_runtime_read_v128((const uint8 *)buf, (uint64 *)ret1, (uint64 *)ret2); + EXPECT_EQ(0, strncmp("01234567", (const char *)ret1, 8)); + EXPECT_EQ(0, strncmp("89ABCDEF", (const char *)ret2, 8)); +} + +TEST_F(wasm_runtime_common_test_suite, + wasm_runtime_show_app_heap_corrupted_prompt) +{ + wasm_runtime_show_app_heap_corrupted_prompt(); +} + +TEST_F(wasm_runtime_common_test_suite, wasm_runtime_is_xip_file) +{ + // WASM file. + const char *wasm_file = WASM_FILE_1; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + EXPECT_EQ(false, wasm_runtime_is_xip_file(wasm_file_buf, wasm_file_size)); + + // AoT file. + const char *aot_file = AOT_FILE_1; + unsigned int aot_file_size = 0; + unsigned char *aot_file_buf = nullptr; + + aot_file_buf = + (unsigned char *)bh_read_file_to_buffer(aot_file, &aot_file_size); + EXPECT_NE(aot_file_buf, nullptr); + EXPECT_EQ(false, wasm_runtime_is_xip_file(aot_file_buf, aot_file_size)); +} + +TEST_F(wasm_runtime_common_test_suite, get_package_type) +{ + const char *wasm_file = WASM_FILE_1; + unsigned int wasm_file_size = 0; + unsigned char *wasm_file_buf = nullptr; + + // WASM file. + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + EXPECT_EQ(Wasm_Module_Bytecode, + get_package_type(wasm_file_buf, wasm_file_size)); + + // WASM file. Abnormally. + wasm_file_buf[3] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[2] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[1] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[0] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + + EXPECT_EQ(Package_Type_Unknown, get_package_type(wasm_file_buf, 0)); + EXPECT_EQ(Package_Type_Unknown, get_package_type(nullptr, 0)); + + // AoT file. + const char *wasm_file_aot = AOT_FILE_1; + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file_aot, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + EXPECT_EQ(Wasm_Module_AoT, get_package_type(wasm_file_buf, wasm_file_size)); + + // AoT file. Abnormally. + wasm_file_buf[3] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[2] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[1] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + wasm_file_buf[0] = -1; + EXPECT_EQ(Package_Type_Unknown, + get_package_type(wasm_file_buf, wasm_file_size)); + + EXPECT_EQ(Package_Type_Unknown, get_package_type(wasm_file_buf, 0)); + EXPECT_EQ(Package_Type_Unknown, get_package_type(nullptr, 0)); +} + +TEST_F(wasm_runtime_common_test_suite, functions_on_wasm_module) +{ + const char *wasm_file = WASM_FILE_1; + wasm_module_inst_t wasm_module_inst = nullptr; + wasm_module_t wasm_module = nullptr; + wasm_exec_env_t exec_env = nullptr; + wasm_exec_env_t exec_env_1 = nullptr; + unsigned char *wasm_file_buf = nullptr; + WASMFunctionInstanceCommon *func = nullptr; + const char *user_data = "test"; + unsigned int wasm_file_size = 0; + unsigned int stack_size = 16 * 1024, heap_size = 16 * 1024; + char error_buf[128] = { 0 }; + unsigned int argv[2] = { 0 }; + WASMType *func_type = nullptr; + wasm_val_t arguments[1]; + char str_test[] = "This is a test."; + char str_exception[] = "Exception: "; + char str_tmp[60] = { 0 }; + void *ptr_tmp = nullptr; + unsigned int offset_tmp = 0; + unsigned int tmp = 0; + unsigned char *p_native_start_addr = nullptr; + unsigned char *p_native_end_addr = nullptr; + NativeSymbol *native_symbols; + uint32 n_native_symbols; + const char *exception_test = nullptr; + + arguments[0].kind = WASM_I32; + arguments[0].of.i32 = 0; + + // Create exec_env. + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + wasm_module_inst = wasm_runtime_instantiate( + wasm_module, stack_size, heap_size, error_buf, sizeof(error_buf)); + EXPECT_NE(wasm_module_inst, nullptr); + exec_env = wasm_runtime_create_exec_env(wasm_module_inst, stack_size); + EXPECT_NE(exec_env, nullptr); + + // Operations on exec_env. + EXPECT_EQ(true, wasm_runtime_register_module_internal("test", wasm_module, + nullptr, 0, error_buf, + sizeof(error_buf))); + EXPECT_NE(nullptr, wasm_runtime_find_module_registered("test")); + EXPECT_EQ(wasm_module_inst, wasm_runtime_get_module_inst(exec_env)); + EXPECT_EQ(exec_env->attachment, + wasm_runtime_get_function_attachment(exec_env)); + EXPECT_EQ(wasm_module, wasm_exec_env_get_module(exec_env)); + + wasm_runtime_set_user_data(exec_env, (void *)user_data); + EXPECT_EQ((void *)user_data, wasm_runtime_get_user_data(exec_env)); + + func = wasm_runtime_lookup_function(wasm_module_inst, "on_timer_event"); + func_type = + wasm_runtime_get_function_type(func, wasm_module_inst->module_type); + EXPECT_NE(func_type, nullptr); + EXPECT_EQ(false, wasm_runtime_call_wasm(exec_env, func, 0, argv)); + exception_test = wasm_runtime_get_exception(wasm_module_inst); + EXPECT_NE(nullptr, exception_test); + + EXPECT_EQ(false, wasm_runtime_call_wasm_a(exec_env, func, 0, nullptr, 1, + arguments)); + exception_test = wasm_runtime_get_exception(wasm_module_inst); + EXPECT_NE(nullptr, exception_test); + + WASMFunctionInstance func_test_1; + WASMFunction wasm_func_test; + WASMType wasm_type_test; + wasm_func_test.func_type = &wasm_type_test; + func_test_1.u.func = &wasm_func_test; + func_test_1.u.func->func_type->param_count = 1; + func_test_1.u.func->func_type->param_cell_num = 2; + func_test_1.u.func->func_type->types[0] = VALUE_TYPE_I64; + func_test_1.u.func->max_stack_cell_num = 10; + EXPECT_EQ(false, wasm_runtime_call_wasm_v( + exec_env, (WASMFunctionInstanceCommon *)(&func_test_1), + 0, nullptr, 1, arguments)); + func_test_1.u.func->func_type->types[0] = VALUE_TYPE_F32; + EXPECT_EQ(false, wasm_runtime_call_wasm_v( + exec_env, (WASMFunctionInstanceCommon *)(&func_test_1), + 0, nullptr, 1, arguments)); + func_test_1.u.func->func_type->types[0] = VALUE_TYPE_F64; + EXPECT_EQ(false, wasm_runtime_call_wasm_v( + exec_env, (WASMFunctionInstanceCommon *)(&func_test_1), + 0, nullptr, 1, arguments)); + +#if 0 + WASMFunctionInstance func_test; + WASMFunctionImport func_import_test; + WASMType *func_type_1 = nullptr; + func_import_test.func_type = func_type; + func_test.u.func_import = &func_import_test; + func_test.is_import_func = true; + func_type_1 = wasm_runtime_get_function_type(&func_test, + wasm_module_inst->module_type); + EXPECT_NE(func_type_1, nullptr); +#endif + + EXPECT_EQ(true, wasm_runtime_create_exec_env_singleton(wasm_module_inst)); + EXPECT_NE(nullptr, wasm_runtime_get_exec_env_singleton(wasm_module_inst)); + + wasm_runtime_set_exception(wasm_module_inst, str_test); + sprintf(str_tmp, "%s%s", str_exception, str_test); + EXPECT_EQ(0, strcmp(str_tmp, wasm_runtime_get_exception(wasm_module_inst))); + wasm_runtime_clear_exception(wasm_module_inst); + EXPECT_EQ(nullptr, wasm_runtime_get_exception(wasm_module_inst)); + + wasm_runtime_set_custom_data(wasm_module_inst, (void *)user_data); + EXPECT_EQ((void *)user_data, + wasm_runtime_get_custom_data(wasm_module_inst)); + + offset_tmp = wasm_runtime_module_malloc(wasm_module_inst, 10, &ptr_tmp); + EXPECT_NE(0, offset_tmp); + EXPECT_EQ(true, + wasm_runtime_validate_app_addr(wasm_module_inst, offset_tmp, 10)); + EXPECT_EQ(ptr_tmp, + wasm_runtime_addr_app_to_native(wasm_module_inst, offset_tmp)); + EXPECT_EQ(true, + wasm_runtime_validate_native_addr(wasm_module_inst, ptr_tmp, 10)); + EXPECT_EQ(offset_tmp, + wasm_runtime_addr_native_to_app(wasm_module_inst, ptr_tmp)); + EXPECT_EQ(true, wasm_runtime_get_native_addr_range( + wasm_module_inst, (unsigned char *)ptr_tmp, + &p_native_start_addr, &p_native_end_addr)); + EXPECT_NE(0, wasm_runtime_module_realloc(wasm_module_inst, offset_tmp, 100, + &ptr_tmp)); + /* can't test like that since shrink size optimization will be applied */ + /* EXPECT_EQ(false, + wasm_enlarge_memory((WASMModuleInstance *)wasm_module_inst, 1)); + */ + EXPECT_EQ(offset_tmp, + wasm_runtime_addr_native_to_app(wasm_module_inst, ptr_tmp)); + EXPECT_EQ(true, wasm_runtime_get_native_addr_range( + wasm_module_inst, (unsigned char *)ptr_tmp, + &p_native_start_addr, &p_native_end_addr)); + + offset_tmp = wasm_runtime_module_dup_data(wasm_module_inst, str_test, + sizeof(str_test)); + EXPECT_EQ(0, strcmp(str_test, (char *)wasm_runtime_addr_app_to_native( + wasm_module_inst, offset_tmp))); + EXPECT_EQ(true, + wasm_runtime_validate_app_str_addr(wasm_module_inst, offset_tmp)); + + ((WASMModuleInstance *)wasm_module_inst)->exec_env_singleton = nullptr; + EXPECT_NE(nullptr, wasm_runtime_get_exec_env_singleton(wasm_module_inst)); + + EXPECT_EQ(false, wasm_runtime_call_wasm(nullptr, func, 0, argv)); + wasm_runtime_set_exception(wasm_module_inst, str_test); + EXPECT_EQ(false, wasm_runtime_call_wasm(exec_env, func, 0, argv)); + wasm_runtime_clear_exception(wasm_module_inst); + + EXPECT_EQ(false, wasm_runtime_call_wasm_a(exec_env, func, 0, nullptr, 2, + arguments)); + WASMFunctionInstance *func_test_call_wasm_a_ptr = + (WASMFunctionInstance *)func; + func_test_call_wasm_a_ptr->u.func->func_type->ret_cell_num = 10; + EXPECT_EQ(true, wasm_runtime_call_wasm_a(exec_env, func, 0, nullptr, 1, + arguments)); + + // Destroy. + wasm_runtime_module_free(wasm_module_inst, offset_tmp); + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(wasm_module_inst); + wasm_runtime_unload(wasm_module); + if (wasm_file_buf) { + wasm_runtime_free(wasm_file_buf); + } +} + +TEST_F(wasm_runtime_common_test_suite, functions_on_aot_module) +{ + const char *wasm_file = AOT_FILE_1; + wasm_module_inst_t wasm_module_inst = nullptr; + wasm_module_t wasm_module = nullptr; + wasm_exec_env_t exec_env = nullptr; + wasm_exec_env_t exec_env_1 = nullptr; + unsigned char *wasm_file_buf = nullptr; + WASMFunctionInstanceCommon *func = nullptr; + const char *user_data = "test"; + unsigned int wasm_file_size = 0; + unsigned int stack_size = 16 * 1024, heap_size = 16 * 1024; + char error_buf[128] = { 0 }; + unsigned int argv[2] = { 0 }; + WASMType *func_type = nullptr; + wasm_val_t arguments[1]; + char str_test[] = "This is a test."; + char str_exception[] = "Exception: "; + char str_tmp[60] = { 0 }; + void *ptr_tmp = nullptr; + unsigned int offset_tmp = 0; + unsigned int tmp = 0; + unsigned char *p_native_start_addr = nullptr; + unsigned char *p_native_end_addr = nullptr; + NativeSymbol *native_symbols; + uint32 n_native_symbols; + const char *exception_test = nullptr; + + arguments[0].kind = WASM_I32; + arguments[0].of.i32 = 0; + + // Create exec_env. + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + wasm_module_inst = wasm_runtime_instantiate( + wasm_module, stack_size, heap_size, error_buf, sizeof(error_buf)); + EXPECT_NE(wasm_module_inst, nullptr); + exec_env = wasm_runtime_create_exec_env(wasm_module_inst, stack_size); + EXPECT_NE(exec_env, nullptr); + + // Operations on exec_env. + EXPECT_EQ(true, wasm_runtime_register_module_internal("test", wasm_module, + nullptr, 0, error_buf, + sizeof(error_buf))); + EXPECT_NE(nullptr, wasm_runtime_find_module_registered("test")); + EXPECT_EQ(wasm_module_inst, wasm_runtime_get_module_inst(exec_env)); + EXPECT_EQ(exec_env->attachment, + wasm_runtime_get_function_attachment(exec_env)); + EXPECT_EQ(wasm_module, wasm_exec_env_get_module(exec_env)); + + wasm_runtime_set_user_data(exec_env, (void *)user_data); + EXPECT_EQ((void *)user_data, wasm_runtime_get_user_data(exec_env)); + + func = wasm_runtime_lookup_function(wasm_module_inst, "on_timer_event"); + func_type = + wasm_runtime_get_function_type(func, wasm_module_inst->module_type); + EXPECT_NE(func_type, nullptr); + + EXPECT_EQ(false, wasm_runtime_call_wasm(exec_env, func, 0, argv)); + exception_test = wasm_runtime_get_exception(wasm_module_inst); + EXPECT_NE(nullptr, exception_test); + + EXPECT_EQ(false, wasm_runtime_call_wasm_a(exec_env, func, 0, nullptr, 1, + arguments)); + exception_test = wasm_runtime_get_exception(wasm_module_inst); + EXPECT_NE(nullptr, exception_test); + EXPECT_EQ(false, wasm_runtime_call_wasm_v(exec_env, func, 0, nullptr, 1, + arguments)); + exception_test = wasm_runtime_get_exception(wasm_module_inst); + EXPECT_NE(nullptr, exception_test); + + AOTFunctionInstance func_test; + AOTImportFunc func_import_test; + func_test.u.func_import = &func_import_test; + func_import_test.func_type = (AOTFuncType *)func_type; + func_test.is_import_func = true; + EXPECT_NE(nullptr, wasm_runtime_get_function_type( + &func_test, wasm_module_inst->module_type)); + + EXPECT_EQ(true, wasm_runtime_create_exec_env_singleton(wasm_module_inst)); + EXPECT_NE(nullptr, wasm_runtime_get_exec_env_singleton(wasm_module_inst)); + + wasm_runtime_set_exception(wasm_module_inst, str_test); + sprintf(str_tmp, "%s%s", str_exception, str_test); + EXPECT_EQ(0, strcmp(str_tmp, wasm_runtime_get_exception(wasm_module_inst))); + wasm_runtime_clear_exception(wasm_module_inst); + EXPECT_EQ(nullptr, wasm_runtime_get_exception(wasm_module_inst)); + + wasm_runtime_set_custom_data(wasm_module_inst, (void *)user_data); + EXPECT_EQ((void *)user_data, + wasm_runtime_get_custom_data(wasm_module_inst)); + + offset_tmp = wasm_runtime_module_malloc(wasm_module_inst, 10, &ptr_tmp); + EXPECT_NE(0, offset_tmp); + EXPECT_EQ(true, + wasm_runtime_validate_app_addr(wasm_module_inst, offset_tmp, 10)); + EXPECT_EQ(ptr_tmp, + wasm_runtime_addr_app_to_native(wasm_module_inst, offset_tmp)); + EXPECT_EQ(true, + wasm_runtime_validate_native_addr(wasm_module_inst, ptr_tmp, 10)); + EXPECT_EQ(offset_tmp, + wasm_runtime_addr_native_to_app(wasm_module_inst, ptr_tmp)); + EXPECT_EQ(true, wasm_runtime_get_native_addr_range( + wasm_module_inst, (unsigned char *)ptr_tmp, + &p_native_start_addr, &p_native_end_addr)); + EXPECT_NE(0, wasm_runtime_module_realloc(wasm_module_inst, offset_tmp, 100, + &ptr_tmp)); + + /* can't test like that since shrink size optimization will be applied */ + /* EXPECT_EQ(false, + wasm_enlarge_memory((WASMModuleInstance *)wasm_module_inst, 1)); + */ + + offset_tmp = wasm_runtime_module_dup_data(wasm_module_inst, str_test, + sizeof(str_test)); + EXPECT_EQ(0, strcmp(str_test, (char *)wasm_runtime_addr_app_to_native( + wasm_module_inst, offset_tmp))); + EXPECT_EQ(true, + wasm_runtime_validate_app_str_addr(wasm_module_inst, offset_tmp)); + + ((WASMModuleInstance *)wasm_module_inst)->exec_env_singleton = nullptr; + EXPECT_NE(nullptr, wasm_runtime_get_exec_env_singleton(wasm_module_inst)); + + // Destroy. + wasm_runtime_module_free(wasm_module_inst, offset_tmp); + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(wasm_module_inst); + wasm_runtime_unload(wasm_module); + if (wasm_file_buf) { + wasm_runtime_free(wasm_file_buf); + } +} + +TEST_F(wasm_runtime_common_test_suite, functions_on_module_type_unknown) +{ + const char *wasm_file = AOT_FILE_1; + wasm_module_inst_t wasm_module_inst = nullptr; + wasm_module_t wasm_module = nullptr; + wasm_exec_env_t exec_env = nullptr; + wasm_exec_env_t exec_env_1 = nullptr; + unsigned char *wasm_file_buf = nullptr; + WASMFunctionInstanceCommon *func = nullptr; + const char *user_data = "test"; + unsigned int wasm_file_size = 0; + unsigned int stack_size = 16 * 1024, heap_size = 16 * 1024; + char error_buf[128] = { 0 }; + unsigned int argv[2] = { 0 }; + WASMType *func_type = nullptr; + wasm_val_t arguments[1]; + char str_test[] = "This is a test."; + char str_exception[] = "Exception: "; + char str_tmp[60] = { 0 }; + void *ptr_tmp = nullptr; + unsigned int offset_tmp = 0; + unsigned int tmp = 0; + unsigned char *p_native_start_addr = nullptr; + unsigned char *p_native_end_addr = nullptr; + const char *exception_test = nullptr; + + arguments[0].kind = WASM_I32; + arguments[0].of.i32 = 0; + + // Create exec_env. + wasm_runtime_unregister_module(wasm_module); + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size); + EXPECT_NE(wasm_file_buf, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_NE(wasm_module, nullptr); + wasm_module_inst = wasm_runtime_instantiate( + wasm_module, stack_size, heap_size, error_buf, sizeof(error_buf)); + EXPECT_NE(wasm_module_inst, nullptr); + exec_env = wasm_runtime_create_exec_env(wasm_module_inst, stack_size); + EXPECT_NE(exec_env, nullptr); + + // wasm_module_inst->module_type = Package_Type_Unknown. + wasm_module_inst->module_type = Package_Type_Unknown; + EXPECT_DEATH(wasm_exec_env_get_module(exec_env), ""); + EXPECT_DEATH( + wasm_runtime_validate_app_str_addr(wasm_module_inst, offset_tmp), ""); + + // wasm_module->module_type = Package_Type_Unknown. + wasm_module->module_type = Package_Type_Unknown; + EXPECT_EQ(nullptr, + wasm_runtime_instantiate(wasm_module, stack_size, heap_size, + error_buf, sizeof(error_buf))); + + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + /* Reload unmodified buffer should be valid now */ + EXPECT_NE(wasm_module, nullptr); + wasm_file_buf[3] = -1; + wasm_file_buf[2] = -1; + wasm_file_buf[1] = -1; + wasm_file_buf[0] = -1; + wasm_module = + wasm_runtime_load(wasm_file_buf, 0, error_buf, sizeof(error_buf)); + EXPECT_EQ(wasm_module, nullptr); + wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, + sizeof(error_buf)); + EXPECT_EQ(wasm_module, nullptr); + + // Destroy. + wasm_runtime_module_free(wasm_module_inst, offset_tmp); + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(wasm_module_inst); + wasm_runtime_unload(wasm_module); + if (wasm_file_buf) { + wasm_runtime_free(wasm_file_buf); + } +} diff --git a/tests/unit/runtime-common/wasm_runtime_init_test.cc b/tests/unit/runtime-common/wasm_runtime_init_test.cc new file mode 100644 index 000000000..30e44cea3 --- /dev/null +++ b/tests/unit/runtime-common/wasm_runtime_init_test.cc @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "platform_common.h" +#include "wasm_runtime_common.h" +#include "bh_read_file.h" +#include "wasm_runtime.h" +#include "bh_platform.h" +#include "wasm_export.h" + +using namespace std; + +extern "C" { +uint32 +wasm_runtime_module_realloc(WASMModuleInstanceCommon *module_inst, uint32 ptr, + uint32 size, void **p_native_addr); +bool +wasm_runtime_create_exec_env_and_call_wasm( + WASMModuleInstanceCommon *module_inst, WASMFunctionInstanceCommon *function, + uint32 argc, uint32 argv[]); +} + +static char global_heap_buf[100 * 1024 * 1024] = { 0 }; + +static std::string CWD; +static std::string MAIN_WASM = "/main.wasm"; +static std::string MAIN_AOT = "/main.aot"; +static char *WASM_FILE_1; +static char *AOT_FILE_1; + +static int +foo(int a, int b); + +static int +foo_native(wasm_exec_env_t exec_env, int a, int b) +{ + return a + b; +} + +static NativeSymbol native_symbols[] = { { + "foo", // the name of WASM function name + (void *)foo_native, // the native function pointer + "(ii)i" // the function prototype signature +} }; + +static std::string +get_binary_path() +{ + char cwd[1024]; + memset(cwd, 0, 1024); + + if (readlink("/proc/self/exe", cwd, 1024) <= 0) { + } + + char *path_end = strrchr(cwd, '/'); + if (path_end != NULL) { + *path_end = '\0'; + } + + return std::string(cwd); +} + +class wasm_runtime_init_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + static void SetUpTestCase() + { + CWD = get_binary_path(); + WASM_FILE_1 = strdup((CWD + MAIN_WASM).c_str()); + AOT_FILE_1 = strdup((CWD + MAIN_AOT).c_str()); + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + static void TearDownTestCase() + { + free(WASM_FILE_1); + free(AOT_FILE_1); + } +}; + +TEST_F(wasm_runtime_init_test_suite, init_and_register_natives) +{ + EXPECT_EQ(true, wasm_runtime_init()); + int n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol); + EXPECT_EQ(true, wasm_runtime_register_natives("env", native_symbols, + n_native_symbols)); + EXPECT_EQ(true, wasm_runtime_register_natives_raw("env", native_symbols, + n_native_symbols)); + wasm_runtime_destroy(); +} + +TEST_F(wasm_runtime_init_test_suite, init_thread_env_destroy_thread_env) +{ + EXPECT_EQ(true, wasm_runtime_init_thread_env()); + wasm_runtime_destroy_thread_env(); +} + +TEST_F(wasm_runtime_init_test_suite, wasm_runtime_full_init) +{ + RuntimeInitArgs init_args; + unsigned char *wasm_file_buf; + uint32 wasm_file_size; + wasm_module_t module = nullptr; + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + EXPECT_EQ(true, wasm_runtime_full_init(&init_args)); + wasm_runtime_destroy(); + init_args.n_native_symbols = 1; + EXPECT_EQ(true, wasm_runtime_full_init(&init_args)); + wasm_runtime_destroy(); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = (void *)malloc; + init_args.mem_alloc_option.allocator.realloc_func = (void *)realloc; + init_args.mem_alloc_option.allocator.free_func = (void *)free; + EXPECT_EQ(true, wasm_runtime_full_init(&init_args)); + wasm_runtime_destroy(); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = (void *)os_malloc; + init_args.mem_alloc_option.allocator.realloc_func = (void *)os_realloc; + init_args.mem_alloc_option.allocator.free_func = (void *)os_free; + EXPECT_EQ(true, wasm_runtime_full_init(&init_args)); + /* Use valid module, and runtime need to be proper inited */ + wasm_file_buf = + (unsigned char *)bh_read_file_to_buffer(WASM_FILE_1, &wasm_file_size); + EXPECT_NE(nullptr, wasm_file_buf); + module = wasm_runtime_load(wasm_file_buf, wasm_file_size, nullptr, 0); + EXPECT_NE(nullptr, module); + EXPECT_EQ(true, wasm_runtime_register_module_internal( + "module", module, wasm_file_buf, wasm_file_size, nullptr, 0)); + wasm_runtime_destroy(); + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = NULL; + init_args.mem_alloc_option.pool.heap_size = 0; + EXPECT_EQ(false, wasm_runtime_full_init(&init_args)); +} diff --git a/tests/unit/shared-utils/CMakeLists.txt b/tests/unit/shared-utils/CMakeLists.txt new file mode 100644 index 000000000..c5a43dd0e --- /dev/null +++ b/tests/unit/shared-utils/CMakeLists.txt @@ -0,0 +1,30 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-shared-utils) + +add_definitions (-DRUN_ON_LINUX) + +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 0) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${WAMR_RUNTIME_LIB_SOURCE} +) + +add_executable (shared_utils_test ${unit_test_sources}) + +target_link_libraries (shared_utils_test gtest_main) + +gtest_discover_tests(shared_utils_test) diff --git a/tests/unit/shared-utils/bh_assert_test.cc b/tests/unit/shared-utils/bh_assert_test.cc new file mode 100644 index 000000000..faa7a807b --- /dev/null +++ b/tests/unit/shared-utils/bh_assert_test.cc @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_assert.h" + +class bh_assert_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} +}; + +TEST_F(bh_assert_test_suite, bh_assert_internal) +{ + bh_assert_internal(6, "file_name_test", 6, "expr_string_test"); + + // Test abnormal cases. + EXPECT_DEATH(bh_assert_internal(0, "file_name_test", 1, "expr_string_test"), + ""); + EXPECT_DEATH(bh_assert_internal(0, nullptr, 2, "expr_string_test"), ""); + EXPECT_DEATH(bh_assert_internal(0, "file_name_test", 3, nullptr), ""); +} diff --git a/tests/unit/shared-utils/bh_common_test.cc b/tests/unit/shared-utils/bh_common_test.cc new file mode 100644 index 000000000..1d1cb528d --- /dev/null +++ b/tests/unit/shared-utils/bh_common_test.cc @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_common.h" + +class bh_common_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +#define STR_TEST "test" + +TEST_F(bh_common_test_suite, wa_strdup) +{ + EXPECT_EQ(nullptr, wa_strdup(nullptr)); + EXPECT_NE(nullptr, wa_strdup(STR_TEST)); +} + +TEST_F(bh_common_test_suite, b_strcpy_s) +{ + char dest[10] = { 0 }; + + EXPECT_EQ(0, b_strcpy_s(dest, sizeof(dest), STR_TEST)); + + // Test abnormal cases. + EXPECT_EQ(-1, b_strcpy_s(nullptr, 0, nullptr)); + EXPECT_EQ(-1, b_strcpy_s(dest, sizeof(dest), nullptr)); + EXPECT_EQ(-1, b_strcpy_s(dest, 0, STR_TEST)); +} + +TEST_F(bh_common_test_suite, b_strcat_s) +{ + char dest[10] = { 0 }; + + EXPECT_EQ(0, b_strcat_s(dest, sizeof(dest), STR_TEST)); + + // Test abnormal cases. + EXPECT_EQ(-1, b_strcat_s(nullptr, 0, nullptr)); + EXPECT_EQ(-1, b_strcat_s(dest, sizeof(dest), nullptr)); + EXPECT_EQ(-1, b_strcat_s(dest, 0, STR_TEST)); +} + +TEST_F(bh_common_test_suite, bh_strdup) +{ + EXPECT_NE(nullptr, bh_strdup(STR_TEST)); + EXPECT_EQ(nullptr, bh_strdup(nullptr)); +} + +TEST_F(bh_common_test_suite, b_memmove_s) +{ + char dest[10] = { 0 }; + + EXPECT_EQ(0, b_memmove_s(dest, sizeof(dest), STR_TEST, sizeof(STR_TEST))); + + // Test abnormal cases. + EXPECT_EQ(0, b_memmove_s(dest, sizeof(dest), STR_TEST, 0)); + EXPECT_EQ(0, b_memmove_s(nullptr, sizeof(dest), STR_TEST, 0)); + + EXPECT_EQ(0, b_memmove_s(dest, sizeof(dest), nullptr, 0)); + EXPECT_EQ(-1, b_memmove_s(dest, sizeof(dest), STR_TEST, sizeof(dest) + 1)); +} + +TEST_F(bh_common_test_suite, b_memcpy_s) +{ + char dest[10] = { 0 }; + + EXPECT_EQ(0, b_memcpy_s(dest, sizeof(dest), STR_TEST, sizeof(STR_TEST))); + + // Test abnormal cases. + EXPECT_EQ(0, b_memcpy_s(dest, sizeof(dest), STR_TEST, 0)); + EXPECT_EQ(-1, + b_memcpy_s(nullptr, sizeof(dest), STR_TEST, sizeof(STR_TEST))); + EXPECT_EQ(-1, b_memcpy_s(dest, sizeof(dest), nullptr, sizeof(STR_TEST))); + EXPECT_EQ(-1, b_memcpy_s(dest, sizeof(dest), STR_TEST, sizeof(dest) + 1)); +} diff --git a/tests/unit/shared-utils/bh_hashmap_test.cc b/tests/unit/shared-utils/bh_hashmap_test.cc new file mode 100644 index 000000000..4b651ef17 --- /dev/null +++ b/tests/unit/shared-utils/bh_hashmap_test.cc @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" +#include "test_helper.h" +#include "gtest/gtest.h" +#include "bh_hashmap.h" +#include "wasm.h" +#include "wasm_export.h" + +#include + +typedef struct HashMapElem { + void *key; + void *value; + struct HashMapElem *next; +} HashMapElem; + +struct HashMap { + /* size of element array */ + uint32 size; + /* lock for elements */ + korp_mutex *lock; + /* hash function of key */ + HashFunc hash_func; + /* key equal function */ + KeyEqualFunc key_equal_func; + KeyDestroyFunc key_destroy_func; + ValueDestroyFunc value_destroy_func; + HashMapElem *elements[1]; +}; + +int DESTROY_NUM = 0; +char TRAVERSE_KEY[] = "key_1"; +char TRAVERSE_VAL[] = "val_1"; +int TRAVERSE_COMP_RES = 0; + +class bh_hashmap_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(bh_hashmap_test_suite, bh_hash_map_create) +{ + // Normally. + EXPECT_NE((HashMap *)nullptr, + bh_hash_map_create(32, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free)); + + // Illegal parameters. + EXPECT_EQ((HashMap *)nullptr, + bh_hash_map_create(65537, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free)); + EXPECT_EQ((HashMap *)nullptr, + bh_hash_map_create(65536, true, nullptr, nullptr, nullptr, + wasm_runtime_free)); + EXPECT_EQ((HashMap *)nullptr, + bh_hash_map_create(65536, true, (HashFunc)wasm_string_hash, + nullptr, nullptr, wasm_runtime_free)); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_insert) +{ + HashMap *test_hash_map = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + nullptr, wasm_runtime_free); + int num = 0; + void **p_old_key = nullptr; + void **p_old_value = nullptr; + + // Normally. + EXPECT_EQ(true, bh_hash_map_insert(test_hash_map, (void *)"key_1", + (void *)"val_1")); + num++; + // Illegal parameters. + EXPECT_EQ(false, bh_hash_map_insert(nullptr, nullptr, (void *)"val_2")); + + // Execute fail: more than 32. + for (; num <= 32; num++) { + bh_hash_map_insert(test_hash_map, (void *)&num, (void *)"val"); + } + EXPECT_EQ(false, + bh_hash_map_insert(test_hash_map, (void *)&num, (void *)"val")); + + // Remove one, insert one. + bh_hash_map_remove(test_hash_map, (void *)"key_1", p_old_key, p_old_value); + EXPECT_EQ(true, bh_hash_map_insert(test_hash_map, (void *)"key_1", + (void *)"val_1")); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_find) +{ + HashMap *test_hash_map = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + nullptr, wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + + // Normally. use_lock is false. + EXPECT_NE((void *)nullptr, + bh_hash_map_find(test_hash_map, (void *)"key_1")); + + // Execute fail. + EXPECT_EQ((void *)nullptr, + bh_hash_map_find(test_hash_map, (void *)"KEY_1")); + + // Illegal parameters. + EXPECT_EQ((void *)nullptr, bh_hash_map_find(nullptr, nullptr)); + EXPECT_EQ((void *)nullptr, bh_hash_map_find(test_hash_map, nullptr)); + + // Normally. use_lock is true. + test_hash_map = bh_hash_map_create(32, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + EXPECT_EQ((void *)nullptr, + bh_hash_map_find(test_hash_map, (void *)"KEY_1")); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_update) +{ + char old_value[10] = { 0 }; + void **p_old_value = (void **)(&old_value); + HashMap *test_hash_map = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + nullptr, wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + + // test_hash_map->lock == nullptr. Normally. + EXPECT_EQ(true, bh_hash_map_update(test_hash_map, (void *)"key_1", + (void *)"val_2", p_old_value)); + // test_hash_map->lock == nullptr. Illegal parameters. + EXPECT_EQ(false, bh_hash_map_update(nullptr, nullptr, (void *)"val_2", + p_old_value)); + EXPECT_EQ(false, bh_hash_map_update(test_hash_map, nullptr, (void *)"val_2", + p_old_value)); + EXPECT_EQ(false, + bh_hash_map_update(nullptr, nullptr, (void *)"val_2", nullptr)); + + // test_hash_map->lock == nullptr. Update non-existent elements. + EXPECT_EQ(false, bh_hash_map_update(test_hash_map, (void *)"key", + (void *)"val", p_old_value)); + + test_hash_map = bh_hash_map_create(32, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + + // test_hash_map->lock == no nullptr. Normally. + EXPECT_EQ(true, bh_hash_map_update(test_hash_map, (void *)"key_1", + (void *)"val_2", p_old_value)); + // test_hash_map->lock == no nullptr. Illegal parameters. + EXPECT_EQ(false, bh_hash_map_update(nullptr, nullptr, (void *)"val_2", + p_old_value)); + EXPECT_EQ(false, bh_hash_map_update(test_hash_map, nullptr, (void *)"val_2", + p_old_value)); +} + +void +trav_callback_fun(void *key, void *value, void *user_data) +{ + if (!strncmp(TRAVERSE_VAL, (const char *)value, 5)) { + TRAVERSE_COMP_RES = 1; + } + else { + TRAVERSE_COMP_RES = 0; + } +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_traverse) +{ + void **p_old_value = nullptr; + HashMap *test_hash_map = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + nullptr, wasm_runtime_free); + + // Normally: TRAVERSE_COMP_RES = 1. + bh_hash_map_insert(test_hash_map, (void *)TRAVERSE_KEY, + (void *)TRAVERSE_VAL); + EXPECT_EQ(true, + bh_hash_map_traverse(test_hash_map, trav_callback_fun, nullptr)); + EXPECT_EQ(1, TRAVERSE_COMP_RES); + + // Normally: TRAVERSE_COMP_RES = 0. + bh_hash_map_update(test_hash_map, (void *)TRAVERSE_KEY, (void *)"val", + p_old_value); + EXPECT_EQ(true, + bh_hash_map_traverse(test_hash_map, trav_callback_fun, nullptr)); + EXPECT_EQ(0, TRAVERSE_COMP_RES); + // Illegal parameters. + EXPECT_EQ(false, bh_hash_map_traverse(nullptr, trav_callback_fun, nullptr)); + EXPECT_EQ(false, bh_hash_map_traverse(test_hash_map, nullptr, nullptr)); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_remove) +{ + void **p_old_key = nullptr; + void **p_old_value = nullptr; + + HashMap *test_hash_map = bh_hash_map_create( + 32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + nullptr, wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + bh_hash_map_insert(test_hash_map, (void *)"key_2", (void *)"val_2"); + + // test_hash_map->lock == nullptr. Normally. + EXPECT_EQ(true, bh_hash_map_remove(test_hash_map, (void *)"key_1", + p_old_key, p_old_value)); + // test_hash_map->lock == nullptr. Remove non-existent elements. + EXPECT_EQ(false, bh_hash_map_remove(test_hash_map, (void *)"key_1", + p_old_key, p_old_value)); + // test_hash_map->lock == nullptr. Illegal parameters. + EXPECT_EQ(false, bh_hash_map_remove(nullptr, (void *)"key_2", p_old_key, + p_old_value)); + EXPECT_EQ(false, bh_hash_map_remove(test_hash_map, nullptr, p_old_key, + p_old_value)); + + test_hash_map = bh_hash_map_create(32, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + bh_hash_map_insert(test_hash_map, (void *)"key_2", (void *)"val_2"); + + // test_hash_map->lock == no nullptr. Normally. + EXPECT_EQ(true, bh_hash_map_remove(test_hash_map, (void *)"key_1", + p_old_key, p_old_value)); + // test_hash_map->lock == no nullptr. Illegal parameters. + EXPECT_EQ(false, bh_hash_map_remove(nullptr, (void *)"key_2", p_old_key, + p_old_value)); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_get_struct_size) +{ + HashMap *test_hash_map = nullptr; + uint32 size = 0; + + // No lock. + test_hash_map = bh_hash_map_create(32, false, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + size = (size_t)(&((HashMap *)0)->elements) + + (uint32)sizeof(HashMapElem *) * test_hash_map->size; + EXPECT_EQ(size, bh_hash_map_get_struct_size(test_hash_map)); + + // Has lock. + test_hash_map = bh_hash_map_create(32, true, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, + wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + size = (size_t)(&((HashMap *)0)->elements) + + (uint32)sizeof(HashMapElem *) * test_hash_map->size; + size += (uint32)sizeof(korp_mutex); + EXPECT_EQ(size, bh_hash_map_get_struct_size(test_hash_map)); +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_get_elem_struct_size) +{ + EXPECT_EQ((uint32)sizeof(HashMapElem), bh_hash_map_get_elem_struct_size()); +} + +void +destroy_func_test(void *key) +{ + DESTROY_NUM++; +} + +TEST_F(bh_hashmap_test_suite, bh_hash_map_destroy) +{ + HashMap *test_hash_map = bh_hash_map_create( + 32, true, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, + destroy_func_test, wasm_runtime_free); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + bh_hash_map_insert(test_hash_map, (void *)"key_2", (void *)"val_2"); + + // test_hash_map->lock == no nullptr. Normally. + EXPECT_EQ(true, bh_hash_map_destroy(test_hash_map)); + // key_destroy_func must be called 2 times. + EXPECT_EQ(2, DESTROY_NUM); + + test_hash_map = bh_hash_map_create(32, false, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, + destroy_func_test, wasm_runtime_free); + + // test_hash_map->lock == no nullptr. Illegal parameters. + EXPECT_EQ(false, bh_hash_map_destroy(nullptr)); + // test_hash_map->lock == nullptr. + EXPECT_EQ(true, bh_hash_map_destroy(test_hash_map)); + + // key_destroy_func and value_destroy_func is nullptr. + test_hash_map = + bh_hash_map_create(32, false, (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, nullptr, nullptr); + bh_hash_map_insert(test_hash_map, (void *)"key_1", (void *)"val_1"); + bh_hash_map_insert(test_hash_map, (void *)"key_2", (void *)"val_2"); + EXPECT_EQ(true, bh_hash_map_destroy(test_hash_map)); +} + +// This fun allows inserting the same keys. +bool +string_equal_test(const char *s1, const char *s2) +{ + return false; +} + +int COUNT_ELEM = 0; + +void +fun_count_elem(void *key, void *value, void *user_data) +{ + COUNT_ELEM++; +} + +TEST_F(bh_hashmap_test_suite, bh_hashmap_thread_safety) +{ + HashMap *test_hash_map = bh_hash_map_create( + 32, true, (HashFunc)wasm_string_hash, (KeyEqualFunc)string_equal_test, + destroy_func_test, wasm_runtime_free); + int32_t i = 0; + std::vector> threads; + + // Creat 8 threads. In every thread, run the codes in brackets of + // std::async. + for (i = 0; i < 8; i++) { + threads.push_back(std::async([&] { + for (int j = 0; j < 25; j++) { + bh_hash_map_insert(test_hash_map, (void *)"key_1", + (void *)"val_1"); + } + })); + } + + // Wait all 8 threads finished. + for (auto &t : threads) { + t.wait(); + } + + // Count hash map elements. + bh_hash_map_traverse(test_hash_map, fun_count_elem, nullptr); + + EXPECT_EQ(200, COUNT_ELEM); + EXPECT_EQ(true, bh_hash_map_destroy(test_hash_map)); +} \ No newline at end of file diff --git a/tests/unit/shared-utils/bh_list_test.cc b/tests/unit/shared-utils/bh_list_test.cc new file mode 100644 index 000000000..981c52f25 --- /dev/null +++ b/tests/unit/shared-utils/bh_list_test.cc @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" + +#include "test_helper.h" +#include "gtest/gtest.h" + +class bh_list_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(bh_list_test_suite, bh_list_init) +{ + bh_list list_test; + + // Normally. + EXPECT_EQ(BH_LIST_SUCCESS, bh_list_init(&list_test)); + + // Illegal parameters. + EXPECT_EQ(BH_LIST_ERROR, bh_list_init(nullptr)); +} + +TEST_F(bh_list_test_suite, bh_list_insert) +{ + bh_list list_test; + bh_list_link elem_insert; + + // Normally. + bh_list_init(&list_test); + EXPECT_EQ(BH_LIST_SUCCESS, bh_list_insert(&list_test, &elem_insert)); + + // Illegal parameters. + EXPECT_EQ(BH_LIST_ERROR, bh_list_insert(nullptr, nullptr)); + EXPECT_EQ(BH_LIST_ERROR, bh_list_insert(&list_test, nullptr)); +} + +TEST_F(bh_list_test_suite, bh_list_remove) +{ + bh_list list_test; + bh_list_link elem_insert_1; + bh_list_link elem_insert_2; + bh_list_link elem_insert_3; + bh_list_link elem_insert_4; + + // Normally. + bh_list_init(&list_test); + bh_list_insert(&list_test, &elem_insert_1); + bh_list_insert(&list_test, &elem_insert_2); + bh_list_insert(&list_test, &elem_insert_3); + bh_list_insert(&list_test, &elem_insert_4); + EXPECT_EQ(BH_LIST_SUCCESS, bh_list_remove(&list_test, &elem_insert_1)); + + // The elem specified by prameter is not in the list. + EXPECT_EQ(BH_LIST_ERROR, bh_list_remove(&list_test, &elem_insert_1)); + + // Illegal parameters. + EXPECT_EQ(BH_LIST_ERROR, bh_list_remove(&list_test, nullptr)); + EXPECT_EQ(BH_LIST_ERROR, bh_list_remove(nullptr, nullptr)); + EXPECT_EQ(BH_LIST_ERROR, bh_list_remove(nullptr, &elem_insert_1)); +} + +TEST_F(bh_list_test_suite, bh_list_length) +{ + bh_list list_test; + bh_list_link elem_insert_1; + bh_list_link elem_insert_2; + + bh_list_init(&list_test); + + // The length is 0. + EXPECT_EQ(0, bh_list_length(&list_test)); + + // The length is 2. + bh_list_insert(&list_test, &elem_insert_1); + bh_list_insert(&list_test, &elem_insert_2); + EXPECT_EQ(2, bh_list_length(&list_test)); + + // Illegal parameters. + EXPECT_EQ(0, bh_list_length(nullptr)); +} + +TEST_F(bh_list_test_suite, bh_list_first_elem) +{ + bh_list list_test; + bh_list_link elem_insert_1; + bh_list_link elem_insert_2; + + bh_list_init(&list_test); + + // There is no element in the list. + EXPECT_EQ(nullptr, bh_list_first_elem(&list_test)); + + // There are 2 elements in the list. + bh_list_insert(&list_test, &elem_insert_1); + bh_list_insert(&list_test, &elem_insert_2); + EXPECT_EQ(&elem_insert_2, bh_list_first_elem(&list_test)); + + // Illegal parameters. + EXPECT_EQ(nullptr, bh_list_first_elem(nullptr)); +} + +TEST_F(bh_list_test_suite, bh_list_elem_next) +{ + bh_list list_test; + bh_list_link elem_insert_1; + bh_list_link elem_insert_2; + + bh_list_init(&list_test); + bh_list_insert(&list_test, &elem_insert_1); + bh_list_insert(&list_test, &elem_insert_2); + + // Normally. + EXPECT_EQ(&elem_insert_1, bh_list_elem_next(&elem_insert_2)); + + // Illegal parameters. + EXPECT_EQ(nullptr, bh_list_elem_next(nullptr)); +} diff --git a/tests/unit/shared-utils/bh_log_test.cc b/tests/unit/shared-utils/bh_log_test.cc new file mode 100644 index 000000000..250fb7926 --- /dev/null +++ b/tests/unit/shared-utils/bh_log_test.cc @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_log.h" +#include "stdio.h" + +class bh_log_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} +}; + +#define TEST_STR "This is a test." + +TEST_F(bh_log_test_suite, bh_log_set_verbose_level) +{ + bh_log_set_verbose_level(BH_LOG_LEVEL_DEBUG); +} + +TEST_F(bh_log_test_suite, bh_print_time) +{ + std::string captured; + + bh_log_set_verbose_level(BH_LOG_LEVEL_WARNING); + bh_print_time(TEST_STR); + + bh_log_set_verbose_level(BH_LOG_LEVEL_DEBUG); + testing::internal::CaptureStdout(); + bh_print_time(TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_EQ(0, strncmp(TEST_STR, captured.c_str(), strlen(TEST_STR))); + + testing::internal::CaptureStdout(); + bh_print_time(TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_EQ(0, strncmp(TEST_STR, captured.c_str(), strlen(TEST_STR))); +} + +TEST_F(bh_log_test_suite, bh_log) +{ + std::string captured; + + bh_log_set_verbose_level(BH_LOG_LEVEL_DEBUG); + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_FATAL, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, TEST_STR, captured); + + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_ERROR, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, TEST_STR, captured); + + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_WARNING, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, TEST_STR, captured); + + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_DEBUG, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, TEST_STR, captured); + + // log_verbose_level == BH_LOG_LEVEL_DEBUG, so BH_LOG_LEVEL_VERBOSE is not + // printed. + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_VERBOSE, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_EQ(nullptr, strstr(captured.c_str(), TEST_STR)); + + // After set log_verbose_level = BH_LOG_LEVEL_VERBOSE, BH_LOG_LEVEL_VERBOSE + // can be printed. + bh_log_set_verbose_level(BH_LOG_LEVEL_VERBOSE); + testing::internal::CaptureStdout(); + bh_log(BH_LOG_LEVEL_VERBOSE, __FILE__, __LINE__, TEST_STR); + captured = testing::internal::GetCapturedStdout(); + EXPECT_PRED_FORMAT2(::testing::IsSubstring, TEST_STR, captured); +} diff --git a/tests/unit/shared-utils/bh_queue_test.cc b/tests/unit/shared-utils/bh_queue_test.cc new file mode 100644 index 000000000..c540d8f36 --- /dev/null +++ b/tests/unit/shared-utils/bh_queue_test.cc @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" + +#include "bh_platform.h" + +class bh_queue_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +typedef struct bh_queue_node { + struct bh_queue_node *next; + struct bh_queue_node *prev; + unsigned short tag; + unsigned int len; + void *body; + bh_msg_cleaner msg_cleaner; +} bh_queue_node; + +struct bh_queue { + bh_queue_mutex queue_lock; + bh_queue_cond queue_wait_cond; + unsigned int cnt; + unsigned int max; + unsigned int drops; + bh_queue_node *head; + bh_queue_node *tail; + + bool exit_loop_run; +}; + +typedef enum LINK_MSG_TYPE { + COAP_TCP_RAW = 0, + COAP_UDP_RAW = 1, + REQUEST_PACKET, + RESPONSE_PACKET, + INSTALL_WASM_APP, + CBOR_GENERIC = 30, + + LINK_MSG_TYPE_MAX = 50 +} LINK_MSG_TYPE; + +typedef enum QUEUE_MSG_TYPE { + COAP_PARSED = LINK_MSG_TYPE_MAX + 1, + RESTFUL_REQUEST, + RESTFUL_RESPONSE, + TIMER_EVENT = 5, + SENSOR_EVENT = 6, + GPIO_INTERRUPT_EVENT = 7, + BLE_EVENT = 8, + JDWP_REQUEST = 9, + WD_TIMEOUT = 10, + BASE_EVENT_MAX = 100 + +} QUEUE_MSG_TYPE; + +enum { + WASM_Msg_Start = BASE_EVENT_MAX, + TIMER_EVENT_WASM, + SENSOR_EVENT_WASM, + CONNECTION_EVENT_WASM, + WIDGET_EVENT_WASM, + WASM_Msg_End = WASM_Msg_Start + 100 +}; + +// If RES_CMP == 1, the function bh_queue_enter_loop_run run error. +int RES_CMP = 0; + +TEST_F(bh_queue_test_suite, bh_queue_create) +{ + EXPECT_NE(nullptr, bh_queue_create()); +} + +TEST_F(bh_queue_test_suite, bh_queue_destroy) +{ + bh_message_t msg_ptr; + bh_queue *queue_ptr = bh_queue_create(); + + // Normally. + msg_ptr = bh_new_msg(RESTFUL_REQUEST, nullptr, 0, nullptr); + bh_post_msg2(queue_ptr, msg_ptr); + bh_queue_destroy(queue_ptr); + EXPECT_EQ(nullptr, queue_ptr->head); + + // Illegal parameters. + bh_queue_destroy(nullptr); +} + +TEST_F(bh_queue_test_suite, bh_message_payload) +{ + bh_message_t msg_ptr; + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + EXPECT_EQ("test_msg_body", bh_message_payload(msg_ptr)); +} + +TEST_F(bh_queue_test_suite, bh_message_payload_len) +{ + bh_message_t msg_ptr; + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + EXPECT_EQ(sizeof("test_msg_body"), bh_message_payload_len(msg_ptr)); +} + +TEST_F(bh_queue_test_suite, bh_message_type) +{ + bh_message_t msg_ptr; + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + EXPECT_EQ(RESTFUL_REQUEST, bh_message_type(msg_ptr)); +} + +TEST_F(bh_queue_test_suite, bh_new_msg) +{ + EXPECT_NE(nullptr, bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr)); +} + +void +msg_cleaner_test(void *) +{ + return; +} + +TEST_F(bh_queue_test_suite, bh_free_msg) +{ + bh_message_t msg_ptr; + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), (void *)msg_cleaner_test); + bh_free_msg(msg_ptr); + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + bh_free_msg(msg_ptr); + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)(uintptr_t)100, 0, nullptr); + bh_free_msg(msg_ptr); +} + +TEST_F(bh_queue_test_suite, bh_post_msg) +{ + int i = 0; + bh_queue *queue_ptr = bh_queue_create(); + bh_message_t msg_ptr; + + EXPECT_EQ(true, bh_post_msg(queue_ptr, TIMER_EVENT_WASM, nullptr, 0)); + EXPECT_EQ(1, queue_ptr->cnt); + + // queue_ptr->cnt >= queue_ptr->max. + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + for (i = 1; i <= 50; i++) { + bh_post_msg2(queue_ptr, msg_ptr); + } + EXPECT_EQ(false, bh_post_msg(queue_ptr, TIMER_EVENT_WASM, nullptr, 0)); +} + +TEST_F(bh_queue_test_suite, bh_post_msg2) +{ + bh_message_t msg_ptr; + bh_queue *queue_ptr = bh_queue_create(); + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, nullptr, 0, nullptr); + EXPECT_EQ(true, bh_post_msg2(queue_ptr, msg_ptr)); + EXPECT_EQ(1, queue_ptr->cnt); +} + +TEST_F(bh_queue_test_suite, bh_get_msg) +{ + bh_message_t msg_ptr; + bh_queue *queue_ptr = bh_queue_create(); + + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + + // queue->cnt == 0, timeout_us == 0. + EXPECT_EQ(nullptr, bh_get_msg(queue_ptr, 0)); + // queue->cnt == 0, timeout_us != 0. + bh_get_msg(queue_ptr, 1); + + bh_post_msg2(queue_ptr, msg_ptr); + EXPECT_EQ(1, queue_ptr->cnt); + bh_get_msg(queue_ptr, -1); + EXPECT_EQ(0, queue_ptr->cnt); +} + +TEST_F(bh_queue_test_suite, bh_queue_get_message_count) +{ + int i = 0, j = 0; + bh_message_t msg_ptr; + bh_queue *queue_ptr = bh_queue_create(); + + // Normally. + msg_ptr = bh_new_msg(RESTFUL_REQUEST, (void *)"test_msg_body", + sizeof("test_msg_body"), nullptr); + for (i = 1; i <= 20; i++) { + bh_post_msg2(queue_ptr, msg_ptr); + } + i = i - 1; + // The count of msg is less than queue_ptr->max. + EXPECT_EQ(i, bh_queue_get_message_count(queue_ptr)); + + // The count of msg is more than queue_ptr->max. + for (j = 1; j <= 60; j++) { + bh_post_msg2(queue_ptr, msg_ptr); + } + j = j - 1; + EXPECT_EQ(queue_ptr->max, bh_queue_get_message_count(queue_ptr)); + EXPECT_EQ(j + i - queue_ptr->max, queue_ptr->drops); + + // Illegal parameters. + EXPECT_EQ(0, bh_queue_get_message_count(nullptr)); +} + +void +bh_queue_enter_loop_run_test_fun(void *message, void *arg) +{ + static int count = 0; + RES_CMP = + strncmp("test_queue_loop", (char *)((bh_message_t)message)->body, 15); + + count++; + if (2 == count) { + bh_queue_exit_loop_run((bh_queue *)arg); + } +} + +TEST_F(bh_queue_test_suite, bh_queue_enter_loop_run) +{ + bh_queue *queue_ptr = bh_queue_create(); + bh_message_t msg_ptr1 = + bh_new_msg(RESTFUL_REQUEST, (void *)"test_queue_loop", + sizeof("test_queue_loop"), nullptr); + bh_message_t msg_ptr2 = + bh_new_msg(RESTFUL_REQUEST, (void *)"test_queue_loop", + sizeof("test_queue_loop"), nullptr); + + bh_post_msg2(queue_ptr, msg_ptr1); + bh_post_msg2(queue_ptr, msg_ptr2); + bh_queue_enter_loop_run(queue_ptr, bh_queue_enter_loop_run_test_fun, + queue_ptr); + EXPECT_EQ(0, RES_CMP); + + // Illegal parameters. + bh_queue_enter_loop_run(nullptr, bh_queue_enter_loop_run_test_fun, + queue_ptr); +} + +TEST_F(bh_queue_test_suite, bh_queue_exit_loop_run) +{ + // Illegal parameters. + bh_queue_exit_loop_run(nullptr); +} \ No newline at end of file diff --git a/tests/unit/shared-utils/bh_vector_test.cc b/tests/unit/shared-utils/bh_vector_test.cc new file mode 100644 index 000000000..3da9fba5d --- /dev/null +++ b/tests/unit/shared-utils/bh_vector_test.cc @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "test_helper.h" +#include "gtest/gtest.h" +#include "bh_platform.h" + +#include + +class bh_vector_test_suite : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +static inline void * +malloc_internal(uint64 size); + +TEST_F(bh_vector_test_suite, bh_vector_init) +{ + Vector *vector_ptr = nullptr; + + // Normally. use_lock is true. + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + EXPECT_EQ(true, bh_vector_init(vector_ptr, 6, sizeof(Vector *), true)); + // use_lock is false. + EXPECT_EQ(true, bh_vector_init(vector_ptr, 6, sizeof(Vector *), false)); + // init_length == 0. + EXPECT_EQ(true, bh_vector_init(vector_ptr, 0, sizeof(Vector *), false)); + // size_elem > UINT32_MAX. + EXPECT_EQ(true, bh_vector_init(vector_ptr, 6, UINT32_MAX + 1, false)); + // init_length > UINT32_MAX. + EXPECT_EQ(true, bh_vector_init(vector_ptr, UINT32_MAX + 1, sizeof(Vector *), + false)); + + // Illegal parameters. + EXPECT_EQ(false, bh_vector_init(nullptr, 6, sizeof(Vector *), true)); +} + +TEST_F(bh_vector_test_suite, bh_vector_set) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, "test"); + + // Normally. use_lock is true. + EXPECT_EQ(true, bh_vector_set(vector_ptr, 0, elem_buf)); + + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_set(nullptr, 0, nullptr)); + EXPECT_EQ(false, bh_vector_set(vector_ptr, 0, nullptr)); + // Illegal parameters: index >= vector->num_elems. + EXPECT_EQ(false, bh_vector_set(vector_ptr, 1, elem_buf)); + + // Normally. use_lock is false. + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), false); + bh_vector_append(vector_ptr, "test"); + EXPECT_EQ(true, bh_vector_set(vector_ptr, 0, elem_buf)); +} + +TEST_F(bh_vector_test_suite, bh_vector_get) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + char get_elem[12] = { 0 }; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, elem_buf); + + // Normally. use_lock is true. + EXPECT_EQ(true, bh_vector_get(vector_ptr, 0, get_elem)); + EXPECT_EQ(0, strncmp(elem_buf, get_elem, 11)); + + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_get(nullptr, 0, nullptr)); + EXPECT_EQ(false, bh_vector_get(vector_ptr, 0, nullptr)); + // Illegal parameters: index >= vector->num_elems. + EXPECT_EQ(false, bh_vector_get(vector_ptr, 1, get_elem)); + + // Normally. use_lock is false. + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), false); + bh_vector_append(vector_ptr, elem_buf); + EXPECT_EQ(true, bh_vector_get(vector_ptr, 0, get_elem)); + EXPECT_EQ(0, strncmp(elem_buf, get_elem, 11)); +} + +TEST_F(bh_vector_test_suite, bh_vector_insert) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + char get_elem[12] = { 0 }; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, "test"); + bh_vector_append(vector_ptr, "test"); + bh_vector_append(vector_ptr, "test"); + bh_vector_append(vector_ptr, "test"); + + // Normally. + EXPECT_EQ(true, bh_vector_insert(vector_ptr, 0, elem_buf)); + bh_vector_get(vector_ptr, 1, get_elem); + EXPECT_EQ(0, strncmp(elem_buf, get_elem, 11)); + + EXPECT_EQ(true, bh_vector_insert(vector_ptr, 2, elem_buf)); + EXPECT_EQ(true, bh_vector_insert(vector_ptr, 5, elem_buf)); + + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_insert(nullptr, 0, nullptr)); + EXPECT_EQ(false, bh_vector_insert(vector_ptr, 0, nullptr)); + EXPECT_EQ(0, strncmp(elem_buf, get_elem, 0)); + // Illegal parameters: index >= vector->num_elems. + EXPECT_EQ(false, bh_vector_insert(vector_ptr, 10, elem_buf)); + + // "if (!extend_vector(vector, vector->num_elems + 1))" == true. + vector_ptr->num_elems = UINT32_MAX + 1; + EXPECT_EQ(false, bh_vector_insert(vector_ptr, 2, elem_buf)); + + // use_lock is false. + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), false); + bh_vector_append(vector_ptr, "test"); + EXPECT_EQ(true, bh_vector_insert(vector_ptr, 0, elem_buf)); +} + +TEST_F(bh_vector_test_suite, bh_vector_append) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + char get_elem[12] = { 0 }; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + + // Normally. + EXPECT_EQ(true, bh_vector_append(vector_ptr, elem_buf)); + bh_vector_get(vector_ptr, 0, get_elem); + EXPECT_EQ(0, strncmp(elem_buf, get_elem, 11)); + + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_append(nullptr, nullptr)); + EXPECT_EQ(false, bh_vector_append(vector_ptr, nullptr)); +} + +TEST_F(bh_vector_test_suite, bh_vector_remove) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + char old_elem[12] = { 0 }; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, elem_buf); + bh_vector_append(vector_ptr, elem_buf); + bh_vector_append(vector_ptr, elem_buf); + bh_vector_append(vector_ptr, elem_buf); + + // Normally. + // Remove the first one. + EXPECT_EQ(true, bh_vector_remove(vector_ptr, 0, old_elem)); + // Remove the middle one. + EXPECT_EQ(true, bh_vector_remove(vector_ptr, 2, old_elem)); + // Remove the last one. + EXPECT_EQ(true, bh_vector_remove(vector_ptr, 1, old_elem)); + + EXPECT_EQ(true, bh_vector_remove(vector_ptr, 0, nullptr)); + + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_remove(nullptr, 0, nullptr)); + EXPECT_EQ(false, bh_vector_remove(vector_ptr, 0, nullptr)); + // Illegal parameters: index >= vector->num_elems. + EXPECT_EQ(false, bh_vector_remove(vector_ptr, 1, old_elem)); + + // use_lock is false. + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), false); + bh_vector_append(vector_ptr, elem_buf); + EXPECT_EQ(true, bh_vector_remove(vector_ptr, 0, old_elem)); +} + +TEST_F(bh_vector_test_suite, bh_vector_size) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, elem_buf); + + EXPECT_EQ(1, bh_vector_size(vector_ptr)); + EXPECT_EQ(0, bh_vector_size(nullptr)); +} + +TEST_F(bh_vector_test_suite, bh_vector_destroy) +{ + Vector *vector_ptr = nullptr; + char elem_buf[] = "test_vector"; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), true); + bh_vector_append(vector_ptr, elem_buf); + + // Normally. + EXPECT_EQ(true, bh_vector_destroy(vector_ptr)); + // Illegal parameters: nullptr. + EXPECT_EQ(false, bh_vector_destroy(nullptr)); + + // use_lock is false. + bh_vector_init(vector_ptr, 6, sizeof(elem_buf), false); + bh_vector_append(vector_ptr, elem_buf); + EXPECT_EQ(true, bh_vector_destroy(vector_ptr)); +} + +TEST_F(bh_vector_test_suite, bh_vector_thread_safety) +{ + Vector *vector_ptr = nullptr; + char elem; + int32_t i = 0; + std::vector> threads; + + vector_ptr = (Vector *)wasm_runtime_malloc(sizeof(Vector)); + memset(vector_ptr, 0, sizeof(Vector)); + bh_vector_init(vector_ptr, 6, sizeof(elem), true); + + for (i = 0; i < 8; i++) { + threads.push_back(std::async([&] { + for (int j = 0; j < 25; j++) { + bh_vector_append(vector_ptr, (void *)&elem); + } + })); + } + + for (auto &t : threads) { + t.wait(); + } + + EXPECT_EQ(bh_vector_size(vector_ptr), 200); + + // Normally. + EXPECT_EQ(true, bh_vector_destroy(vector_ptr)); +} diff --git a/tests/unit/shared-utils/shared_utils_test.cc b/tests/unit/shared-utils/shared_utils_test.cc new file mode 100644 index 000000000..82bedf32f --- /dev/null +++ b/tests/unit/shared-utils/shared_utils_test.cc @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" +#include "test_helper.h" +#include "gtest/gtest.h" + +/* Test APIs under wamr/core/shared/utils */ + +class SharedUtilsTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + virtual void SetUp() {} + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + virtual void TearDown() {} + + public: + WAMRRuntimeRAII<512 * 1024> runtime; +}; + +TEST_F(SharedUtilsTest, bh_list) {} diff --git a/tests/unit/tid-allocator/CMakeLists.txt b/tests/unit/tid-allocator/CMakeLists.txt new file mode 100644 index 000000000..be62340a3 --- /dev/null +++ b/tests/unit/tid-allocator/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) + +project (tid_allocator_tests) + +if (NOT DEFINED WAMR_BUILD_LIB_WASI_THREADS) + set (WAMR_BUILD_LIB_WASI_THREADS 1) +endif () + +if (NOT DEFINED WAMR_BUILD_INTERP) + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_PLATFORM) + string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) +endif () + +include (../unit_common.cmake) + +add_library (tid_allocator_vmlib ${WAMR_RUNTIME_LIB_SOURCE}) +add_library (wamr_gtest_main main.cpp) +target_link_libraries (wamr_gtest_main PUBLIC gtest tid_allocator_vmlib) + +function (create_wamr_unit_test test_name) + set (sources ${ARGN}) + add_executable (${test_name} ${sources}) + target_link_libraries ( + ${test_name} + wamr_gtest_main + tid_allocator_vmlib + ${LLVM_AVAILABLE_LIBS} + ) + gtest_discover_tests (${test_name}) + endfunction () + +include (${IWASM_DIR}/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake) + diff --git a/tests/unit/main.cpp b/tests/unit/tid-allocator/main.cpp similarity index 99% rename from tests/unit/main.cpp rename to tests/unit/tid-allocator/main.cpp index 63695d9ee..081676a1b 100644 --- a/tests/unit/main.cpp +++ b/tests/unit/tid-allocator/main.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ + #include #include "wasm_runtime_common.h" diff --git a/tests/unit/unit_common.cmake b/tests/unit/unit_common.cmake new file mode 100644 index 000000000..90ea2eb7c --- /dev/null +++ b/tests/unit/unit_common.cmake @@ -0,0 +1,105 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +if (NOT DEFINED WAMR_BUILD_PLATFORM) + set (WAMR_BUILD_PLATFORM "linux") +endif () + +set (UNIT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}) + +include_directories(${UNIT_ROOT_DIR}) + +enable_language (ASM) + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Debug) +endif () + +if (NOT DEFINED WAMR_BUILD_INTERP) + # Enable Interpreter by default + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_AOT) + # Enable AOT by default. + set (WAMR_BUILD_AOT 1) +endif () + +if (NOT DEFINED WAMR_BUILD_JIT) + # Disable JIT by default. + set (WAMR_BUILD_JIT 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) + # Enable libc builtin support by default + set (WAMR_BUILD_LIBC_BUILTIN 1) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_WASI) + # Enable libc wasi support by default + set (WAMR_BUILD_LIBC_WASI 1) +endif () + +if (NOT DEFINED WAMR_BUILD_MULTI_MODULE) + set (WAMR_BUILD_MULTI_MODULE 1) +endif() + +if (NOT DEFINED WAMR_BUILD_APP_FRAMEWORK) + set (WAMR_BUILD_APP_FRAMEWORK 1) +endif () + +if (COLLECT_CODE_COVERAGE EQUAL 1) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") +endif () + +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -ffunction-sections -fdata-sections \ + -Wall -Wno-unused-parameter -Wno-pedantic") + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) + +# include the build config template file +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +include_directories (${SHARED_DIR}/include + ${IWASM_DIR}/include) + +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +if (NOT (GOOGLETEST_INCLUDED EQUAL 1)) +# Prevent overriding the parent project's compiler/linker +# settings on Windows +set (gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +# Fetch Google test +include (FetchContent) +FetchContent_Declare ( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) +FetchContent_MakeAvailable (googletest) + +endif() + +# Add helper classes +include_directories(${CMAKE_CURRENT_LIST_DIR}/common) + +message ("unit_common.cmake included") + diff --git a/tests/unit/wasm-c-api/CMakeLists.txt b/tests/unit/wasm-c-api/CMakeLists.txt new file mode 100644 index 000000000..3b8884e11 --- /dev/null +++ b/tests/unit/wasm-c-api/CMakeLists.txt @@ -0,0 +1,62 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 2.9) +project (wasm_c_api_test) + +################ runtime settings ################ +set(CMAKE_BUILD_TYPE Debug) +set(WAMR_BUILD_PLATFORM "linux") + +# Resetdefault linker flags +set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# WAMR features switch +set(WAMR_BUILD_TARGET "X86_64") +set(WAMR_BUILD_INTERP 1) +set(WAMR_BUILD_AOT 0) +set(WAMR_BUILD_JIT 0) +set(WAMR_BUILD_LIBC_BUILTIN 1) +set(WAMR_BUILD_LIBC_WASI 0) +set(WAMR_BUILD_FAST_INTERP 0) + +# compiling and linking flags +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -pie -fPIE") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security -mindirect-branch-register") + +# build out vmlib +# hard code path here +set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..) +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +add_library(vmlib STATIC ${WAMR_RUNTIME_LIB_SOURCE}) +################################################ + +################ unit test related ################ +# Add googletest directly to our build. This defines +# the gtest and gtest_main targets. + +if (NOT (GOOGLETEST_INCLUDED EQUAL 1)) +# Prevent overriding the parent project's compiler/linker +# settings on Windows +set (gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +# Fetch Google test +include (FetchContent) +FetchContent_Declare ( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) +FetchContent_MakeAvailable (googletest) +endif() + +enable_testing() + +add_executable(wasm_c_api_test + basic.cc +) + +target_link_libraries(wasm_c_api_test vmlib gtest_main) + +gtest_discover_tests(wasm_c_api_test) diff --git a/tests/unit/wasm-c-api/basic.cc b/tests/unit/wasm-c-api/basic.cc new file mode 100644 index 000000000..34d837dd9 --- /dev/null +++ b/tests/unit/wasm-c-api/basic.cc @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +#include "bh_platform.h" +#include "wasm_c_api.h" +#include "wasm_c_api_internal.h" + +#ifndef own +#define own +#endif + +class CApiTests : public ::testing::Test +{ + protected: + void SetUp() + { + bh_log_set_verbose_level(5); + engine = nullptr; + engine = wasm_engine_new(); + ASSERT_NE(nullptr, engine); + } + + void TearDown() { wasm_engine_delete(engine); } + + wasm_engine_t *engine; +}; + +TEST_F(CApiTests, empty) {} + +TEST_F(CApiTests, wasm_engine_t) +{ + wasm_engine_t *engine1 = wasm_engine_new(); + wasm_engine_t *engine2 = wasm_engine_new(); + EXPECT_EQ(engine1, engine2); + /* TearDown() will delete it */ +} + +TEST_F(CApiTests, wasm_store_t) +{ + wasm_engine_t *engine = wasm_engine_new(); + wasm_store_t *store1 = wasm_store_new(engine); + EXPECT_NE(nullptr, store1); + EXPECT_NE(nullptr, store1->modules->data); + + wasm_store_t *store2 = wasm_store_new(engine); + EXPECT_NE(store1, store2); + EXPECT_NE(store1->modules->data, store2->modules->data); + + wasm_store_delete(store1); + wasm_store_delete(store2); + + store1 = wasm_store_new(engine); + EXPECT_NE(nullptr, store1); + wasm_store_delete(store1); +} + +TEST_F(CApiTests, wasm_byte_vec_t) +{ + wasm_byte_vec_t byte_vec = { 0 }; + wasm_byte_vec_new_uninitialized(&byte_vec, 10); + EXPECT_NE(nullptr, byte_vec.data); + EXPECT_EQ(10, byte_vec.size); + + byte_vec.data[0] = (wasm_byte_t)'a'; + byte_vec.data[1] = (wasm_byte_t)'b'; + byte_vec.data[2] = (wasm_byte_t)'c'; + EXPECT_STREQ("abc", (char *)byte_vec.data); + + byte_vec.data[5] = (wasm_byte_t)'d'; + byte_vec.data[6] = (wasm_byte_t)'e'; + byte_vec.data[7] = (wasm_byte_t)'f'; + EXPECT_STREQ("def", (char *)(byte_vec.data + 5)); + + wasm_byte_vec_delete(&byte_vec); + EXPECT_EQ(nullptr, byte_vec.data); + EXPECT_EQ(0, byte_vec.size); +} + +TEST_F(CApiTests, wasm_valtype_vec_t) +{ + wasm_valtype_vec_t tuple1 = { 0 }; + wasm_valtype_vec_new_uninitialized(&tuple1, 128); + EXPECT_NE(nullptr, tuple1.data); + EXPECT_EQ(128, tuple1.size); + + wasm_valtype_t *val_type_1 = wasm_valtype_new_i32(); + tuple1.data[0] = val_type_1; + EXPECT_EQ(WASM_I32, wasm_valtype_kind(*(tuple1.data + 0))); + wasm_valtype_vec_delete(&tuple1); + wasm_valtype_delete(val_type_1); + + wasm_valtype_t *val_types[5] = { + wasm_valtype_new_i32(), wasm_valtype_new_i64(), wasm_valtype_new_f32(), + wasm_valtype_new_f64(), wasm_valtype_new_funcref() + }; + + wasm_valtype_vec_t tuple2 = { 0 }; + wasm_valtype_vec_new(&tuple2, 5, val_types); + EXPECT_NE(nullptr, tuple2.data); + EXPECT_EQ(WASM_F32, wasm_valtype_kind(*(tuple2.data + 2))); + EXPECT_EQ(WASM_FUNCREF, wasm_valtype_kind(*(tuple2.data + 4))); + + wasm_valtype_vec_t tuple3 = { 0 }; + wasm_valtype_vec_copy(&tuple3, &tuple2); + + wasm_valtype_vec_delete(&tuple2); + + EXPECT_EQ(WASM_I64, wasm_valtype_kind(*(tuple3.data + 1))); + EXPECT_EQ(WASM_F64, wasm_valtype_kind(*(tuple3.data + 3))); + wasm_valtype_vec_delete(&tuple3); +} + +TEST_F(CApiTests, wasm_functype_t) +{ + wasm_functype_t *callback_type = wasm_functype_new_1_1( + wasm_valtype_new(WASM_EXTERNREF), wasm_valtype_new(WASM_FUNCREF)); + EXPECT_EQ(WASM_EXTERNREF, + wasm_valtype_kind(*(wasm_functype_params(callback_type)->data))); + wasm_functype_delete(callback_type); + + callback_type = wasm_functype_new_0_0(); + wasm_functype_delete(callback_type); + + callback_type = wasm_functype_new_0_1(wasm_valtype_new(WASM_EXTERNREF)); + const wasm_valtype_vec_t *results = wasm_functype_results(callback_type); + EXPECT_EQ(WASM_EXTERNREF, wasm_valtype_kind(*(results->data))); + wasm_functype_delete(callback_type); + + callback_type = wasm_functype_new_1_0(wasm_valtype_new(WASM_EXTERNREF)); + EXPECT_EQ(WASM_EXTERNREF, + wasm_valtype_kind(*(wasm_functype_params(callback_type)->data))); + wasm_functype_delete(callback_type); + + wasm_functype_t *func_type1 = wasm_functype_new_2_2( + wasm_valtype_new(WASM_I32), wasm_valtype_new(WASM_I64), + wasm_valtype_new(WASM_I32), wasm_valtype_new(WASM_I64)); + wasm_functype_t *func_type2 = wasm_functype_copy(func_type1); + wasm_functype_delete(func_type1); + + EXPECT_EQ(WASM_I64, wasm_valtype_kind( + *(wasm_functype_results(func_type2)->data + 1))); + wasm_functype_delete(func_type2); +} + +TEST_F(CApiTests, wasm_globaltype_t) +{ + wasm_globaltype_t *const_f32_type = + wasm_globaltype_new(wasm_valtype_new(WASM_F32), WASM_CONST); + EXPECT_EQ(WASM_F32, + wasm_valtype_kind(wasm_globaltype_content(const_f32_type))); + + wasm_globaltype_t *cloned = wasm_globaltype_copy(const_f32_type); + wasm_globaltype_delete(const_f32_type); + + EXPECT_EQ(WASM_F32, wasm_valtype_kind(wasm_globaltype_content(cloned))); + + wasm_globaltype_delete(cloned); +} + +static wasm_trap_t * +test_func(const wasm_val_vec_t *args, own wasm_val_vec_t *results) +{ + return NULL; +} + +TEST_F(CApiTests, wasm_func_t) +{ + wasm_valtype_t *types[4] = { wasm_valtype_new_i32(), wasm_valtype_new_i64(), + wasm_valtype_new_i64(), + wasm_valtype_new_i32() }; + wasm_valtype_vec_t tuple1 = { 0 }, tuple2 = { 0 }; + wasm_valtype_vec_new(&tuple1, 4, types); + wasm_valtype_vec_copy(&tuple2, &tuple1); + wasm_functype_t *callback_type = wasm_functype_new(&tuple1, &tuple2); + + wasm_store_t *store = wasm_store_new(engine); + wasm_func_t *callback_func = wasm_func_new(store, callback_type, test_func); + wasm_functype_delete(callback_type); + + callback_type = callback_func->type; + EXPECT_EQ(WASM_I32, wasm_valtype_kind( + *(wasm_functype_params(callback_type)->data + 0))); + EXPECT_EQ(WASM_I32, wasm_valtype_kind( + *(wasm_functype_results(callback_type)->data + 3))); + wasm_func_delete(callback_func); + wasm_store_delete(store); +} diff --git a/tests/unit/wasm-c-api/run.sh b/tests/unit/wasm-c-api/run.sh new file mode 100755 index 000000000..1b0d88e36 --- /dev/null +++ b/tests/unit/wasm-c-api/run.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# ./c_api_unit_test --gtest_list_tests + +function run_one() +{ + local case=$1 + valgrind --tool=memcheck --leak-check=yes -v \ + ./c_api_unit_test --gtest_filter=CApiTests.${case} +} + +function run() +{ + valgrind --tool=memcheck --leak-check=yes -v \ + ./c_api_unit_test +} + +[[ $# -gt 0 ]] && $@ || run diff --git a/tests/unit/wasm-vm/.gitignore b/tests/unit/wasm-vm/.gitignore new file mode 100644 index 000000000..aa3883989 --- /dev/null +++ b/tests/unit/wasm-vm/.gitignore @@ -0,0 +1,2 @@ +wasm-apps/app[123]/*.wat +wasm-apps/app[123]/*.wasm \ No newline at end of file diff --git a/tests/unit/wasm-vm/CMakeLists.txt b/tests/unit/wasm-vm/CMakeLists.txt new file mode 100644 index 000000000..d13d65aac --- /dev/null +++ b/tests/unit/wasm-vm/CMakeLists.txt @@ -0,0 +1,53 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.9) + +project (test-wasm-vm) + +add_definitions (-DRUN_ON_LINUX) + +add_definitions (-Dattr_container_malloc=malloc) +add_definitions (-Dattr_container_free=free) + +set (WAMR_BUILD_APP_FRAMEWORK 1) +set (CMAKE_BUILD_TYPE Release) + +include (../unit_common.cmake) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc) + +set (UNIT_SOURCE ${source_all}) + +set (unit_test_sources + ${UNIT_SOURCE} + ${PLATFORM_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${LIB_HOST_AGENT_SOURCE} + ${NATIVE_INTERFACE_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${LIBC_WASI_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} + ${UNCOMMON_SHARED_SOURCE} + ) + +# Now simply link against gtest or gtest_main as needed. Eg +add_executable(wasm_vm_test ${unit_test_sources}) + +target_link_libraries(wasm_vm_test ${LLVM_AVAILABLE_LIBS} gtest_main) + +add_custom_command(TARGET wasm_vm_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps/app4/*.wasm + ${PROJECT_BINARY_DIR}/ + COMMENT "Copy wasm files to the output directory" +) + +gtest_discover_tests(wasm_vm_test) diff --git a/tests/unit/wasm-vm/wasm-apps/app1.wast b/tests/unit/wasm-vm/wasm-apps/app1.wast new file mode 100644 index 000000000..aea3a8792 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app1.wast @@ -0,0 +1,106 @@ +(module + (type $0 (func (param i32) (result i32))) + (type $1 (func (param i32 i32) (result i32))) + (type $2 (func (param i32))) + (type $3 (func (param i32 i32 i32) (result i32))) + (type $4 (func)) + (type $5 (func (result i32))) + (import "env" "malloc" (func $13 (param i32) (result i32))) + (import "env" "calloc" (func $14 (param i32 i32) (result i32))) + (import "env" "free" (func $15 (param i32))) + (import "env" "memcpy" (func $16 (param i32 i32 i32) (result i32))) + (import "env" "strdup" (func $17 (param i32) (result i32))) + (memory $6 1) + (global $7 i32 (i32.const 1024)) + (global $8 i32 (i32.const 1024)) + (global $9 i32 (i32.const 1024)) + (global $10 i32 (i32.const 5120)) + (global $11 i32 (i32.const 0)) + (global $12 i32 (i32.const 1)) + (export "memory" (memory $6)) + (export "__wasm_call_ctors" (func $18)) + (export "on_init" (func $18)) + (export "my_sqrt" (func $19)) + (export "null_pointer" (func $20)) + (export "my_malloc" (func $21)) + (export "my_calloc" (func $22)) + (export "my_free" (func $23)) + (export "my_memcpy" (func $24)) + (export "my_strdup" (func $25)) + (export "__dso_handle" (global $7)) + (export "__data_end" (global $8)) + (export "__global_base" (global $9)) + (export "__heap_base" (global $10)) + (export "__memory_base" (global $11)) + (export "__table_base" (global $12)) + + (func $18 (type $4) + nop + ) + + (func $19 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $1 + local.get $1 + i32.mul + local.get $0 + local.get $0 + i32.mul + i32.add + ) + + (func $20 (type $5) + (result i32) + i32.const 0 + ) + + (func $21 (type $0) + (param $0 i32) + (result i32) + local.get $0 + call $13 + ) + + (func $22 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $0 + local.get $1 + call $14 + ) + + (func $23 (type $2) + (param $0 i32) + local.get $0 + call $15 + ) + + (func $24 (type $3) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $16 + ) + + (func $25 (type $0) + (param $0 i32) + (result i32) + local.get $0 + call $17 + ) + + ;;(custom_section "producers" + ;; (after code) + ;; "\01\0cprocessed-by\01\05clangV11.0.0 (ht" + ;; "tps://github.com/llvm/llvm-proje" + ;; "ct 176249bd6732a8044d457092ed932" + ;; "768724a6f06)") + + ) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/app1/main.c b/tests/unit/wasm-vm/wasm-apps/app1/main.c new file mode 100644 index 000000000..0090d105f --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app1/main.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include + +void +on_init() +{} + +int +my_sqrt(int x, int y) +{ + return x * x + y * y; +} + +void * +null_pointer() +{ + void *ptr = NULL; + return ptr; +} + +void * +my_malloc(int size) +{ + return malloc(size); +} + +void * +my_calloc(int nmemb, int size) +{ + return calloc(nmemb, size); +} + +void +my_free(void *ptr) +{ + return free(ptr); +} + +void * +my_memcpy(void *dst, void *src, int size) +{ + return memcpy(dst, src, size); +} + +char * +my_strdup(const char *s) +{ + return strdup(s); +} diff --git a/tests/unit/wasm-vm/wasm-apps/app1_wasm.h b/tests/unit/wasm-vm/wasm-apps/app1_wasm.h new file mode 100644 index 000000000..2b20b39f9 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app1_wasm.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +unsigned char app1_wasm[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x1E, 0x06, 0x60, + 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x01, + 0x7F, 0x00, 0x60, 0x03, 0x7F, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x01, 0x7F, 0x02, 0x40, 0x05, 0x03, 0x65, 0x6E, 0x76, 0x06, + 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, + 0x06, 0x63, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x01, 0x03, 0x65, 0x6E, + 0x76, 0x04, 0x66, 0x72, 0x65, 0x65, 0x00, 0x02, 0x03, 0x65, 0x6E, 0x76, + 0x06, 0x6D, 0x65, 0x6D, 0x63, 0x70, 0x79, 0x00, 0x03, 0x03, 0x65, 0x6E, + 0x76, 0x06, 0x73, 0x74, 0x72, 0x64, 0x75, 0x70, 0x00, 0x00, 0x03, 0x09, + 0x08, 0x04, 0x01, 0x05, 0x00, 0x01, 0x02, 0x03, 0x00, 0x05, 0x03, 0x01, + 0x00, 0x01, 0x06, 0x23, 0x06, 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, + 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, + 0x00, 0x41, 0x80, 0x28, 0x0B, 0x7F, 0x00, 0x41, 0x00, 0x0B, 0x7F, 0x00, + 0x41, 0x01, 0x0B, 0x07, 0xD4, 0x01, 0x10, 0x06, 0x6D, 0x65, 0x6D, 0x6F, + 0x72, 0x79, 0x02, 0x00, 0x11, 0x5F, 0x5F, 0x77, 0x61, 0x73, 0x6D, 0x5F, + 0x63, 0x61, 0x6C, 0x6C, 0x5F, 0x63, 0x74, 0x6F, 0x72, 0x73, 0x00, 0x05, + 0x07, 0x6F, 0x6E, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x00, 0x05, 0x07, 0x6D, + 0x79, 0x5F, 0x73, 0x71, 0x72, 0x74, 0x00, 0x06, 0x0C, 0x6E, 0x75, 0x6C, + 0x6C, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x00, 0x07, 0x09, + 0x6D, 0x79, 0x5F, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x08, 0x09, + 0x6D, 0x79, 0x5F, 0x63, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x09, 0x07, + 0x6D, 0x79, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x00, 0x0A, 0x09, 0x6D, 0x79, + 0x5F, 0x6D, 0x65, 0x6D, 0x63, 0x70, 0x79, 0x00, 0x0B, 0x09, 0x6D, 0x79, + 0x5F, 0x73, 0x74, 0x72, 0x64, 0x75, 0x70, 0x00, 0x0C, 0x0C, 0x5F, 0x5F, + 0x64, 0x73, 0x6F, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x03, 0x00, + 0x0A, 0x5F, 0x5F, 0x64, 0x61, 0x74, 0x61, 0x5F, 0x65, 0x6E, 0x64, 0x03, + 0x01, 0x0D, 0x5F, 0x5F, 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x5F, 0x62, + 0x61, 0x73, 0x65, 0x03, 0x02, 0x0B, 0x5F, 0x5F, 0x68, 0x65, 0x61, 0x70, + 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x03, 0x0D, 0x5F, 0x5F, 0x6D, 0x65, + 0x6D, 0x6F, 0x72, 0x79, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x04, 0x0C, + 0x5F, 0x5F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x62, 0x61, 0x73, 0x65, + 0x03, 0x05, 0x0A, 0x41, 0x08, 0x03, 0x00, 0x01, 0x0B, 0x0D, 0x00, 0x20, + 0x01, 0x20, 0x01, 0x6C, 0x20, 0x00, 0x20, 0x00, 0x6C, 0x6A, 0x0B, 0x04, + 0x00, 0x41, 0x00, 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x00, 0x0B, 0x08, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, 0x01, 0x0B, 0x06, 0x00, 0x20, 0x00, + 0x10, 0x02, 0x0B, 0x0A, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, + 0x03, 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x04, 0x0B, 0x00, 0x76, 0x09, + 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x01, 0x0C, 0x70, + 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2D, 0x62, 0x79, 0x01, + 0x05, 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x56, 0x31, 0x31, 0x2E, 0x30, 0x2E, + 0x30, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x6C, 0x6C, + 0x76, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, 0x2D, 0x70, 0x72, 0x6F, 0x6A, + 0x65, 0x63, 0x74, 0x20, 0x31, 0x37, 0x36, 0x32, 0x34, 0x39, 0x62, 0x64, + 0x36, 0x37, 0x33, 0x32, 0x61, 0x38, 0x30, 0x34, 0x34, 0x64, 0x34, 0x35, + 0x37, 0x30, 0x39, 0x32, 0x65, 0x64, 0x39, 0x33, 0x32, 0x37, 0x36, 0x38, + 0x37, 0x32, 0x34, 0x61, 0x36, 0x66, 0x30, 0x36, 0x29 +}; diff --git a/tests/unit/wasm-vm/wasm-apps/app2.wast b/tests/unit/wasm-vm/wasm-apps/app2.wast new file mode 100644 index 000000000..c5ea06eaa --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app2.wast @@ -0,0 +1,311 @@ +(module + (type $0 (func (param i32 i32 i32) (result i32))) + (type $1 (func (param i32 i32) (result i32))) + (type $2 (func (param i32) (result i32))) + (type $3 (func (param i32))) + (type $4 (func (param i32 i32 i32 i32) (result i32))) + (type $5 (func)) + (type $6 (func (result i32))) + (import "env" "malloc" (func $15 (param i32) (result i32))) + (import "env" "calloc" (func $16 (param i32 i32) (result i32))) + (import "env" "free" (func $17 (param i32))) + (import "env" "memcpy" (func $18 (param i32 i32 i32) (result i32))) + (import "env" "strdup" (func $19 (param i32) (result i32))) + (import "env" "memcmp" (func $20 (param i32 i32 i32) (result i32))) + (import "env" "printf" (func $21 (param i32 i32) (result i32))) + (import "env" "sprintf" (func $22 (param i32 i32 i32) (result i32))) + (import "env" "snprintf" (func $23 (param i32 i32 i32 i32) (result i32))) + (import "env" "puts" (func $24 (param i32) (result i32))) + (import "env" "putchar" (func $25 (param i32) (result i32))) + (import "env" "memmove" (func $26 (param i32 i32 i32) (result i32))) + (import "env" "memset" (func $27 (param i32 i32 i32) (result i32))) + (import "env" "strchr" (func $28 (param i32 i32) (result i32))) + (import "env" "strcmp" (func $29 (param i32 i32) (result i32))) + (import "env" "strcpy" (func $30 (param i32 i32) (result i32))) + (import "env" "strlen" (func $31 (param i32) (result i32))) + (import "env" "strncmp" (func $32 (param i32 i32 i32) (result i32))) + (import "env" "strncpy" (func $33 (param i32 i32 i32) (result i32))) + (memory $7 1) + (global $8 (mut i32) (i32.const 5120)) + (global $9 i32 (i32.const 1024)) + (global $10 i32 (i32.const 1024)) + (global $11 i32 (i32.const 1024)) + (global $12 i32 (i32.const 5120)) + (global $13 i32 (i32.const 0)) + (global $14 i32 (i32.const 1)) + (export "memory" (memory $7)) + (export "__wasm_call_ctors" (func $34)) + (export "on_init" (func $34)) + (export "my_sqrt" (func $35)) + (export "null_pointer" (func $36)) + (export "my_malloc" (func $37)) + (export "my_calloc" (func $38)) + (export "my_free" (func $39)) + (export "my_memcpy" (func $40)) + (export "my_strdup" (func $41)) + (export "my_memcmp" (func $42)) + (export "my_printf" (func $43)) + (export "my_sprintf" (func $44)) + (export "my_snprintf" (func $45)) + (export "my_puts" (func $46)) + (export "my_putchar" (func $47)) + (export "my_memmove" (func $48)) + (export "my_memset" (func $49)) + (export "my_strchr" (func $50)) + (export "my_strcmp" (func $51)) + (export "my_strcpy" (func $52)) + (export "my_strlen" (func $53)) + (export "my_strncmp" (func $54)) + (export "my_strncpy" (func $55)) + (export "__dso_handle" (global $9)) + (export "__data_end" (global $10)) + (export "__global_base" (global $11)) + (export "__heap_base" (global $12)) + (export "__memory_base" (global $13)) + (export "__table_base" (global $14)) + + (func $34 (type $5) + nop + ) + + (func $35 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $1 + local.get $1 + i32.mul + local.get $0 + local.get $0 + i32.mul + i32.add + ) + + (func $36 (type $6) + (result i32) + i32.const 0 + ) + + (func $37 (type $2) + (param $0 i32) + (result i32) + local.get $0 + call $15 + ) + + (func $38 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $0 + local.get $1 + call $16 + ) + + (func $39 (type $3) + (param $0 i32) + local.get $0 + call $17 + ) + + (func $40 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $18 + ) + + (func $41 (type $2) + (param $0 i32) + (result i32) + local.get $0 + call $19 + ) + + (func $42 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $20 + ) + + (func $43 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + (local $2 i32) + global.get $8 + i32.const 16 + i32.sub + local.tee $2 + global.set $8 + local.get $2 + local.get $1 + i32.store + local.get $0 + local.get $2 + call $21 + local.get $2 + i32.const 16 + i32.add + global.set $8 + ) + + (func $44 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + (local $3 i32) + global.get $8 + i32.const 16 + i32.sub + local.tee $3 + global.set $8 + local.get $3 + local.get $2 + i32.store + local.get $0 + local.get $1 + local.get $3 + call $22 + local.get $3 + i32.const 16 + i32.add + global.set $8 + ) + + (func $45 (type $4) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (param $3 i32) + (result i32) + (local $4 i32) + global.get $8 + i32.const 16 + i32.sub + local.tee $4 + global.set $8 + local.get $4 + local.get $3 + i32.store + local.get $0 + local.get $1 + local.get $2 + local.get $4 + call $23 + local.get $4 + i32.const 16 + i32.add + global.set $8 + ) + + (func $46 (type $2) + (param $0 i32) + (result i32) + local.get $0 + call $24 + ) + + (func $47 (type $2) + (param $0 i32) + (result i32) + local.get $0 + call $25 + ) + + (func $48 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $26 + ) + + (func $49 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $27 + ) + + (func $50 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $0 + local.get $1 + call $28 + ) + + (func $51 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $0 + local.get $1 + call $29 + ) + + (func $52 (type $1) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $0 + local.get $1 + call $30 + ) + + (func $53 (type $2) + (param $0 i32) + (result i32) + local.get $0 + call $31 + ) + + (func $54 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $32 + ) + + (func $55 (type $0) + (param $0 i32) + (param $1 i32) + (param $2 i32) + (result i32) + local.get $0 + local.get $1 + local.get $2 + call $33 + ) + + ;;(custom_section "producers" + ;; (after code) + ;; "\01\0cprocessed-by\01\05clangV11.0.0 (ht" + ;; "tps://github.com/llvm/llvm-proje" + ;; "ct 176249bd6732a8044d457092ed932" + ;; "768724a6f06)") + + ) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/app2/main.c b/tests/unit/wasm-vm/wasm-apps/app2/main.c new file mode 100644 index 000000000..160d834a5 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app2/main.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include + +void +on_init() +{} + +int +my_sqrt(int x, int y) +{ + return x * x + y * y; +} + +void * +null_pointer() +{ + void *ptr = NULL; + return ptr; +} + +void * +my_malloc(int size) +{ + return malloc(size); +} + +void * +my_calloc(int nmemb, int size) +{ + return calloc(nmemb, size); +} + +void +my_free(void *ptr) +{ + free(ptr); +} + +void * +my_memcpy(void *dst, void *src, int size) +{ + return memcpy(dst, src, size); +} + +char * +my_strdup(const char *s) +{ + return strdup(s); +} + +int +my_memcmp(const void *buf1, const void *buf2, int size) +{ + return memcmp(buf1, buf2, size); +} + +int +my_printf(const char *format, char *s) +{ + return printf(format, s); +} + +int +my_sprintf(char *buf1, const char *format, char *buf2) +{ + return sprintf(buf1, format, buf2); +} + +int +my_snprintf(char *buf1, int size, const char *format, char *buf2) +{ + return snprintf(buf1, size, format, buf2); +} + +int +my_puts(const char *s) +{ + return puts(s); +} + +int +my_putchar(int s) +{ + return putchar(s); +} + +void * +my_memmove(void *buf1, const void *buf2, int size) +{ + return memmove(buf1, buf2, size); +} + +void * +my_memset(void *buf, int c, int size) +{ + return memset(buf, c, size); +} + +char * +my_strchr(const char *s, int c) +{ + return strchr(s, c); +} + +int +my_strcmp(const char *buf1, const char *buf2) +{ + return strcmp(buf1, buf2); +} + +char * +my_strcpy(char *buf1, const char *buf2) +{ + return strcpy(buf1, buf2); +} + +int +my_strlen(const char *s) +{ + return (int)strlen(s); +} + +int +my_strncmp(const char *buf1, const char *buf2, int n) +{ + return strncmp(buf1, buf2, n); +} + +char * +my_strncpy(char *buf1, const char *buf2, int n) +{ + return strncpy(buf1, buf2, n); +} diff --git a/tests/unit/wasm-vm/wasm-apps/app2_wasm.h b/tests/unit/wasm-vm/wasm-apps/app2_wasm.h new file mode 100644 index 000000000..d89f7e57d --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app2_wasm.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +unsigned char app2_wasm[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x26, 0x07, 0x60, + 0x03, 0x7F, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, + 0x60, 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x01, 0x7F, 0x00, 0x60, 0x04, 0x7F, + 0x7F, 0x7F, 0x7F, 0x01, 0x7F, 0x60, 0x00, 0x00, 0x60, 0x00, 0x01, 0x7F, + 0x02, 0xFB, 0x01, 0x13, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, 0x61, 0x6C, + 0x6C, 0x6F, 0x63, 0x00, 0x02, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x63, 0x61, + 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x04, 0x66, + 0x72, 0x65, 0x65, 0x00, 0x03, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, 0x65, + 0x6D, 0x63, 0x70, 0x79, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x73, + 0x74, 0x72, 0x64, 0x75, 0x70, 0x00, 0x02, 0x03, 0x65, 0x6E, 0x76, 0x06, + 0x6D, 0x65, 0x6D, 0x63, 0x6D, 0x70, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, + 0x06, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x01, 0x03, 0x65, 0x6E, + 0x76, 0x07, 0x73, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x00, 0x03, + 0x65, 0x6E, 0x76, 0x08, 0x73, 0x6E, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, + 0x00, 0x04, 0x03, 0x65, 0x6E, 0x76, 0x04, 0x70, 0x75, 0x74, 0x73, 0x00, + 0x02, 0x03, 0x65, 0x6E, 0x76, 0x07, 0x70, 0x75, 0x74, 0x63, 0x68, 0x61, + 0x72, 0x00, 0x02, 0x03, 0x65, 0x6E, 0x76, 0x07, 0x6D, 0x65, 0x6D, 0x6D, + 0x6F, 0x76, 0x65, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x6D, 0x65, + 0x6D, 0x73, 0x65, 0x74, 0x00, 0x00, 0x03, 0x65, 0x6E, 0x76, 0x06, 0x73, + 0x74, 0x72, 0x63, 0x68, 0x72, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, 0x06, + 0x73, 0x74, 0x72, 0x63, 0x6D, 0x70, 0x00, 0x01, 0x03, 0x65, 0x6E, 0x76, + 0x06, 0x73, 0x74, 0x72, 0x63, 0x70, 0x79, 0x00, 0x01, 0x03, 0x65, 0x6E, + 0x76, 0x06, 0x73, 0x74, 0x72, 0x6C, 0x65, 0x6E, 0x00, 0x02, 0x03, 0x65, + 0x6E, 0x76, 0x07, 0x73, 0x74, 0x72, 0x6E, 0x63, 0x6D, 0x70, 0x00, 0x00, + 0x03, 0x65, 0x6E, 0x76, 0x07, 0x73, 0x74, 0x72, 0x6E, 0x63, 0x70, 0x79, + 0x00, 0x00, 0x03, 0x17, 0x16, 0x05, 0x01, 0x06, 0x02, 0x01, 0x03, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x04, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x02, 0x00, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x29, 0x07, 0x7F, + 0x01, 0x41, 0x80, 0x28, 0x0B, 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, + 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, + 0x00, 0x41, 0x80, 0x28, 0x0B, 0x7F, 0x00, 0x41, 0x00, 0x0B, 0x7F, 0x00, + 0x41, 0x01, 0x0B, 0x07, 0x81, 0x03, 0x1E, 0x06, 0x6D, 0x65, 0x6D, 0x6F, + 0x72, 0x79, 0x02, 0x00, 0x11, 0x5F, 0x5F, 0x77, 0x61, 0x73, 0x6D, 0x5F, + 0x63, 0x61, 0x6C, 0x6C, 0x5F, 0x63, 0x74, 0x6F, 0x72, 0x73, 0x00, 0x13, + 0x07, 0x6F, 0x6E, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x00, 0x13, 0x07, 0x6D, + 0x79, 0x5F, 0x73, 0x71, 0x72, 0x74, 0x00, 0x14, 0x0C, 0x6E, 0x75, 0x6C, + 0x6C, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x65, 0x72, 0x00, 0x15, 0x09, + 0x6D, 0x79, 0x5F, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x16, 0x09, + 0x6D, 0x79, 0x5F, 0x63, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x17, 0x07, + 0x6D, 0x79, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x00, 0x18, 0x09, 0x6D, 0x79, + 0x5F, 0x6D, 0x65, 0x6D, 0x63, 0x70, 0x79, 0x00, 0x19, 0x09, 0x6D, 0x79, + 0x5F, 0x73, 0x74, 0x72, 0x64, 0x75, 0x70, 0x00, 0x1A, 0x09, 0x6D, 0x79, + 0x5F, 0x6D, 0x65, 0x6D, 0x63, 0x6D, 0x70, 0x00, 0x1B, 0x09, 0x6D, 0x79, + 0x5F, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x1C, 0x0A, 0x6D, 0x79, + 0x5F, 0x73, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x1D, 0x0B, 0x6D, + 0x79, 0x5F, 0x73, 0x6E, 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x1E, + 0x07, 0x6D, 0x79, 0x5F, 0x70, 0x75, 0x74, 0x73, 0x00, 0x1F, 0x0A, 0x6D, + 0x79, 0x5F, 0x70, 0x75, 0x74, 0x63, 0x68, 0x61, 0x72, 0x00, 0x20, 0x0A, + 0x6D, 0x79, 0x5F, 0x6D, 0x65, 0x6D, 0x6D, 0x6F, 0x76, 0x65, 0x00, 0x21, + 0x09, 0x6D, 0x79, 0x5F, 0x6D, 0x65, 0x6D, 0x73, 0x65, 0x74, 0x00, 0x22, + 0x09, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x63, 0x68, 0x72, 0x00, 0x23, + 0x09, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x63, 0x6D, 0x70, 0x00, 0x24, + 0x09, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x63, 0x70, 0x79, 0x00, 0x25, + 0x09, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x6C, 0x65, 0x6E, 0x00, 0x26, + 0x0A, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x6E, 0x63, 0x6D, 0x70, 0x00, + 0x27, 0x0A, 0x6D, 0x79, 0x5F, 0x73, 0x74, 0x72, 0x6E, 0x63, 0x70, 0x79, + 0x00, 0x28, 0x0C, 0x5F, 0x5F, 0x64, 0x73, 0x6F, 0x5F, 0x68, 0x61, 0x6E, + 0x64, 0x6C, 0x65, 0x03, 0x01, 0x0A, 0x5F, 0x5F, 0x64, 0x61, 0x74, 0x61, + 0x5F, 0x65, 0x6E, 0x64, 0x03, 0x02, 0x0D, 0x5F, 0x5F, 0x67, 0x6C, 0x6F, + 0x62, 0x61, 0x6C, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x03, 0x0B, 0x5F, + 0x5F, 0x68, 0x65, 0x61, 0x70, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x04, + 0x0D, 0x5F, 0x5F, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x5F, 0x62, 0x61, + 0x73, 0x65, 0x03, 0x05, 0x0C, 0x5F, 0x5F, 0x74, 0x61, 0x62, 0x6C, 0x65, + 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x06, 0x0A, 0x94, 0x02, 0x16, 0x03, + 0x00, 0x01, 0x0B, 0x0D, 0x00, 0x20, 0x01, 0x20, 0x01, 0x6C, 0x20, 0x00, + 0x20, 0x00, 0x6C, 0x6A, 0x0B, 0x04, 0x00, 0x41, 0x00, 0x0B, 0x06, 0x00, + 0x20, 0x00, 0x10, 0x00, 0x0B, 0x08, 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, + 0x01, 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x02, 0x0B, 0x0A, 0x00, 0x20, + 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, 0x03, 0x0B, 0x06, 0x00, 0x20, 0x00, + 0x10, 0x04, 0x0B, 0x0A, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, + 0x05, 0x0B, 0x21, 0x01, 0x01, 0x7F, 0x23, 0x00, 0x41, 0x10, 0x6B, 0x22, + 0x02, 0x24, 0x00, 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x00, 0x20, 0x00, + 0x20, 0x02, 0x10, 0x06, 0x20, 0x02, 0x41, 0x10, 0x6A, 0x24, 0x00, 0x0B, + 0x23, 0x01, 0x01, 0x7F, 0x23, 0x00, 0x41, 0x10, 0x6B, 0x22, 0x03, 0x24, + 0x00, 0x20, 0x03, 0x20, 0x02, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x01, + 0x20, 0x03, 0x10, 0x07, 0x20, 0x03, 0x41, 0x10, 0x6A, 0x24, 0x00, 0x0B, + 0x25, 0x01, 0x01, 0x7F, 0x23, 0x00, 0x41, 0x10, 0x6B, 0x22, 0x04, 0x24, + 0x00, 0x20, 0x04, 0x20, 0x03, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x01, + 0x20, 0x02, 0x20, 0x04, 0x10, 0x08, 0x20, 0x04, 0x41, 0x10, 0x6A, 0x24, + 0x00, 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x09, 0x0B, 0x06, 0x00, 0x20, + 0x00, 0x10, 0x0A, 0x0B, 0x0A, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, + 0x10, 0x0B, 0x0B, 0x0A, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, + 0x0C, 0x0B, 0x08, 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, 0x0D, 0x0B, 0x08, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, 0x0E, 0x0B, 0x08, 0x00, 0x20, 0x00, + 0x20, 0x01, 0x10, 0x0F, 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x10, 0x0B, + 0x0A, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, 0x11, 0x0B, 0x0A, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x10, 0x12, 0x0B, 0x00, 0x76, + 0x09, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x01, 0x0C, + 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2D, 0x62, 0x79, + 0x01, 0x05, 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x56, 0x31, 0x31, 0x2E, 0x30, + 0x2E, 0x30, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x6C, + 0x6C, 0x76, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, 0x2D, 0x70, 0x72, 0x6F, + 0x6A, 0x65, 0x63, 0x74, 0x20, 0x31, 0x37, 0x36, 0x32, 0x34, 0x39, 0x62, + 0x64, 0x36, 0x37, 0x33, 0x32, 0x61, 0x38, 0x30, 0x34, 0x34, 0x64, 0x34, + 0x35, 0x37, 0x30, 0x39, 0x32, 0x65, 0x64, 0x39, 0x33, 0x32, 0x37, 0x36, + 0x38, 0x37, 0x32, 0x34, 0x61, 0x36, 0x66, 0x30, 0x36, 0x29 +}; diff --git a/tests/unit/wasm-vm/wasm-apps/app3.wast b/tests/unit/wasm-vm/wasm-apps/app3.wast new file mode 100644 index 000000000..7c29ca518 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app3.wast @@ -0,0 +1,63 @@ +(module + (type $0 (func (param i32) (result i32))) + (type $1 (func)) + (type $2 (func (result i32))) + (type $3 (func (param i32 i32) (result i32))) + (import "env" "malloc" (func $11 (param i32) (result i32))) + (memory $4 1) + (global $5 i32 (i32.const 1024)) + (global $6 i32 (i32.const 1024)) + (global $7 i32 (i32.const 1024)) + (global $8 i32 (i32.const 5120)) + (global $9 i32 (i32.const 0)) + (global $10 i32 (i32.const 1)) + (export "memory" (memory $4)) + (export "__wasm_call_ctors" (func $12)) + (export "on_init" (func $12)) + (export "my_sqrt" (func $13)) + (export "null_pointer" (func $14)) + (export "my_malloc" (func $15)) + (export "__dso_handle" (global $5)) + (export "__data_end" (global $6)) + (export "__global_base" (global $7)) + (export "__heap_base" (global $8)) + (export "__memory_base" (global $9)) + (export "__table_base" (global $10)) + + (func $12 (type $1) + nop + ) + + (func $13 (type $3) + (param $0 i32) + (param $1 i32) + (result i32) + local.get $1 + local.get $1 + i32.mul + local.get $0 + local.get $0 + i32.mul + i32.add + ) + + (func $14 (type $2) + (result i32) + i32.const 0 + ) + + (func $15 (type $0) + (param $0 i32) + (result i32) + local.get $0 + call $11 + ) + + ;;(custom_section "producers" + ;; (after code) + ;; "\01\0cprocessed-by\01\05clangV11.0.0 (ht" + ;; "tps://github.com/llvm/llvm-proje" + ;; "ct 176249bd6732a8044d457092ed932" + ;; "768724a6f06)") + + ) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/app3/main.c b/tests/unit/wasm-vm/wasm-apps/app3/main.c new file mode 100644 index 000000000..000331ee9 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app3/main.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include + +void +on_init() +{} + +int +my_sqrt(int x, int y) +{ + return x * x + y * y; +} + +void * +null_pointer() +{ + void *ptr = NULL; + return ptr; +} + +void * +my_malloc(int size) +{ + return malloc(size); +} diff --git a/tests/unit/wasm-vm/wasm-apps/app3_wasm.h b/tests/unit/wasm-vm/wasm-apps/app3_wasm.h new file mode 100644 index 000000000..5c2ee5236 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app3_wasm.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +unsigned char app3_wasm[] = { + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x13, 0x04, 0x60, + 0x01, 0x7F, 0x01, 0x7F, 0x60, 0x00, 0x00, 0x60, 0x00, 0x01, 0x7F, 0x60, + 0x02, 0x7F, 0x7F, 0x01, 0x7F, 0x02, 0x0E, 0x01, 0x03, 0x65, 0x6E, 0x76, + 0x06, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x00, 0x03, 0x05, 0x04, + 0x01, 0x03, 0x02, 0x00, 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x23, 0x06, + 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, + 0x7F, 0x00, 0x41, 0x80, 0x08, 0x0B, 0x7F, 0x00, 0x41, 0x80, 0x28, 0x0B, + 0x7F, 0x00, 0x41, 0x00, 0x0B, 0x7F, 0x00, 0x41, 0x01, 0x0B, 0x07, 0xA6, + 0x01, 0x0C, 0x06, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x11, + 0x5F, 0x5F, 0x77, 0x61, 0x73, 0x6D, 0x5F, 0x63, 0x61, 0x6C, 0x6C, 0x5F, + 0x63, 0x74, 0x6F, 0x72, 0x73, 0x00, 0x01, 0x07, 0x6F, 0x6E, 0x5F, 0x69, + 0x6E, 0x69, 0x74, 0x00, 0x01, 0x07, 0x6D, 0x79, 0x5F, 0x73, 0x71, 0x72, + 0x74, 0x00, 0x02, 0x0C, 0x6E, 0x75, 0x6C, 0x6C, 0x5F, 0x70, 0x6F, 0x69, + 0x6E, 0x74, 0x65, 0x72, 0x00, 0x03, 0x09, 0x6D, 0x79, 0x5F, 0x6D, 0x61, + 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x04, 0x0C, 0x5F, 0x5F, 0x64, 0x73, 0x6F, + 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x03, 0x00, 0x0A, 0x5F, 0x5F, + 0x64, 0x61, 0x74, 0x61, 0x5F, 0x65, 0x6E, 0x64, 0x03, 0x01, 0x0D, 0x5F, + 0x5F, 0x67, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x5F, 0x62, 0x61, 0x73, 0x65, + 0x03, 0x02, 0x0B, 0x5F, 0x5F, 0x68, 0x65, 0x61, 0x70, 0x5F, 0x62, 0x61, + 0x73, 0x65, 0x03, 0x03, 0x0D, 0x5F, 0x5F, 0x6D, 0x65, 0x6D, 0x6F, 0x72, + 0x79, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x04, 0x0C, 0x5F, 0x5F, 0x74, + 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x03, 0x05, 0x0A, + 0x1F, 0x04, 0x03, 0x00, 0x01, 0x0B, 0x0D, 0x00, 0x20, 0x01, 0x20, 0x01, + 0x6C, 0x20, 0x00, 0x20, 0x00, 0x6C, 0x6A, 0x0B, 0x04, 0x00, 0x41, 0x00, + 0x0B, 0x06, 0x00, 0x20, 0x00, 0x10, 0x00, 0x0B, 0x00, 0x76, 0x09, 0x70, + 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x01, 0x0C, 0x70, 0x72, + 0x6F, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2D, 0x62, 0x79, 0x01, 0x05, + 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x56, 0x31, 0x31, 0x2E, 0x30, 0x2E, 0x30, + 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, + 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, 0x2D, 0x70, 0x72, 0x6F, 0x6A, 0x65, + 0x63, 0x74, 0x20, 0x31, 0x37, 0x36, 0x32, 0x34, 0x39, 0x62, 0x64, 0x36, + 0x37, 0x33, 0x32, 0x61, 0x38, 0x30, 0x34, 0x34, 0x64, 0x34, 0x35, 0x37, + 0x30, 0x39, 0x32, 0x65, 0x64, 0x39, 0x33, 0x32, 0x37, 0x36, 0x38, 0x37, + 0x32, 0x34, 0x61, 0x36, 0x66, 0x30, 0x36, 0x29 +}; diff --git a/tests/unit/wasm-vm/wasm-apps/app4/m1.wasm b/tests/unit/wasm-vm/wasm-apps/app4/m1.wasm new file mode 100644 index 0000000000000000000000000000000000000000..6979e1801e59855a6572e7ef1f8ce6ac836c2733 GIT binary patch literal 103 zcmXZTF$#b%5JkcFH!%r%nr-YoiKbBm1A_KmT?ET1hI%yt>a?IIn21p)bWxI}q=!jE h9T50ve9pihe5e*w7~W%s!G2`|V9*UL8%u?h zO8Gd+CeeV$HKaVcjpu(mObgU0A?=_|w(t9nGbnL^cB8fkn2@}~s=lu!$b`U@{12na B5XArh literal 0 HcmV?d00001 diff --git a/tests/unit/wasm-vm/wasm-apps/app4/m2.wat b/tests/unit/wasm-vm/wasm-apps/app4/m2.wat new file mode 100644 index 000000000..340a3436b --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app4/m2.wat @@ -0,0 +1,24 @@ +(module + (import "m1" "f1" (func $m1-f1 (result i32))) + (export "m1-f1" (func $m1-f1)) + + (import "m1" "m1" (memory $m1-m1 1 2)) + (import "m1" "t1" (table $m1-t1 0 funcref)) + (import "m1" "g1" (global $m1-g1 i32)) + + (func $f2 (export "f2") (param i32) (result i32) + (i32.add (call $m1-f1) (local.get 0)) + ) + + (func $f4 (result i32) (i32.const 3)) + + (func $f3 (export "f3") (param i32 i32) (result i32) + (i32.add + (call $m1-f1) + (i32.add + (call $f4) + (call $f2 (local.get 0)) + ) + ) + ) +) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/app4/m3.wasm b/tests/unit/wasm-vm/wasm-apps/app4/m3.wasm new file mode 100644 index 0000000000000000000000000000000000000000..ecbff3d7b62d573e3d1e527d8f433865b2462d2e GIT binary patch literal 86 zcmZQbEY4+QU|?Y6VoG3OtWRL9XRK#(U}efRWJ)t+U;xq_xrXtHIhl#YOpJ_7Abtsy V&sYGFPlxiE>w(IRn9__G7y;)b5>o&G literal 0 HcmV?d00001 diff --git a/tests/unit/wasm-vm/wasm-apps/app4/m3.wat b/tests/unit/wasm-vm/wasm-apps/app4/m3.wat new file mode 100644 index 000000000..e300121ef --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/app4/m3.wat @@ -0,0 +1,7 @@ +(module + (import "m1" "f1" (func $m1-f1 (result i32))) + (import "m1" "m1_alias" (memory $m1-m1 1 2)) + (import "m1" "t1_alias" (table $m1-t1 0 funcref)) + (import "m1" "g1_alias" (global $m1-g1 i32)) + (import "m2" "f2" (func $m2-f2 (param i32) (result i32))) +) \ No newline at end of file diff --git a/tests/unit/wasm-vm/wasm-apps/binarydump b/tests/unit/wasm-vm/wasm-apps/binarydump new file mode 100755 index 0000000000000000000000000000000000000000..e7c4d2a1da6bff79857d7b3047ccc86ef25f3a1e GIT binary patch literal 13448 zcmeHOeQ+DcbzcyYNKq0<$sduWjI~j$gpx&wlqH$^hz*d0bWll3B|(2oM4v$5NTLP- z6gY^aJ93p!R)k@la+21g>6g_s?X=VWA$J;&>UJcu%1Bm6ozjh+(X^e8;@TO|v{R-@ z6gG*4{@&g$csK$b_n*#mhO5E7eZTjyZ{O}6Z*Nz>9_Tn+<#I7qs@M~ZxJ%VO0a;hZ z-rOlziM6oR%*VE{PqS4(R^sOq5~5a3(FN&R(Hg1e23>()OO*w*RQW_j(N9}2TCj?W zkSMjcSbVZ-(GwdiR#C>d0LYGFt$$dspeIE|(epBnNlBF*v1HdE?HZ(=qBAluMOFW( zZ}baEf1xTLIO2UoSi86`QqrYz{CzV@^~?2w1@(!Fq8%2@6jgS=3_FVRlNRZob<6fD zPf^LTUGZ4|zCF9*(Z+ZzksWOuZQ0kjZ;v;V^zIh@CjX>+q^nnir1HqYQOx(_ zM{|JWpI_OqDgI8|_r9|IAOAf(^t&Hl{QTM-WUGFte&UjarknyLHlM11cU8dmSHNjL zmh=Bu1w2v#KT!b>RlwI*z+V8)@pBd*fO2s*R>0R(z>ieG8OA?C!@Z9UBvVF$4VXqe z&Qe)3!*o4kh9l4Gk)h}Hfp9F&1~P{6JR5*8!UiJoWX52_;dnd=ZX_Ku4K|QA!ci!s zV+nJBWz2MBI0ZM<2Kh>x`fxagHqwRxcyKtGkg(2{^ z5TXVf?pDg6O*UNJ(`*zh_Vu8n_KqfM;rdx$gbr73e|{^t;C;6-WvD42WeIW70DHvZoH@lf!_RMR>i({4;pttE0}?;0P= zAA#YI2kN%8-(;fpl}DuXNCX1Yn0Uiui~$e zyjT0u4}^p1du}+;a`W1B{z=VsU3=@E`9RUz8s)8S3+uaPwSVRd&4{06*Z0COpFm)J z*H=Ca$n_)9(p8Q>sM`3GEW2{<>#!?2`ym+=X8LAdfDP3#Gn%yA>DyW^JEKhmZeP); z-~ zE|AtC%lQJFFR<)=%J^F!7Yd@Gxo%R8AfnEB2p6u<%p=2bXygJPDuc6NCjuWH4CGIf zlLb=o6`iaDG&9kg&()Lc<~8c?)#K=2ekXLUeu-*ZsWwTqjZ~YVnuk2lEa?*_NRf|H zl*_)Y<$B-La-CB*0`F1h;1-Dsjc$$sZ&AiQXv^U-=5&RM0DtmHhj^C=_O2u^P^6FCTXyo_yWwtnPIh zyM-%%Xji@rWuSTOU|`-ft+uXT-3jabFht{l_goX5@4fL4w{G3az4_C3r$1Pco0+~- z<)X{>>D=GH^iQVD>Gi9etR9Ee+-A$s^c!wKR?vTnR`b7OYpw3fCy=~3*QC;==YXaA z7o?l8bj4`>-OrJ08eMC6DA&2uw=f&0qT0lYZ4Ho6?wY5x8-d$ka5o0-5FH=B<+hFrr?z=R-k5KZ8_hq%1r*r!!FgGVU?_k>8hOW31{cv4M z=Ja>aoM>lmm9WGRbuL7;$JUBW;}1hC)NWq$Kka|YpDXx#{h^MRw>`0*<6-r3Bhj8< z?rt#mPRDk7a@1(kAG`Cf{ud&8=_8Xj|BHIQb>u$i$lYy+hr<2;s*PWBY5V80AJ8A1 zFZTIQ`1}0N`Soj)i_gO!UBeKPKlvw#-Xo}_#g(z%OnA^Z!24r~aC$779ZvDaBtJ9| ziyKey#soi<2oIwcOW<8dCzKsanXzOdb3od2n?7Gsj>p3hgPTJJPi9THfFo16w;aH} z*vb-f9)cxBz>@SG#<=I5kNQ;pDsc;1COUX|Dl#$NB z58v%=;tkZNtx~jg`$2Lsmdx^DgqTR0Je#3z$1-hBEzs2yXhhV~sy7igGL(T|&BoH`asL<(rw~;n+>cn};Srup^Y9?vU85YMg)r!) zHY7Pcbv@y<<~tAHJ4iv6^7@QD0y*hFgP7(?*HeGk zv+-!%nvt3_?8!|BcRcpUR)R^V9ly^ZR-xzj)Ss(rTeqre4lP^qDCBn`r?n+h@`Mlz z`?G*oqmOawgOa-kU8F(&zlmQj`aV%2KPTkW_P6nyLQV`&*6OMM&8k+<#;>{q9{%!* zR!_rktkgVB=T>Q+mhtLNk1y?M@q3#5o`zNrhaU7>JvAb4YvDf+Kh~3woGq8-3@m40 zIRncXSkAz529`6hoPp&GEN9^VLk7;&_(Yf|B~>xYWm0jEW33cSuCnyiH~&5OEJ@`d zai#s%lcKg+^0Z!~vdJQBqmZ|j%L)y=Oo=H>0wEql5{}Q zQ<9#O^c6{+?H_4tJHQ)y`?Co%%lCTsdYc-XcV`9L{9^MyZ_}Rb7EE8K9&c`HZgP59 z%DXXpTdI6Z1hhjKDvP_BSr%VWoR@ZIZp_llW%XAvHE&Dxt6916cH=Hk^Q2UNHBzKOVOYwTlV4(hp4ia)?;JIPtx>_MF0D2IQFseN6$jho@FmCuDz{2_L} zEWU}+_L#G{nR@CiO6Y!H!G2g+M64P;PhD(j{PY~HLjLbK#)Ui+&K=Kbuf(0t?{?vT zF;4Z|=@IzSeA2lB@~{3LfEDE&uC6lU^2fl-_3JNzlb=74af)wUz^+UDmDN7f7!%*P zK;OcT^lwUBeA@z6DR1uz*#`E^1|MpRh1w~XPtqtC=P!imeM{yQ?S8q+%%2BE0+-Iu z?E+sq&kqSdOXpQL@D1oM?c!2Ve~0=7E})W&37nT87Qwu1f%fiHay%v8|-umWDFfIp0WQ9RCmJqmn7nLIpM0jG0V<@5)Em&+&Zbgr*@ zh)p`~>v6&nk$S$ZkTHBs`1i0WY{OGA#Fepc2wXBYQiJ~1<1Of-!~Y}Fk2-(1L)yGv z!Ouq&^r=_J`wo)J&!` zdN@1E#3qn|eG~8Fd-v}vuY}FEL`)ZZUb>Mm(_=VHgpDvATXe%?FtKquG|dv##oata zNk^5$)}3x9^?pQdq?tIlqz@VK6ti?K1=|0E@59~x&VU~1YDc%MKB{_2OHrn`KilQ+ z47NebCJ_gq0O6>d9?+yWt-YJ+M>>wR`aASvhY$AzLVC#G+7X}@#IdPJCM)_Z4o&%d z>X;NAj?#mnPJJ=Iq0TnSZiu$4!~w2SZE-fM6w-}o*bK{~Tn>@r?AM}nk97cS5fGs` z&v-e-)R1-7OCAd=Rgg!<93UM7 zNwrdU;y_y|r0e~ejEvMetVYM;96Co&>D_Wxx5dMm45qYo0?whQV@%Y9p}|tOLdj4u zZ)R-R4EKYYX^Rf28uo>abc%VgcWQY3t-(e!JSe%rMAqA%jp5{GEXusZ4TUp9%o`m` zz@J6Uv?al|9_{6oFgj#uBOWFLSxd!D<`v2EqUs$?f;Ej%Tq-p?N_9D*lxMU0i2NmUW>*htib&+?#kN%>)TJN;T zK-Ib&Dxx^^_Z(1K6RY;sy6CpF=ayOVJAl$t^m)i>jjedKep-H z>O^z++3nT(?vk`u@7>C#URD(SEr-2Y2VRsPI#j&M-pT*I!(P3=T$1)*R*7@8tNi_u z!(Oc`_s9=R>U)aPm&2-9_Gi*wjh}iy^GW*=nw+-cjQ=&rD1XXcowrx#@ae39y*S&y z3ZdOzt!HcK;5JH#gtp>r|0ZM}{8X6gyO}zd@6>nl@4&XsX0O)A8y^OU;?#HY--8Z? zsM=TSX#NT9zYklQYRX=%x7Gifp!EP1IUS4fsQGsRGJE@KUB0kIm=*OcZm~bAAOGR7 zFRtIYWpQ2^N~-J>T>x%xU#&OJbIU-*Db1I}a}NUYrTVYli!X4?LbYRYR$Ho0ln(h( z`%QKbb!D&C$4X4PR1~FYrrH()dHI`1tqPsduonj_{HVEa*PG!Mr|x5#4!iMF{ZY?9 Sxw;vk- literal 0 HcmV?d00001 diff --git a/tests/unit/wasm-vm/wasm-apps/build.sh b/tests/unit/wasm-vm/wasm-apps/build.sh new file mode 100755 index 000000000..dbf062ae7 --- /dev/null +++ b/tests/unit/wasm-vm/wasm-apps/build.sh @@ -0,0 +1,32 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +## build app1 +/opt/wasi-sdk/bin/clang -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -o app1/app1.wasm app1/main.c -Wl,--export-all \ + -Wl,--export=__heap_base,--export=__data_end \ + -Wl,--no-entry -nostdlib -Wl,--allow-undefined +./binarydump -o app1_wasm.h -n app1_wasm app1/app1.wasm +wavm disassemble app1/app1.wasm app1.wast +rm -f app1/app1.wasm + +## build app2 +/opt/wasi-sdk/bin/clang -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -o app2/app2.wasm app2/main.c -Wl,--export-all \ + -Wl,--export=__heap_base,--export=__data_end \ + -Wl,--no-entry -nostdlib -Wl,--allow-undefined +./binarydump -o app2_wasm.h -n app2_wasm app2/app2.wasm +wavm disassemble app2/app2.wasm app2.wast +rm -f app2/app2.wasm + +## build app3 +/opt/wasi-sdk/bin/clang -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -o app3/app3.wasm app3/main.c -Wl,--export-all \ + -Wl,--export=__heap_base,--export=__data_end \ + -Wl,--no-entry -nostdlib -Wl,--allow-undefined +./binarydump -o app3_wasm.h -n app3_wasm app3/app3.wasm +wavm disassemble app3/app3.wasm app3.wast +rm -f app3/app3.wasm diff --git a/tests/unit/wasm-vm/wasm_vm.cc b/tests/unit/wasm-vm/wasm_vm.cc new file mode 100644 index 000000000..f4f5a834d --- /dev/null +++ b/tests/unit/wasm-vm/wasm_vm.cc @@ -0,0 +1,716 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "gtest/gtest.h" +#include "bh_platform.h" +#include "bh_read_file.h" +#include "wasm_export.h" +#if WASM_ENABLE_MULTI_MODULE != 0 +#include "wasm.h" +#include "wasm_runtime.h" +#endif +#include "wasm-apps/app1_wasm.h" +#include "wasm-apps/app2_wasm.h" +#include "wasm-apps/app3_wasm.h" + +#define EightK (8 * 1024) +// To use a test fixture, derive a class from testing::Test. +class WasmVMTest : public testing::Test +{ + protected: + // You should make the members protected s.t. they can be + // accessed from sub-classes. + + // virtual void SetUp() will be called before each test is run. You + // should define it if you need to initialize the varaibles. + // Otherwise, this can be skipped. + void SetUp() + { + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); + + ASSERT_EQ(wasm_runtime_full_init(&init_args), true); + + // bh_log_set_verbose_level(5); + + clean = true; + } + + // virtual void TearDown() will be called after each test is run. + // You should define it if there is cleanup work to do. Otherwise, + // you don't have to provide it. + // + void TearDown() + { + if (clean) { + wasm_runtime_destroy(); + } + } + + public: + wasm_module_t module = NULL; + wasm_module_inst_t module_inst = NULL; + wasm_function_inst_t func_inst = NULL; + wasm_exec_env_t exec_env = NULL; + char error_buf[128]; + char global_heap_buf[512 * 1024]; + RuntimeInitArgs init_args; + bool clean = true; +}; + +TEST_F(WasmVMTest, Test_app1) +{ + unsigned argv[10]; + + ASSERT_TRUE(app1_wasm != NULL); + + /* Load module */ + module = wasm_runtime_load(app1_wasm, sizeof(app1_wasm), error_buf, + sizeof(error_buf)); + if (module == nullptr) { + printf("error: %s\n", error_buf); + } + + ASSERT_TRUE(module != NULL); + + /* Initiate module */ + module_inst = wasm_runtime_instantiate(module, 8 * 1024, 8 * 1024, + error_buf, sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + /* _on_init() function doesn't exist */ + func_inst = wasm_runtime_lookup_function(module_inst, "_on_init"); + ASSERT_TRUE(func_inst == NULL); + + /* on_init() function exists */ + func_inst = wasm_runtime_lookup_function(module_inst, "on_init"); + ASSERT_TRUE(func_inst != NULL); + + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_inst, 0, NULL) == true); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* call my_malloc */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_malloc"); + ASSERT_TRUE(func_inst != NULL); + + /* malloc with very large size */ + argv[0] = 10 * 1024; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + wasm_runtime_clear_exception(module_inst); + ASSERT_EQ(argv[0], 0); + + /* malloc 1K, should success */ + argv[0] = 1024; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* convert to native address */ + ASSERT_TRUE(wasm_runtime_validate_app_addr(module_inst, argv[0], 1)); + char *buf = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf != NULL); + + ASSERT_EQ(wasm_runtime_addr_native_to_app(module_inst, buf), argv[0]); + int32 buf_offset = argv[0]; + + /* call memcpy */ + char *buf1 = buf + 100; + memcpy(buf1, "123456", 7); + func_inst = wasm_runtime_lookup_function(module_inst, "my_memcpy"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = buf_offset + 100; + argv[2] = 7; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + ASSERT_TRUE(strcmp(buf, buf1) == 0); + + /* call strdup */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_strdup"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + + int32 buf_offset1 = argv[0]; + ASSERT_NE(buf_offset, buf_offset1); + + buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, buf_offset1); + ASSERT_TRUE(strcmp(buf, buf1) == 0); + + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + wasm_runtime_destroy_exec_env(exec_env); +} + +TEST_F(WasmVMTest, Test_app2) +{ + unsigned argv[10]; + + /* Load module */ + module = wasm_runtime_load(app2_wasm, sizeof(app2_wasm), error_buf, + sizeof(error_buf)); + + ASSERT_TRUE(module != NULL); + + /* Initiate module */ + module_inst = wasm_runtime_instantiate(module, 8 * 1024, 8 * 1024, + error_buf, sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + /* _on_init() function doesn't exist */ + func_inst = wasm_runtime_lookup_function(module_inst, "_on_init"); + ASSERT_TRUE(func_inst == NULL); + + /* on_init() function exists */ + func_inst = wasm_runtime_lookup_function(module_inst, "on_init"); + ASSERT_TRUE(func_inst != NULL); + + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_inst, 0, NULL) == true); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* call my_malloc */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_malloc"); + ASSERT_TRUE(func_inst != NULL); + + /* malloc 1K, should success */ + argv[0] = 1024; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* convert to native address */ + ASSERT_TRUE(wasm_runtime_validate_app_addr(module_inst, argv[0], 1)); + char *buf = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf != NULL); + + ASSERT_EQ(wasm_runtime_addr_native_to_app(module_inst, buf), argv[0]); + int32 buf_offset = argv[0]; + + /* call memcpy */ + char *buf1 = buf + 100; + memcpy(buf1, "123456", 7); + func_inst = wasm_runtime_lookup_function(module_inst, "my_memcpy"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = buf_offset + 100; + argv[2] = 7; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + ASSERT_TRUE(strcmp(buf, buf1) == 0); + + /* call memcmp */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_memcmp"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = buf_offset + 100; + argv[2] = 7; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + ASSERT_TRUE(argv[0] == 0); + + /* call printf */ + char *format = buf + 200; + memcpy(format, "string0 is %s", 13); + func_inst = wasm_runtime_lookup_function(module_inst, "my_printf"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = wasm_runtime_addr_native_to_app(module_inst, format); + argv[1] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(argv[0] == 17); + + /* call sprintf */ + memcpy(format, "string1 is %s", 13); + func_inst = wasm_runtime_lookup_function(module_inst, "my_sprintf"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 300; + int32 argv0_tmp = argv[0]; + argv[1] = wasm_runtime_addr_native_to_app(module_inst, format); + argv[2] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + ASSERT_TRUE( + memcmp((char *)wasm_runtime_addr_app_to_native(module_inst, argv0_tmp), + "string1 is 123456", 17) + == 0); + ASSERT_TRUE(argv[0] == 17); + + /* call snprintf */ + memcpy(format, "string2 is %s", 13); + func_inst = wasm_runtime_lookup_function(module_inst, "my_snprintf"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 400; + argv0_tmp = argv[0]; + argv[1] = 3; + argv[2] = wasm_runtime_addr_native_to_app(module_inst, format); + argv[3] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 4, argv); + + ASSERT_TRUE( + memcmp((char *)wasm_runtime_addr_app_to_native(module_inst, argv0_tmp), + "st\0", 3) + == 0); + ASSERT_TRUE(argv[0] == 17); + + /* call puts */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_puts"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + + ASSERT_TRUE(argv[0] != EOF); + + /* call putchar */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_putchar"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + + ASSERT_TRUE(argv[0] != EOF); + + /* call memmove without memory coverage*/ + func_inst = wasm_runtime_lookup_function(module_inst, "my_memmove"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 10; + argv[1] = buf_offset + 100; + argv[2] = 6; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(strcmp(buf + 100, buf1) == 0); + ASSERT_TRUE(memcmp(buf1, "123456", 6) == 0); + + /* call memmove with memory coverage*/ + func_inst = wasm_runtime_lookup_function(module_inst, "my_memmove"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 95; + argv[1] = buf_offset + 100; + argv[2] = 6; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(strcmp(buf + 100, buf1) != 0); + ASSERT_TRUE(memcmp(buf1, "123456", 6) == 0); + ASSERT_TRUE(memcmp(buf + 100, "623456", 6) == 0); + + /* call memset*/ + func_inst = wasm_runtime_lookup_function(module_inst, "my_memset"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 100; + argv[1] = 48; + argv[2] = 4; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + ASSERT_TRUE(memcmp(buf + 100, "000056", 6) == 0); + + /* call strchr*/ + func_inst = wasm_runtime_lookup_function(module_inst, "my_strchr"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = 49; // asc2 for char "1" + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + + buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf1 - buf == 0); + + /* call strcmp */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_strcmp"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + + ASSERT_TRUE(argv[0] == 0); + + argv[0] = buf_offset; + argv[1] = buf_offset + 1; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + + ASSERT_TRUE(argv[0] != 0); + + /* call strcpy */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_strcpy"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 110; + argv[1] = buf_offset; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(memcmp(buf + 110, "123456", 6) == 0); + + /* call strlen */ + buf1 = buf + 110; + memcpy(buf1, "123456\0", 7); + func_inst = wasm_runtime_lookup_function(module_inst, "my_strlen"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 110; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + + ASSERT_TRUE(argv[0] == 6); + + /* call strncmp */ + buf1 = buf + 110; + memcpy(buf1, "123457", 6); + func_inst = wasm_runtime_lookup_function(module_inst, "my_strncmp"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset; + argv[1] = buf_offset + 110; + argv[2] = 5; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + ASSERT_TRUE(argv[0] == 0); + + argv[0] = buf_offset; + argv[1] = buf_offset + 110; + argv[2] = 6; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + ASSERT_TRUE(argv[0] != 0); + + /* call strncpy */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_strncpy"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset + 130; + argv[1] = buf_offset; + argv[2] = 5; + wasm_runtime_call_wasm(exec_env, func_inst, 3, argv); + + buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(memcmp(buf, buf1, 5) == 0); + ASSERT_TRUE(memcmp(buf, buf1, 6) != 0); + + /* call _my_calloc */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_calloc"); + ASSERT_TRUE(func_inst != NULL); + /* calloc, should success */ + argv[0] = 10; + argv[1] = 4; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* convert to native address */ + ASSERT_TRUE(wasm_runtime_validate_app_addr(module_inst, argv[0], 40)); + char *buf2 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf2 != NULL); + + ASSERT_EQ(wasm_runtime_addr_native_to_app(module_inst, buf2), argv[0]); + int32 buf_offset1 = argv[0]; + + /* call _my_free */ + memcpy(buf2, "123456", 6); + func_inst = wasm_runtime_lookup_function(module_inst, "my_free"); + ASSERT_TRUE(func_inst != NULL); + argv[0] = buf_offset1; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + + ASSERT_TRUE(memcmp(buf2, "123456", 6) != 0); + + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + wasm_runtime_destroy_exec_env(exec_env); +} + +TEST_F(WasmVMTest, Test_app3) +{ + unsigned argv[10]; + + /* Load module */ + module = wasm_runtime_load(app3_wasm, sizeof(app3_wasm), error_buf, + sizeof(error_buf)); + + ASSERT_TRUE(module != NULL); + + /* Initiate module */ + module_inst = wasm_runtime_instantiate(module, 8 * 1024, 8 * 1024, + error_buf, sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024); + ASSERT_TRUE(exec_env != NULL); + + /* _on_init() function doesn't exist */ + func_inst = wasm_runtime_lookup_function(module_inst, "_on_init"); + ASSERT_TRUE(func_inst == NULL); + + /* on_init() function exists */ + func_inst = wasm_runtime_lookup_function(module_inst, "on_init"); + ASSERT_TRUE(func_inst != NULL); + + ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_inst, 0, NULL) == true); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* call my_malloc */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_malloc"); + ASSERT_TRUE(func_inst != NULL); + + /* malloc with very large size */ + argv[0] = 10 * 1024; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + wasm_runtime_clear_exception(module_inst); + ASSERT_EQ(argv[0], 0); + + /* malloc 1K, should success */ + argv[0] = 1024; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* convert to native address */ + ASSERT_TRUE(wasm_runtime_validate_app_addr(module_inst, argv[0], 1)); + char *buf = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf != NULL); + + ASSERT_EQ(wasm_runtime_addr_native_to_app(module_inst, buf), argv[0]); + int32 buf_offset = argv[0]; + + /* call my_malloc */ + func_inst = wasm_runtime_lookup_function(module_inst, "my_malloc"); + ASSERT_TRUE(func_inst != NULL); + + /* malloc, should success */ + argv[0] = 10; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + + /* convert to native address */ + ASSERT_TRUE(wasm_runtime_validate_app_addr(module_inst, argv[0], 1)); + char *buf1 = (char *)wasm_runtime_addr_app_to_native(module_inst, argv[0]); + ASSERT_TRUE(buf1 != NULL); + + ASSERT_EQ(wasm_runtime_addr_native_to_app(module_inst, buf1), argv[0]); + int32 buf_offset1 = argv[0]; + + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + wasm_runtime_destroy_exec_env(exec_env); +} + +#if WASM_ENABLE_MULTI_MODULE != 0 +static const char *module_search_path = "."; +static bool call_destroyer = false; +static bool +module_reader_callback(package_type_t module_type, const char *module_name, + uint8 **p_buffer, uint32 *p_size) +{ + const char *format = "%s/%s.wasm"; + int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) + + strlen(".wasm") + 1; + char *wasm_file_name = (char *)BH_MALLOC(sz); + if (!wasm_file_name) { + return false; + } + + snprintf(wasm_file_name, sz, format, module_search_path, module_name); + printf("going to open %s\n", wasm_file_name); + + call_destroyer = false; + *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size); + + BH_FREE(wasm_file_name); + return *p_buffer != NULL; +} + +static void +module_destroyer_callback(uint8 *buffer, uint32 size) +{ + wasm_runtime_free(buffer); + call_destroyer = true; +} + +TEST_F(WasmVMTest, Test_app4_single) +{ + uint8 *buffer = NULL; + uint32 buffer_size = 0; + bool ret = false; + unsigned argv[10]; + + wasm_runtime_set_module_reader(&module_reader_callback, + &module_destroyer_callback); + + /* m1 only */ + ret = module_reader_callback(Wasm_Module_Bytecode, "m1", &buffer, + &buffer_size); + ASSERT_TRUE(ret); + ASSERT_TRUE(buffer_size > 0); + ASSERT_TRUE(buffer != NULL); + + module = + wasm_runtime_load(buffer, buffer_size, error_buf, sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + ASSERT_FALSE(wasm_runtime_find_module_registered("m1")); + + wasm_runtime_register_module("m1", module, error_buf, sizeof(error_buf)); + + ASSERT_TRUE(wasm_runtime_find_module_registered("m1")); + + module_inst = wasm_runtime_instantiate(module, EightK, EightK, error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, EightK); + ASSERT_TRUE(exec_env != NULL); + + func_inst = wasm_runtime_lookup_function(module_inst, "f1"); + ASSERT_TRUE(func_inst != NULL); + ASSERT_FALSE(((WASMFunctionInstance *)func_inst)->is_import_func); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->param_cell_num == 0); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->ret_cell_num == 1); + + wasm_runtime_call_wasm(exec_env, func_inst, 0, argv); + printf("exception is %s", wasm_runtime_get_exception(module_inst)); + + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + ASSERT_TRUE(argv[0] == 1); + + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + wasm_runtime_unload(module); + + // call destroyer and without exception + ASSERT_FALSE(call_destroyer); + module_destroyer_callback(buffer, buffer_size); + + clean = false; + wasm_runtime_destroy(); +} + +TEST_F(WasmVMTest, Test_app4_plus_one) +{ + uint8 *buffer = NULL; + uint32 buffer_size = 0; + bool ret = false; + uint32_t argv[10] = { 0 }; + + wasm_runtime_set_module_reader(&module_reader_callback, + &module_destroyer_callback); + + /* m2 -> m1 */ + ret = module_reader_callback(Wasm_Module_Bytecode, "m2", &buffer, + &buffer_size); + ASSERT_TRUE(ret); + ASSERT_TRUE(buffer_size > 0); + ASSERT_TRUE(buffer != NULL); + + module = + wasm_runtime_load(buffer, buffer_size, error_buf, sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + module_inst = wasm_runtime_instantiate(module, EightK, EightK, error_buf, + sizeof(error_buf)); + ASSERT_TRUE(module_inst != NULL); + + exec_env = wasm_runtime_create_exec_env(module_inst, EightK); + ASSERT_TRUE(exec_env != NULL); + + printf("------------------- m1-f1 ---------------------\n"); + func_inst = wasm_runtime_lookup_function(module_inst, "m1-f1"); + ASSERT_TRUE(func_inst != NULL); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->is_import_func); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->param_cell_num == 0); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->ret_cell_num == 1); + + wasm_runtime_call_wasm(exec_env, func_inst, 0, argv); + printf("exception is %s\n", wasm_runtime_get_exception(module_inst)); + + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + ASSERT_TRUE(argv[0] == 1); + + printf("------------------- f2 ---------------------\n"); + func_inst = wasm_runtime_lookup_function(module_inst, "f2"); + ASSERT_TRUE(func_inst != NULL); + ASSERT_FALSE(((WASMFunctionInstance *)func_inst)->is_import_func); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->param_cell_num == 1); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->ret_cell_num == 1); + + argv[0] = 2; + wasm_runtime_call_wasm(exec_env, func_inst, 1, argv); + printf("exception is %s\n", wasm_runtime_get_exception(module_inst)); + + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + ASSERT_TRUE(argv[0] == 3); + + printf("------------------- f3 ---------------------\n"); + func_inst = wasm_runtime_lookup_function(module_inst, "f3"); + ASSERT_TRUE(func_inst != NULL); + ASSERT_FALSE(((WASMFunctionInstance *)func_inst)->is_import_func); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->param_cell_num == 2); + ASSERT_TRUE(((WASMFunctionInstance *)func_inst)->ret_cell_num == 1); + + argv[0] = 4; + argv[1] = 9; + wasm_runtime_call_wasm(exec_env, func_inst, 2, argv); + printf("exception is %s\n", wasm_runtime_get_exception(module_inst)); + + ASSERT_TRUE(wasm_runtime_get_exception(module_inst) == NULL); + ASSERT_TRUE(argv[0] == 9); + + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); + + wasm_runtime_unload(module); + ASSERT_FALSE(call_destroyer); +} + +TEST_F(WasmVMTest, Test_app4_family) +{ + uint8 *buffer = NULL; + uint32 buffer_size = 0; + bool ret = false; + + wasm_runtime_set_module_reader(&module_reader_callback, + &module_destroyer_callback); + + /* m3 -> m2[->m1], m1 */ + ret = module_reader_callback(Wasm_Module_Bytecode, "m3", &buffer, + &buffer_size); + ASSERT_TRUE(ret); + ASSERT_TRUE(buffer_size > 0); + ASSERT_TRUE(buffer != NULL); + module = + wasm_runtime_load(buffer, buffer_size, error_buf, sizeof(error_buf)); + ASSERT_TRUE(module != NULL); + + wasm_runtime_unload(module); + ASSERT_FALSE(call_destroyer); +} + +static const WASMModule * +search_sub_module(const WASMModule *parent_module, const char *sub_module_name) +{ + WASMRegisteredModule *node = (WASMRegisteredModule *)bh_list_first_elem( + parent_module->import_module_list); + while (node && strcmp(node->module_name, sub_module_name)) { + node = (WASMRegisteredModule *)bh_list_elem_next(node); + } + return node ? (WASMModule *)node->module : NULL; +} + +TEST_F(WasmVMTest, Test_app4_reuse) +{ + uint8 *buffer = NULL; + uint32 buffer_size = 0; + bool ret = false; + + wasm_runtime_set_module_reader(&module_reader_callback, + &module_destroyer_callback); + + /* m3 -> m2[->m1], m1 */ + ret = module_reader_callback(Wasm_Module_Bytecode, "m3", &buffer, + &buffer_size); + ASSERT_TRUE(buffer != NULL); + + WASMModule *m3 = (WASMModule *)wasm_runtime_load( + buffer, buffer_size, error_buf, sizeof(error_buf)); + ASSERT_TRUE(m3 != NULL); + + const WASMModule *m2 = search_sub_module(m3, "m2"); + const WASMModule *m1_in_m2 = search_sub_module(m2, "m1"); + const WASMModule *m1_in_m3 = search_sub_module(m3, "m1"); + ASSERT_EQ(m1_in_m2, m1_in_m3); +} +#endif /* WASM_ENABLE_MULTI_MODULE */