diff --git a/crates/wasmedge-sys/src/ast_module.rs b/crates/wasmedge-sys/src/ast_module.rs index 50eebb46f..831de3a57 100644 --- a/crates/wasmedge-sys/src/ast_module.rs +++ b/crates/wasmedge-sys/src/ast_module.rs @@ -392,8 +392,7 @@ pub(crate) struct InnerExportType(pub(crate) *const ffi::WasmEdge_ExportTypeCont unsafe impl Send for InnerExportType {} unsafe impl Sync for InnerExportType {} -// #[cfg(test)] -#[cfg(ignore)] +#[cfg(test)] mod tests { use crate::{Config, Loader}; use std::{ @@ -402,38 +401,6 @@ mod tests { }; use wasmedge_types::{ExternalInstanceType, Mutability, RefType, ValType}; - #[test] - fn test_module_clone() { - let path = std::env::current_dir() - .unwrap() - .ancestors() - .nth(2) - .unwrap() - .join("examples/wasmedge-sys/data/import.wat"); - - let result = Config::create(); - assert!(result.is_ok()); - let mut config = result.unwrap(); - config.bulk_memory_operations(true); - assert!(config.bulk_memory_operations_enabled()); - - // load module from file - let result = Loader::create(Some(&config)); - assert!(result.is_ok()); - let loader = result.unwrap(); - let result = loader.from_file(path); - assert!(result.is_ok()); - let module = result.unwrap(); - assert!(!module.inner.0.is_null()); - - // clone module - let module_clone = module.clone(); - - drop(module); - assert_eq!(std::sync::Arc::strong_count(&module_clone.inner), 1); - drop(module_clone); - } - #[test] fn test_module_import() { let path = std::env::current_dir() @@ -617,7 +584,7 @@ mod tests { // check exports assert_eq!(module.count_of_exports(), 16); - let exports = module.exports(); + let exports = module.export(); // check the ty and name functions let result = exports[0].ty(); @@ -772,7 +739,7 @@ mod tests { // check exports assert_eq!(module.count_of_exports(), 16); - let exports = module.exports(); + let exports = module.export(); // check the ty and name functions let result = exports[0].ty(); @@ -934,7 +901,7 @@ mod tests { // check exports assert_eq!(module.count_of_exports(), 16); - let exports = module.exports(); + let exports = module.export(); // check the ty and name functions let result = exports[0].ty(); diff --git a/crates/wasmedge-sys/src/async/function.rs b/crates/wasmedge-sys/src/async/function.rs index 5e13dc906..64dd801d4 100644 --- a/crates/wasmedge-sys/src/async/function.rs +++ b/crates/wasmedge-sys/src/async/function.rs @@ -128,140 +128,105 @@ impl AsMut for AsyncFunction { } } -#[cfg(ignore)] -/// Defines the signature of a host function. -pub(crate) type HostFn = fn( - CallingFrame, - Vec, - Option<&'static mut T>, -) -> Result, HostFuncError>; - -#[cfg(ignore)] -extern "C" fn wrap_sync_wasi_fn( - key_ptr: *mut std::ffi::c_void, - data: *mut std::ffi::c_void, - call_frame_ctx: *const ffi::WasmEdge_CallingFrameContext, - params: *const ffi::WasmEdge_Value, - param_len: u32, - returns: *mut ffi::WasmEdge_Value, - return_len: u32, -) -> ffi::WasmEdge_Result { - let frame = CallingFrame::create(call_frame_ctx); - - // recover the async host function - let real_func: HostFn = unsafe { std::mem::transmute(key_ptr) }; - - // recover the context data - let data = if std::any::TypeId::of::() == std::any::TypeId::of::() { - None - } else { - let data: &'static mut T = unsafe { &mut *(data as *mut T) }; - Some(data) +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + instance::function::AsFunc, r#async::fiber::AsyncState, types::WasmValue, Executor, }; - // input arguments - let input = { - let raw_input = unsafe { - std::slice::from_raw_parts( - params, - param_len - .try_into() - .expect("len of params should not greater than usize"), - ) - }; - raw_input.iter().map(|r| (*r).into()).collect::>() - }; + use wasmedge_types::{error::CoreExecutionError, FuncType, ValType}; - // returns - let return_len = return_len - .try_into() - .expect("len of returns should not greater than usize"); - let raw_returns = unsafe { std::slice::from_raw_parts_mut(returns, return_len) }; - - match real_func(frame, input, data) { - Ok(returns) => { - assert!(returns.len() == return_len, "[wasmedge-sys] check the number of returns of host function. Expected: {}, actual: {}", return_len, returns.len()); - for (idx, wasm_value) in returns.into_iter().enumerate() { - raw_returns[idx] = wasm_value.as_raw(); - } - ffi::WasmEdge_Result { Code: 0 } + #[tokio::test] + async fn test_func_basic() { + #[derive(Debug)] + struct Data { + _x: i32, + _y: String, + _v: Vec, + _s: Vec, } - Err(err) => match err { - HostFuncError::User(code) => unsafe { - ffi::WasmEdge_ResultGen(ffi::WasmEdge_ErrCategory_UserLevelError, code) - }, - HostFuncError::Runtime(code) => unsafe { - ffi::WasmEdge_ResultGen(ffi::WasmEdge_ErrCategory_WASM, code) - }, - }, - } -} -#[cfg(ignore)] -extern "C" fn wrap_async_wasi_fn( - key_ptr: *mut std::ffi::c_void, - data: *mut std::ffi::c_void, - call_frame_ctx: *const ffi::WasmEdge_CallingFrameContext, - params: *const ffi::WasmEdge_Value, - param_len: u32, - returns: *mut ffi::WasmEdge_Value, - return_len: u32, -) -> ffi::WasmEdge_Result { - let frame = CallingFrame::create(call_frame_ctx); - // recover the async host function - let real_func: AsyncHostFn = unsafe { std::mem::transmute(key_ptr) }; - - // recover the context data - let data = if std::any::TypeId::of::() == std::any::TypeId::of::() { - None - } else { - let data: &'static mut T = unsafe { &mut *(data as *mut T) }; - Some(data) - }; - - // arguments - let input = { - let raw_input = unsafe { - std::slice::from_raw_parts( - params, - param_len - .try_into() - .expect("len of params should not greater than usize"), - ) + let mut data: Data = Data { + _x: 12, + _y: "hello".to_string(), + _v: vec![1, 2, 3], + _s: vec!["macos", "linux", "windows"], }; - raw_input.iter().map(|r| (*r).into()).collect::>() - }; - // returns - let return_len = return_len - .try_into() - .expect("len of returns should not greater than usize"); - let raw_returns = unsafe { std::slice::from_raw_parts_mut(returns, return_len) }; + fn real_add( + _host_data: &mut Data, + _inst: &mut AsyncInstance, + _frame: &mut CallingFrame, + input: Vec, + ) -> Box, CoreError>> + Send> { + Box::new(async move { + println!("Rust: Entering Rust function real_add"); + + if input.len() != 2 { + return Err(CoreError::Execution(CoreExecutionError::FuncTypeMismatch)); + } + + let a = if input[0].ty() == ValType::I32 { + input[0].to_i32() + } else { + return Err(CoreError::Execution(CoreExecutionError::FuncTypeMismatch)); + }; + + let b = if input[1].ty() == ValType::I32 { + input[1].to_i32() + } else { + return Err(CoreError::Execution(CoreExecutionError::FuncTypeMismatch)); + }; + + tokio::time::sleep(std::time::Duration::from_millis(300)).await; + + let c = a + b; + println!("Rust: calcuating in real_add c: {c:?}"); + + println!("Rust: Leaving Rust function real_add"); + Ok(vec![WasmValue::from_i32(c)]) + }) + } - let async_cx = AsyncCx::new(); - let mut future = Pin::from(real_func(frame, input, data)); - let result = match unsafe { async_cx.block_on(future.as_mut()) } { - Ok(Ok(ret)) => Ok(ret), - Ok(Err(err)) => Err(err), - Err(_err) => Err(HostFuncError::Runtime(0x07)), - }; + // create a FuncType + let func_ty = FuncType::new(vec![ValType::I32; 2], vec![ValType::I32]); + // create a host function + let result = + AsyncFunction::create_async_func(&func_ty, real_add::>, &mut data, 0); + assert!(result.is_ok()); + let mut host_func = result.unwrap(); + + // get func type + let result = host_func.ty(); + assert!(result.is_some()); + let ty = result.unwrap(); + + // check parameters + assert_eq!(ty.args_len(), 2); + assert_eq!(ty.args(), &[ValType::I32; 2]); + + // check returns + assert_eq!(ty.returns_len(), 1); + assert_eq!(ty.returns(), &[ValType::I32]); + + // run this function + let result = Executor::create(None, None); + assert!(result.is_ok()); + let mut executor = result.unwrap(); + + let async_state = AsyncState::new(); + + let result = executor + .call_func_async( + &async_state, + host_func.as_mut(), + vec![WasmValue::from_i32(1), WasmValue::from_i32(2)], + ) + .await; - // parse result - match result { - Ok(returns) => { - assert!(returns.len() == return_len, "[wasmedge-sys] check the number of returns of async host function. Expected: {}, actual: {}", return_len, returns.len()); - for (idx, wasm_value) in returns.into_iter().enumerate() { - raw_returns[idx] = wasm_value.as_raw(); - } - ffi::WasmEdge_Result { Code: 0 } - } - Err(err) => match err { - HostFuncError::User(code) => unsafe { - ffi::WasmEdge_ResultGen(ffi::WasmEdge_ErrCategory_UserLevelError, code) - }, - HostFuncError::Runtime(code) => unsafe { - ffi::WasmEdge_ResultGen(ffi::WasmEdge_ErrCategory_WASM, code) - }, - }, + assert!(result.is_ok()); + let returns = result.unwrap(); + assert_eq!(returns[0].to_i32(), 3); } } diff --git a/crates/wasmedge-sys/src/async/module.rs b/crates/wasmedge-sys/src/async/module.rs index 4279c6b99..8134da4cc 100644 --- a/crates/wasmedge-sys/src/async/module.rs +++ b/crates/wasmedge-sys/src/async/module.rs @@ -2442,21 +2442,13 @@ impl async_wasi::snapshots::common::memory::Memory for Memory { } } -// #[cfg(test)] -#[cfg(ignore)] +#[cfg(test)] mod tests { use super::*; - use crate::{ - r#async::fiber::AsyncState, Config, Executor, Loader, Store, Validator, WasiInstance, - }; + use crate::{r#async::fiber::AsyncState, Executor, Loader, Store, Validator}; #[tokio::test] async fn test_async_wasi_module() -> Result<(), Box> { - // create a Config - let mut config = Config::create()?; - config.wasi(true); - assert!(config.wasi_enabled()); - // create an Executor let result = Executor::create(None, None); assert!(result.is_ok()); @@ -2471,11 +2463,10 @@ mod tests { // create an AsyncWasiModule let result = AsyncWasiModule::create(Some(vec!["abc"]), Some(vec![("ENV", "1")]), None); assert!(result.is_ok()); - let async_wasi_module = result.unwrap(); + let mut async_wasi_module = result.unwrap(); // register async_wasi module into the store - let wasi_import = WasiInstance::AsyncWasi(async_wasi_module); - let result = executor.register_wasi_instance(&mut store, &wasi_import); + let result = executor.register_import_module(&mut store, async_wasi_module.as_mut()); assert!(result.is_ok()); let wasm_file = std::env::current_dir() @@ -2486,8 +2477,8 @@ mod tests { .join("examples/wasmedge-sys/async_hello.wasm"); let module = Loader::create(None)?.from_file(&wasm_file)?; Validator::create(None)?.validate(&module)?; - let instance = executor.register_active_module(&mut store, &module)?; - let fn_start = instance.get_func("_start")?; + let mut instance = executor.register_active_module(&mut store, &module)?; + let mut fn_start = instance.get_func_mut("_start")?; async fn tick() { let mut i = 0; @@ -2501,7 +2492,7 @@ mod tests { let async_state = AsyncState::new(); let _ = executor - .call_func_async(&async_state, &fn_start, []) + .call_func_async(&async_state, &mut fn_start, []) .await?; Ok(()) diff --git a/crates/wasmedge-sys/src/compiler.rs b/crates/wasmedge-sys/src/compiler.rs index c273a5c93..9dd0a8692 100644 --- a/crates/wasmedge-sys/src/compiler.rs +++ b/crates/wasmedge-sys/src/compiler.rs @@ -148,7 +148,7 @@ unsafe impl Sync for InnerCompiler {} mod tests { use super::*; use crate::{ - AsImport, CallingFrame, Compiler, Config, Executor, FuncType, Function, ImportModule, + AsInstance, CallingFrame, Compiler, Config, Executor, FuncType, Function, ImportModule, Loader, Store, Validator, WasmValue, }; use std::{ @@ -156,10 +156,9 @@ mod tests { sync::{Arc, Mutex}, thread, }; - use wasmedge_macro::sys_host_function; use wasmedge_types::{ - error::{CoreError, CoreLoadError, HostFuncError}, - wat2wasm, CompilerOptimizationLevel, CompilerOutputFormat, NeverType, + error::{CoreError, CoreLoadError}, + wat2wasm, CompilerOptimizationLevel, CompilerOutputFormat, }; #[test] @@ -460,11 +459,11 @@ mod tests { // register the wasm module as named module let extern_module = Loader::create(Some(&config))?.from_file(&out_path)?; Validator::create(Some(&config))?.validate(&extern_module)?; - let extern_instance = + let mut extern_instance = executor.register_named_module(&mut store, &extern_module, "extern")?; - let fib = extern_instance.get_func("fib")?; - let returns = executor.call_func(&fib, [WasmValue::from_i32(5)])?; + let mut fib = extern_instance.get_func_mut("fib")?; + let returns = executor.call_func(&mut fib, [WasmValue::from_i32(5)])?; assert_eq!(returns[0].to_i32(), 8); } @@ -472,10 +471,11 @@ mod tests { // register the wasm module as active module let active_module = Loader::create(Some(&config))?.from_file(&out_path)?; Validator::create(Some(&config))?.validate(&active_module)?; - let active_instance = executor.register_active_module(&mut store, &active_module)?; + let mut active_instance = + executor.register_active_module(&mut store, &active_module)?; - let fib = active_instance.get_func("fib")?; - let returns = executor.call_func(&fib, [WasmValue::from_i32(5)])?; + let mut fib = active_instance.get_func_mut("fib")?; + let returns = executor.call_func(&mut fib, [WasmValue::from_i32(5)])?; assert_eq!(returns[0].to_i32(), 8); } @@ -486,18 +486,17 @@ mod tests { } #[cfg(feature = "aot")] - fn create_spec_test_module() -> ImportModule { + fn create_spec_test_module() -> ImportModule<()> { // create an ImportObj module - let result = ImportModule::::create("spectest", None); + let result = ImportModule::create("spectest", Box::new(())); assert!(result.is_ok()); let mut import = result.unwrap(); // create a host function - let result = FuncType::create([], []); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - let result = - Function::create_sync_func::(&func_ty, Box::new(spec_test_print), None, 0); + let func_ty = FuncType::new(vec![], vec![]); + let result = unsafe { + Function::create_sync_func(&func_ty, spec_test_print, import.get_host_data_mut(), 0) + }; assert!(result.is_ok()); let host_func = result.unwrap(); // add host function "print" @@ -506,11 +505,12 @@ mod tests { } #[cfg(feature = "aot")] - #[sys_host_function] fn spec_test_print( - _frame: CallingFrame, + _data: &mut (), + _inst: &mut crate::Instance, + _frame: &mut CallingFrame, _inputs: Vec, - ) -> Result, HostFuncError> { + ) -> Result, CoreError> { Ok(vec![]) } } diff --git a/crates/wasmedge-sys/src/config.rs b/crates/wasmedge-sys/src/config.rs index 4efcbdef0..08f6fed2c 100644 --- a/crates/wasmedge-sys/src/config.rs +++ b/crates/wasmedge-sys/src/config.rs @@ -729,8 +729,7 @@ pub(crate) struct InnerConfig(pub(crate) *mut ffi::WasmEdge_ConfigureContext); unsafe impl Send for InnerConfig {} unsafe impl Sync for InnerConfig {} -// #[cfg(test)] -#[cfg(ignore)] +#[cfg(test)] mod tests { use super::*; use std::{ @@ -1016,65 +1015,4 @@ mod tests { handle.join().unwrap(); } - - #[test] - fn test_config_clone() { - // create a Config instance - let result = Config::create(); - assert!(result.is_ok()); - let mut config = result.unwrap(); - assert_eq!(std::sync::Arc::strong_count(&config.inner), 1); - - // set options - config.multi_memories(true); - config.annotations(true); - config.bulk_memory_operations(false); - config.exception_handling(true); - config.function_references(true); - config.memory64(true); - config.multi_value(false); - config.mutable_globals(false); - config.non_trap_conversions(false); - config.sign_extension_operators(false); - config.reference_types(false); - config.simd(false); - config.tail_call(true); - config.threads(true); - config.measure_cost(true); - config.measure_time(true); - #[cfg(feature = "aot")] - config.dump_ir(true); - #[cfg(feature = "aot")] - config.generic_binary(true); - config.count_instructions(true); - - let config_clone = config.clone(); - assert_eq!(std::sync::Arc::strong_count(&config.inner), 2); - // check new settings - assert!(config_clone.multi_memories_enabled()); - assert!(config_clone.annotations_enabled()); - assert!(!config_clone.bulk_memory_operations_enabled()); - assert!(config_clone.exception_handling_enabled()); - assert!(config_clone.function_references_enabled()); - assert!(config_clone.memory64_enabled()); - assert!(!config_clone.multi_value_enabled()); - assert!(!config_clone.mutable_globals_enabled()); - assert!(!config_clone.non_trap_conversions_enabled()); - assert!(!config_clone.sign_extension_operators_enabled()); - assert!(!config_clone.reference_types_enabled()); - assert!(!config_clone.simd_enabled()); - assert!(config_clone.tail_call_enabled()); - assert!(config_clone.threads_enabled()); - assert!(config_clone.is_cost_measuring()); - #[cfg(feature = "aot")] - assert!(config_clone.dump_ir_enabled()); - #[cfg(feature = "aot")] - assert!(config_clone.generic_binary_enabled()); - assert!(config_clone.is_instruction_counting()); - assert!(config_clone.is_time_measuring()); - - drop(config); - assert_eq!(std::sync::Arc::strong_count(&config_clone.inner), 1); - drop(config_clone); - } } diff --git a/crates/wasmedge-sys/src/executor.rs b/crates/wasmedge-sys/src/executor.rs index 80194fbbb..a27a40aba 100644 --- a/crates/wasmedge-sys/src/executor.rs +++ b/crates/wasmedge-sys/src/executor.rs @@ -502,401 +502,3 @@ impl Executor { pub(crate) struct InnerExecutor(pub(crate) *mut ffi::WasmEdge_ExecutorContext); unsafe impl Send for InnerExecutor {} unsafe impl Sync for InnerExecutor {} - -// #[cfg(test)] -#[cfg(ignore)] -mod tests { - use super::*; - cfg_if::cfg_if! { - if #[cfg(all(feature = "async", target_os = "linux"))] { - use crate::r#async::AsyncWasiModule; - use crate::{Loader, Validator}; - use wasmedge_macro::sys_async_host_function; - } - } - use crate::{ - AsImport, CallingFrame, Config, FuncTypeOwn, Function, Global, GlobalType, ImportModule, - MemType, Memory, Statistics, Table, TableType, HOST_FUNCS, HOST_FUNC_FOOTPRINTS, - }; - use std::{ - sync::{Arc, Mutex}, - thread, - }; - use wasmedge_macro::sys_host_function; - use wasmedge_types::{error::HostFuncError, Mutability, NeverType, RefType, ValType}; - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_executor_create() { - { - // create an Executor context without configuration and statistics - let result = Executor::create(None, None); - assert!(result.is_ok()); - let executor = result.unwrap(); - assert!(!executor.inner.0.is_null()); - } - - { - // create an Executor context with a given configuration - let result = Config::create(); - assert!(result.is_ok()); - let config = result.unwrap(); - let result = Executor::create(Some(&config), None); - assert!(result.is_ok()); - let executor = result.unwrap(); - assert!(!executor.inner.0.is_null()); - } - - { - // create an Executor context with a given statistics - let result = Statistics::create(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - let result = Executor::create(None, Some(&mut stat)); - assert!(result.is_ok()); - let executor = result.unwrap(); - assert!(!executor.inner.0.is_null()); - } - - { - // create an Executor context with the given configuration and statistics. - let result = Config::create(); - assert!(result.is_ok()); - let config = result.unwrap(); - - let result = Statistics::create(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - - let result = Executor::create(Some(&config), Some(&mut stat)); - assert!(result.is_ok()); - let executor = result.unwrap(); - assert!(!executor.inner.0.is_null()); - } - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_executor_register_import() { - // create an Executor - let result = Executor::create(None, None); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - assert!(!executor.inner.0.is_null()); - - // create a Store - let result = Store::create(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - // create an ImportObj module - let host_name = "extern"; - let result = ImportModule::::create(host_name, None); - assert!(result.is_ok()); - let mut import = result.unwrap(); - - assert_eq!(HOST_FUNCS.read().len(), 0); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0); - - // add host function "func-add": (externref, i32) -> (i32) - let result = FuncTypeOwn::create([ValType::ExternRef, ValType::I32], [ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - let result = Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0); - assert!(result.is_ok()); - let host_func = result.unwrap(); - // add the function into the import_obj module - import.add_func("func-add", host_func); - - // create a Table instance - let result = TableType::create(RefType::FuncRef, 10, Some(20)); - assert!(result.is_ok()); - let table_ty = result.unwrap(); - let result = Table::create(&table_ty); - assert!(result.is_ok()); - let host_table = result.unwrap(); - // add the table into the import_obj module - import.add_table("table", host_table); - - // create a Memory instance - let result = MemType::create(1, Some(2), false); - assert!(result.is_ok()); - let mem_ty = result.unwrap(); - let result = Memory::create(&mem_ty); - assert!(result.is_ok()); - let host_memory = result.unwrap(); - // add the memory into the import_obj module - import.add_memory("memory", host_memory); - - // create a Global instance - let result = GlobalType::create(ValType::I32, Mutability::Const); - assert!(result.is_ok()); - let global_ty = result.unwrap(); - let result = Global::create(&global_ty, WasmValue::from_i32(666)); - assert!(result.is_ok()); - let host_global = result.unwrap(); - // add the global into import_obj module - import.add_global("global_i32", host_global); - - let result = executor.register_import_module(&mut store, &import); - assert!(result.is_ok()); - - { - let result = store.module("extern"); - assert!(result.is_ok()); - let instance = result.unwrap(); - - let result = instance.get_global("global_i32"); - assert!(result.is_ok()); - let global = result.unwrap(); - assert_eq!(global.get_value().to_i32(), 666); - } - - let handle = thread::spawn(move || { - let result = store.module("extern"); - assert!(result.is_ok()); - let instance = result.unwrap(); - - let result = instance.get_global("global_i32"); - assert!(result.is_ok()); - let global = result.unwrap(); - assert_eq!(global.get_value().to_i32(), 666); - }); - - handle.join().unwrap(); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_executor_send() { - // create an Executor context with the given configuration and statistics. - let result = Config::create(); - assert!(result.is_ok()); - let config = result.unwrap(); - - let result = Statistics::create(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - - let result = Executor::create(Some(&config), Some(&mut stat)); - assert!(result.is_ok()); - let executor = result.unwrap(); - assert!(!executor.inner.0.is_null()); - - let handle = thread::spawn(move || { - assert!(!executor.inner.0.is_null()); - println!("{:?}", executor.inner); - }); - - handle.join().unwrap(); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_executor_sync() { - // create an Executor context with the given configuration and statistics. - let result = Config::create(); - assert!(result.is_ok()); - let config = result.unwrap(); - - let result = Statistics::create(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - - let result = Executor::create(Some(&config), Some(&mut stat)); - assert!(result.is_ok()); - let executor = Arc::new(Mutex::new(result.unwrap())); - - let executor_cloned = Arc::clone(&executor); - let handle = thread::spawn(move || { - let result = executor_cloned.lock(); - assert!(result.is_ok()); - let executor = result.unwrap(); - - assert!(!executor.inner.0.is_null()); - }); - - handle.join().unwrap(); - } - - #[cfg(all(feature = "async", target_os = "linux"))] - #[tokio::test] - async fn test_executor_register_async_wasi() -> Result<(), Box> { - // create a Config - let mut config = Config::create()?; - config.wasi(true); - assert!(config.wasi_enabled()); - - // create an Executor - let result = Executor::create(None, None); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - assert!(!executor.inner.0.is_null()); - - // create a Store - let result = Store::create(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - // create an AsyncWasiModule - let result = AsyncWasiModule::create(Some(vec!["abc"]), Some(vec![("ENV", "1")]), None); - assert!(result.is_ok()); - let async_wasi_module = result.unwrap(); - - let wasi_import = WasiInstance::AsyncWasi(async_wasi_module); - let result = executor.register_wasi_instance(&mut store, &wasi_import); - assert!(result.is_ok()); - - // register async_wasi module into the store - let wasm_file = std::env::current_dir() - .unwrap() - .ancestors() - .nth(2) - .unwrap() - .join("examples/wasmedge-sys/async_hello.wasm"); - let module = Loader::create(None)?.from_file(&wasm_file)?; - Validator::create(None)?.validate(&module)?; - let instance = executor.register_active_module(&mut store, &module)?; - let mut fn_start = instance.get_func("_start")?; - - async fn tick() { - let mut i = 0; - loop { - println!("[tick] i={i}"); - tokio::time::sleep(std::time::Duration::from_millis(500)).await; - i += 1; - } - } - tokio::spawn(tick()); - - dbg!("call async host func"); - - let async_state = AsyncState::new(); - let _ = executor - .call_func_async(&async_state, &mut fn_start, []) - .await?; - - dbg!("call async host func done"); - - Ok(()) - } - - #[cfg(all(feature = "async", target_os = "linux"))] - #[tokio::test] - async fn test_executor_run_async_host_func() -> Result<(), Box> { - fn async_hello( - _frame: CallingFrame, - _inputs: Vec, - _: *mut std::os::raw::c_void, - ) -> Box<(dyn std::future::Future, HostFuncError>> + Send)> - { - Box::new(async move { - for _ in 0..10 { - println!("[async hello] say hello"); - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - } - - println!("[async hello] Done!"); - - Ok(vec![]) - }) - } - - // create a Config - let mut config = Config::create()?; - config.wasi(true); - assert!(config.wasi_enabled()); - - // create an Executor - let result = Executor::create(None, None); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - assert!(!executor.inner.0.is_null()); - - // create a Store - let result = Store::create(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - // create an AsyncWasiModule - let result = AsyncWasiModule::create(None, None, None); - assert!(result.is_ok()); - let async_wasi_module = result.unwrap(); - - // register async_wasi module into the store - let wasi_import = WasiInstance::AsyncWasi(async_wasi_module); - let result = executor.register_wasi_instance(&mut store, &wasi_import); - assert!(result.is_ok()); - - let ty = FuncTypeOwn::create([], [])?; - let async_hello_func = - Function::create_async_func::(&ty, Box::new(async_hello), None, 0)?; - let mut import = ImportModule::::create("extern", None)?; - import.add_func("async_hello", async_hello_func); - - executor.register_import_module(&mut store, &import)?; - - let extern_instance = store.module("extern")?; - let mut async_hello = extern_instance.get_func("async_hello")?; - - async fn tick() { - let mut i = 0; - loop { - println!("[tick] i={i}"); - tokio::time::sleep(std::time::Duration::from_millis(500)).await; - i += 1; - } - } - tokio::spawn(tick()); - - let async_state = AsyncState::new(); - let _ = executor - .call_func_async(&async_state, &mut async_hello, []) - .await?; - - Ok(()) - } - - #[sys_host_function] - fn real_add( - _frame: CallingFrame, - inputs: Vec, - ) -> Result, HostFuncError> { - if inputs.len() != 2 { - return Err(HostFuncError::User(1)); - } - - let a = if inputs[0].ty() == ValType::I32 { - inputs[0].to_i32() - } else { - return Err(HostFuncError::User(2)); - }; - - let b = if inputs[1].ty() == ValType::I32 { - inputs[1].to_i32() - } else { - return Err(HostFuncError::User(3)); - }; - - let c = a + b; - - Ok(vec![WasmValue::from_i32(c)]) - } - - #[cfg(all(feature = "async", target_os = "linux"))] - #[sys_async_host_function] - async fn async_hello( - _frame: CallingFrame, - _inputs: Vec, - _data: *mut std::os::raw::c_void, - ) -> Result, HostFuncError> { - for _ in 0..10 { - println!("[async hello] say hello"); - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - } - - println!("[async hello] Done!"); - - Ok(vec![]) - } -} diff --git a/crates/wasmedge-sys/src/instance/function.rs b/crates/wasmedge-sys/src/instance/function.rs index 1f5d8d51c..2cf3d3489 100644 --- a/crates/wasmedge-sys/src/instance/function.rs +++ b/crates/wasmedge-sys/src/instance/function.rs @@ -101,46 +101,6 @@ impl Function { /// # Safety /// /// The lifetime of `data` must be greater than that of `Function` itself. - /// - /// # Example - /// - /// The example defines a host function `real_add`, and creates a [Function] binding to it by calling - /// the `create_binding` method. - /// - /// ```rust - /// use wasmedge_macro::sys_host_function; - /// use wasmedge_sys::{FuncType, Function, WasmValue, CallingFrame}; - /// use wasmedge_types::{error::HostFuncError, ValType, WasmEdgeResult, NeverType}; - /// - /// #[sys_host_function] - /// fn real_add(_frame: CallingFrame, inputs: Vec) -> Result, HostFuncError> { - /// if inputs.len() != 2 { - /// return Err(HostFuncError::User(1)); - /// } - /// - /// let a = if inputs[0].ty() == ValType::I32 { - /// inputs[0].to_i32() - /// } else { - /// return Err(HostFuncError::User(2)); - /// }; - /// - /// let b = if inputs[1].ty() == ValType::I32 { - /// inputs[1].to_i32() - /// } else { - /// return Err(HostFuncError::User(3)); - /// }; - /// - /// let c = a + b; - /// - /// Ok(vec![WasmValue::from_i32(c)]) - /// } - /// - /// // create a FuncType - /// let func_ty = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]).expect("fail to create a FuncType"); - /// - /// // create a Function instance - /// let func = Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0).expect("fail to create a Function instance"); - /// ``` pub unsafe fn create_sync_func( ty: &wasmedge_types::FuncType, real_fn: SyncFn, @@ -303,15 +263,6 @@ impl FuncTypeOwn { /// # Error /// /// If fail to create a [FuncType], then an error is returned. - /// - /// # Example - /// - /// ```rust - /// use wasmedge_sys::FuncType; - /// use wasmedge_types::ValType; - /// - /// let func_ty = FuncType::create(vec![ValType::I32;2], vec![ValType::I32]).expect("fail to create a FuncType"); - /// ``` pub(crate) fn create, R: IntoIterator>( args: I, returns: R, @@ -409,19 +360,12 @@ pub(crate) struct InnerFuncType(pub(crate) *const ffi::WasmEdge_FunctionTypeCont unsafe impl Send for InnerFuncType {} unsafe impl Sync for InnerFuncType {} -// #[cfg(test)] -#[cfg(ignore)] +#[cfg(test)] mod tests { use super::*; - #[cfg(all(feature = "async", target_os = "linux"))] - use crate::{r#async::AsyncWasiModule, WasiInstance, ASYNC_HOST_FUNCS}; - use crate::{types::WasmValue, AsImport, Executor, ImportModule, Store, HOST_FUNC_FOOTPRINTS}; - use std::{ - sync::{Arc, Mutex}, - thread, - }; - use wasmedge_macro::sys_host_function; - use wasmedge_types::{NeverType, ValType}; + use crate::{types::WasmValue, Executor}; + + use wasmedge_types::{error::CoreExecutionError, FuncType, ValType}; #[test] fn test_func_type() { @@ -442,7 +386,7 @@ mod tests { // create FuncType let result = FuncTypeOwn::create(param_tys, ret_tys); assert!(result.is_ok()); - let func_ty = result.unwrap().get_ref(); + let func_ty = result.unwrap(); // check parameters assert_eq!(func_ty.params_len(), param_len as u32); @@ -473,7 +417,7 @@ mod tests { // create FuncType let result = FuncTypeOwn::create([], []); assert!(result.is_ok()); - let func_ty = result.unwrap().get_ref(); + let func_ty = result.unwrap(); assert_eq!(func_ty.params_len(), 0); assert_eq!(func_ty.returns_len(), 0); @@ -489,7 +433,8 @@ mod tests { _v: Vec, _s: Vec, } - let data: Data = Data { + + let mut data: Data = Data { _x: 12, _y: "hello".to_string(), _v: vec![1, 2, 3], @@ -497,29 +442,27 @@ mod tests { }; fn real_add( - _frame: CallingFrame, + _host_data: &mut Data, + _inst: &mut Instance, + _frame: &mut CallingFrame, input: Vec, - data: *mut std::ffi::c_void, - ) -> Result, HostFuncError> { + ) -> Result, CoreError> { println!("Rust: Entering Rust function real_add"); - let host_data = unsafe { Box::from_raw(data as *mut T) }; - println!("host_data: {:?}", host_data); - if input.len() != 2 { - return Err(HostFuncError::User(1)); + return Err(CoreError::Execution(CoreExecutionError::FuncTypeMismatch)); } let a = if input[0].ty() == ValType::I32 { input[0].to_i32() } else { - return Err(HostFuncError::User(2)); + return Err(CoreError::Execution(CoreExecutionError::FuncTypeMismatch)); }; let b = if input[1].ty() == ValType::I32 { input[1].to_i32() } else { - return Err(HostFuncError::User(3)); + return Err(CoreError::Execution(CoreExecutionError::FuncTypeMismatch)); }; let c = a + b; @@ -529,672 +472,40 @@ mod tests { Ok(vec![WasmValue::from_i32(c)]) } - assert_eq!(HOST_FUNCS.read().len(), 0); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0); - // create a FuncType - let result = FuncTypeOwn::create(vec![ValType::I32; 2], vec![ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); + let func_ty = FuncType::new(vec![ValType::I32; 2], vec![ValType::I32]); // create a host function - let result = Function::create_sync_func( - &func_ty, - Box::new(real_add::>), - Some(Box::new(data)), - 0, - ); + let result = unsafe { + Function::create_sync_func(&func_ty, real_add::>, &mut data, 0) + }; assert!(result.is_ok()); - let host_func = result.unwrap(); + let mut host_func = result.unwrap(); // get func type - let result = FuncType::get_from_func(&host_func); + let result = host_func.ty(); assert!(result.is_some()); let ty = result.unwrap(); // check parameters - assert_eq!(ty.params_len(), 2); - let param_tys = ty.params_type_iter().collect::>(); - assert_eq!(param_tys, vec![ValType::I32; 2]); + assert_eq!(ty.args_len(), 2); + assert_eq!(ty.args(), &[ValType::I32; 2]); // check returns assert_eq!(ty.returns_len(), 1); - let return_tys = ty.returns_type_iter().collect::>(); - assert_eq!(return_tys, vec![ValType::I32]); + assert_eq!(ty.returns(), &[ValType::I32]); // run this function let result = Executor::create(None, None); assert!(result.is_ok()); let mut executor = result.unwrap(); - let result = host_func.call( - &mut executor, + + let result = executor.call_func( + &mut host_func, vec![WasmValue::from_i32(1), WasmValue::from_i32(2)], ); + assert!(result.is_ok()); let returns = result.unwrap(); assert_eq!(returns[0].to_i32(), 3); } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_func_create_host_func_in_host_func() { - #[sys_host_function] - fn func( - _frame: CallingFrame, - _input: Vec, - ) -> Result, HostFuncError> { - println!("Entering host function: func"); - - // spawn a new thread to create a new host function - let handler = std::thread::spawn(|| { - #[sys_host_function] - fn real_add( - _frame: CallingFrame, - input: Vec, - ) -> Result, HostFuncError> { - println!("Rust: Entering Rust function real_add"); - - if input.len() != 2 { - return Err(HostFuncError::User(1)); - } - - let a = if input[0].ty() == ValType::I32 { - input[0].to_i32() - } else { - return Err(HostFuncError::User(2)); - }; - - let b = if input[1].ty() == ValType::I32 { - input[1].to_i32() - } else { - return Err(HostFuncError::User(3)); - }; - - let c = a + b; - - println!("Rust: Leaving Rust function real_add"); - Ok(vec![WasmValue::from_i32(c)]) - } - - // create a FuncType - let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - // create a host function - let result = - Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0); - assert!(result.is_ok()); - let host_func = result.unwrap(); - - // run this function - let result = Executor::create(None, None); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - let result = host_func.call( - &mut executor, - vec![WasmValue::from_i32(1), WasmValue::from_i32(2)], - ); - assert!(result.is_ok()); - let returns = result.unwrap(); - assert_eq!(returns[0].to_i32(), 3); - }); - handler.join().unwrap(); - - println!("Leaving host function: func"); - Ok(vec![]) - } - - // create a FuncType - let result = FuncType::create(vec![], vec![]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - // create a host function - let result = Function::create_sync_func::(&func_ty, Box::new(func), None, 0); - assert!(result.is_ok()); - let host_func = result.unwrap(); - - // run this function - let result = Executor::create(None, None); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - let result = host_func.call(&mut executor, vec![]); - assert!(result.is_ok()); - } - - #[test] - fn test_func_send() { - // create a FuncType - let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - // create a host function - let result = Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0); - assert!(result.is_ok()); - let host_func = result.unwrap(); - - let handle = thread::spawn(move || { - // get func type - let result = host_func.ty(); - assert!(result.is_ok()); - let ty = result.unwrap(); - - // check parameters - assert_eq!(ty.params_len(), 2); - let param_tys = ty.params_type_iter().collect::>(); - assert_eq!(param_tys, vec![ValType::I32; 2]); - - // check returns - assert_eq!(ty.returns_len(), 1); - let return_tys = ty.returns_type_iter().collect::>(); - assert_eq!(return_tys, vec![ValType::I32]); - }); - - handle.join().unwrap() - } - - #[test] - fn test_func_sync() { - // create a FuncType - let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - // create a host function - let result = Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0); - assert!(result.is_ok()); - let host_func = Arc::new(Mutex::new(result.unwrap())); - - let host_func_cloned = Arc::clone(&host_func); - let handle = thread::spawn(move || { - let result = host_func_cloned.lock(); - assert!(result.is_ok()); - let host_func = result.unwrap(); - - // get func type - let result = host_func.ty(); - assert!(result.is_ok()); - let ty = result.unwrap(); - - // check parameters - assert_eq!(ty.params_len(), 2); - let param_tys = ty.params_type_iter().collect::>(); - assert_eq!(param_tys, vec![ValType::I32; 2]); - - // check returns - assert_eq!(ty.returns_len(), 1); - let return_tys = ty.returns_type_iter().collect::>(); - assert_eq!(return_tys, vec![ValType::I32]); - }); - - handle.join().unwrap(); - } - - #[sys_host_function] - fn real_add( - _frame: CallingFrame, - input: Vec, - ) -> Result, HostFuncError> { - println!("Rust: Entering Rust function real_add"); - - if input.len() != 2 { - return Err(HostFuncError::User(1)); - } - - let a = if input[0].ty() == ValType::I32 { - input[0].to_i32() - } else { - return Err(HostFuncError::User(2)); - }; - - let b = if input[1].ty() == ValType::I32 { - input[1].to_i32() - } else { - return Err(HostFuncError::User(3)); - }; - - let c = a + b; - println!("Rust: calcuating in real_add c: {c:?}"); - - println!("Rust: Leaving Rust function real_add"); - Ok(vec![WasmValue::from_i32(c)]) - } - - #[test] - fn test_func_closure() -> Result<(), Box> { - { - // create a host function - let real_add = |_: CallingFrame, - input: Vec, - _: *mut std::os::raw::c_void| - -> Result, HostFuncError> { - println!("Rust: Entering Rust function real_add"); - - if input.len() != 2 { - return Err(HostFuncError::User(1)); - } - - let a = if input[0].ty() == ValType::I32 { - input[0].to_i32() - } else { - return Err(HostFuncError::User(2)); - }; - - let b = if input[1].ty() == ValType::I32 { - input[1].to_i32() - } else { - return Err(HostFuncError::User(3)); - }; - - let c = a + b; - println!("Rust: calcuating in real_add c: {c:?}"); - - println!("Rust: Leaving Rust function real_add"); - Ok(vec![WasmValue::from_i32(c)]) - }; - - // create a FuncType - let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - - // create a host function from the closure defined above - let result = - Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0); - assert!(result.is_ok()); - let host_func = result.unwrap(); - - // create a Store - let result = Store::create(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - // create an ImportModule - let mut import = ImportModule::::create("extern", None)?; - import.add_func("add", host_func); - - // run this function - let result = Executor::create(None, None); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - executor.register_import_module(&mut store, &import)?; - - let extern_instance = store.module("extern")?; - let add = extern_instance.get_func("add")?; - - let result = - executor.call_func(&add, vec![WasmValue::from_i32(1), WasmValue::from_i32(2)]); - assert!(result.is_ok()); - let returns = result.unwrap(); - assert_eq!(returns[0].to_i32(), 3); - } - - assert_eq!(HOST_FUNCS.read().len(), 0); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0); - - Ok(()) - } - - #[test] - fn test_func_drop() -> Result<(), Box> { - // create a host function - let real_add = |_: CallingFrame, - input: Vec, - _: *mut std::os::raw::c_void| - -> Result, HostFuncError> { - println!("Rust: Entering Rust function real_add"); - - if input.len() != 2 { - return Err(HostFuncError::User(1)); - } - - let a = if input[0].ty() == ValType::I32 { - input[0].to_i32() - } else { - return Err(HostFuncError::User(2)); - }; - - let b = if input[1].ty() == ValType::I32 { - input[1].to_i32() - } else { - return Err(HostFuncError::User(3)); - }; - - let c = a + b; - println!("Rust: calcuating in real_add c: {c:?}"); - - println!("Rust: Leaving Rust function real_add"); - Ok(vec![WasmValue::from_i32(c)]) - }; - - // create a FuncType - let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - - // create a host function - let result = Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0); - assert!(result.is_ok()); - let host_func = result.unwrap(); - - assert_eq!(Arc::strong_count(&host_func.inner), 1); - assert!(!host_func.registered); - - assert_eq!(HOST_FUNCS.read().len(), 1); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1); - - // clone the host function before adding it to the import object - let host_func_cloned = host_func.clone(); - - assert_eq!(Arc::strong_count(&host_func_cloned.inner), 2); - assert!(!host_func_cloned.registered); - - assert_eq!(HOST_FUNCS.read().len(), 1); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1); - - // create an ImportModule - let mut import = ImportModule::::create("extern", None)?; - // add the host function to the import module - import.add_func("add", host_func); - - assert_eq!(Arc::strong_count(&host_func_cloned.inner), 2); - assert!(!host_func_cloned.registered); - - assert_eq!(HOST_FUNCS.read().len(), 1); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1); - - drop(host_func_cloned); - - assert_eq!(HOST_FUNCS.read().len(), 1); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1); - - // create a Store - let result = Store::create(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - // run this function - let result = Executor::create(None, None); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - executor.register_import_module(&mut store, &import)?; - - // get the registered host function - let extern_instance = store.module("extern")?; - let add = extern_instance.get_func("add")?; - assert_eq!(Arc::strong_count(&add.inner), 1); - assert!(add.registered); - - assert_eq!(HOST_FUNCS.read().len(), 1); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1); - - // clone the host function - let add_cloned = add.clone(); - assert_eq!(Arc::strong_count(&add.inner), 2); - assert!(add.registered); - assert_eq!(Arc::strong_count(&add_cloned.inner), 2); - assert!(add_cloned.registered); - - assert_eq!(HOST_FUNCS.read().len(), 1); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1); - - // drop the cloned host function - drop(add_cloned); - assert_eq!(Arc::strong_count(&add.inner), 1); - assert!(add.registered); - - assert_eq!(HOST_FUNCS.read().len(), 1); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1); - - drop(add); - - assert_eq!(HOST_FUNCS.read().len(), 1); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1); - - // get the registered host function again - let extern_instance = store.module("extern")?; - let add_again = extern_instance.get_func("add")?; - assert_eq!(Arc::strong_count(&add_again.inner), 1); - assert!(add_again.registered); - - assert_eq!(HOST_FUNCS.read().len(), 1); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1); - - // ! notice that `add_again` should be dropped before or not be used after dropping `import` - drop(add_again); - - assert_eq!(HOST_FUNCS.read().len(), 1); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1); - - // drop the import object - drop(import); - - assert!(store.module("extern").is_err()); - - assert_eq!(HOST_FUNCS.read().len(), 0); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0); - - // ! if `add_again` is not dropped before dropping `import`, then calling `add_again` will crash - // let result = executor.call_func( - // &add_again, - // vec![WasmValue::from_i32(1), WasmValue::from_i32(2)], - // ); - - Ok(()) - } - - #[cfg(all(feature = "async", target_os = "linux"))] - #[tokio::test] - async fn test_func_async_closure() -> Result<(), Box> { - { - #[derive(Debug)] - struct Data { - _x: i32, - _y: String, - _v: Vec, - _s: Vec, - } - impl Drop for Data { - fn drop(&mut self) { - println!("Dropping Data"); - } - } - - let data: Data = Data { - _x: 12, - _y: "hello".to_string(), - _v: vec![1, 2, 3], - _s: vec!["macos", "linux", "windows"], - }; - - // define an async closure - let c = |_frame: CallingFrame, - _args: Vec, - data: *mut std::os::raw::c_void| - -> Box< - (dyn std::future::Future, HostFuncError>> + Send), - > { - // let host_data = unsafe { &mut *(data as *mut Data) }; - let host_data = unsafe { Box::from_raw(data as *mut Data) }; - - Box::new(async move { - for _ in 0..10 { - println!("[async hello] say hello"); - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - - println!("host_data: {:?}", host_data); - } - - println!("[async hello] Done!"); - - Ok(vec![]) - }) - }; - - // create a FuncType - let result = FuncType::create(vec![], vec![]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - - // create an async host function - let result = - Function::create_async_func(&func_ty, Box::new(c), Some(Box::new(data)), 0); - assert!(result.is_ok()); - let async_hello_func = result.unwrap(); - - // create an Executor - let result = Executor::create(None, None); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - assert!(!executor.inner.0.is_null()); - - // create a Store - let result = Store::create(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - // create an AsyncWasiModule - let result = AsyncWasiModule::create(Some(vec!["abc"]), Some(vec![("a", "1")]), None); - assert!(result.is_ok()); - let async_wasi_module = result.unwrap(); - - // register async_wasi module into the store - let wasi_import = WasiInstance::AsyncWasi(async_wasi_module); - let result = executor.register_wasi_instance(&mut store, &wasi_import); - assert!(result.is_ok()); - - // create an ImportModule - let mut import = ImportModule::::create("extern", None)?; - import.add_func("async_hello", async_hello_func); - - executor.register_import_module(&mut store, &import)?; - - let extern_instance = store.module("extern")?; - let async_hello = extern_instance.get_func("async_hello")?; - - async fn tick() { - let mut i = 0; - loop { - println!("[tick] i={i}"); - tokio::time::sleep(std::time::Duration::from_millis(500)).await; - i += 1; - } - } - tokio::spawn(tick()); - - let async_state = crate::r#async::fiber::AsyncState::new(); - let _ = executor - .call_func_async(&async_state, &async_hello, []) - .await?; - } - - assert_eq!(ASYNC_HOST_FUNCS.read().len(), 0); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0); - - Ok(()) - } - - #[cfg(all(feature = "async", target_os = "linux"))] - #[tokio::test] - async fn test_func_async_func() -> Result<(), Box> { - { - #[derive(Debug)] - struct Data { - _x: i32, - _y: String, - _v: Vec, - _s: Vec, - } - let data: Data = Data { - _x: 12, - _y: "hello".to_string(), - _v: vec![1, 2, 3], - _s: vec!["macos", "linux", "windows"], - }; - - // define async host function - fn f( - _frame: CallingFrame, - _args: Vec, - data: *mut std::ffi::c_void, - ) -> Box<(dyn std::future::Future, HostFuncError>> + Send)> - { - let data = unsafe { Box::from_raw(data as *mut T) }; - - Box::new(async move { - for _ in 0..10 { - println!("[async hello] say hello"); - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - println!("host_data: {:?}", data); - } - - println!("[async hello] Done!"); - - Ok(vec![]) - }) - } - - // create a FuncType - let result = FuncType::create(vec![], vec![]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - - // create an async host function - let result = Function::create_async_func( - &func_ty, - Box::new(f::>), - Some(Box::new(data)), - 0, - ); - assert!(result.is_ok()); - let async_hello_func = result.unwrap(); - - // create an Executor - let result = Executor::create(None, None); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - assert!(!executor.inner.0.is_null()); - - // create a Store - let result = Store::create(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - // create an AsyncWasiModule - let result = AsyncWasiModule::create(Some(vec!["abc"]), Some(vec![("a", "1")]), None); - assert!(result.is_ok()); - let async_wasi_module = result.unwrap(); - - // register async_wasi module into the store - let wasi_import = WasiInstance::AsyncWasi(async_wasi_module); - let result = executor.register_wasi_instance(&mut store, &wasi_import); - assert!(result.is_ok()); - - // create an ImportModule - let mut import = ImportModule::::create("extern", None)?; - import.add_func("async_hello", async_hello_func); - - executor.register_import_module(&mut store, &import)?; - - let extern_instance = store.module("extern")?; - let async_hello = extern_instance.get_func("async_hello")?; - - async fn tick() { - let mut i = 0; - loop { - println!("[tick] i={i}"); - tokio::time::sleep(std::time::Duration::from_millis(500)).await; - i += 1; - } - } - tokio::spawn(tick()); - - let async_state = crate::r#async::fiber::AsyncState::new(); - let _ = executor - .call_func_async(&async_state, &async_hello, []) - .await?; - } - - assert_eq!(ASYNC_HOST_FUNCS.read().len(), 0); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0); - - Ok(()) - } } diff --git a/crates/wasmedge-sys/src/instance/global.rs b/crates/wasmedge-sys/src/instance/global.rs index 29230aa99..8b088e994 100644 --- a/crates/wasmedge-sys/src/instance/global.rs +++ b/crates/wasmedge-sys/src/instance/global.rs @@ -73,22 +73,6 @@ impl Global { /// /// If fail to set value, then an error is returned. /// - /// # Example - /// - /// ``` - /// use wasmedge_sys::{Global, GlobalType, WasmValue}; - /// use wasmedge_types::{ValType, Mutability}; - /// - /// // create a GlobalType instance - /// let ty = GlobalType::create(ValType::F32, Mutability::Var).expect("fail to create a GlobalType"); - /// // create a Global instance - /// let mut global = Global::create(&ty, WasmValue::from_f32(3.1415)).expect("fail to create a Global"); - /// - /// global.set_value(WasmValue::from_f32(314.15)).expect("fail to set a new value for a Global"); - /// assert_eq!(global.get_value().to_f32(), 314.15); - /// ``` - /// - /// pub fn set_value(&mut self, val: WasmValue) -> WasmEdgeResult<()> { let ty = self.ty()?; if ty.mutability() == Mutability::Const { @@ -199,14 +183,10 @@ pub(crate) struct InnerGlobalType(pub(crate) *mut ffi::WasmEdge_GlobalTypeContex unsafe impl Send for InnerGlobalType {} unsafe impl Sync for InnerGlobalType {} -// #[cfg(test)] -#[cfg(ignore)] +#[cfg(test)] mod tests { use super::*; - use std::{ - sync::{Arc, Mutex}, - thread, - }; + use std::thread; use wasmedge_types::{Mutability, ValType}; #[test] @@ -217,7 +197,6 @@ mod tests { assert!(result.is_ok()); let global_ty = result.unwrap(); assert!(!global_ty.inner.0.is_null()); - assert!(!global_ty.registered); // value type assert_eq!(global_ty.value_type(), ValType::I32); @@ -229,10 +208,7 @@ mod tests { #[allow(clippy::assertions_on_result_states)] fn test_global_const_i32() { // create a GlobalType instance - let result = GlobalType::create(ValType::I32, Mutability::Const); - assert!(result.is_ok()); - let ty = result.unwrap(); - assert!(!ty.inner.0.is_null()); + let ty = wasmedge_types::GlobalType::new(ValType::I32, Mutability::Const); // create a const Global instance let result = Global::create(&ty, WasmValue::from_i32(99)); @@ -248,9 +224,7 @@ mod tests { let result = global_const.ty(); assert!(result.is_ok()); let ty = result.unwrap(); - assert!(!ty.inner.0.is_null()); - assert!(ty.registered); - assert_eq!(ty.value_type(), ValType::I32); + assert_eq!(ty.value_ty(), ValType::I32); assert_eq!(ty.mutability(), Mutability::Const); } @@ -258,10 +232,7 @@ mod tests { #[allow(clippy::assertions_on_result_states)] fn test_global_var_f32() { // create a GlobalType instance - let result = GlobalType::create(ValType::F32, Mutability::Var); - assert!(result.is_ok()); - let ty = result.unwrap(); - assert!(!ty.inner.0.is_null()); + let ty = wasmedge_types::GlobalType::new(ValType::F32, Mutability::Var); // create a Var Global instance let result = Global::create(&ty, WasmValue::from_f32(13.14)); @@ -278,9 +249,7 @@ mod tests { let result = global_var.ty(); assert!(result.is_ok()); let ty = result.unwrap(); - assert!(!ty.inner.0.is_null()); - assert!(ty.registered); - assert_eq!(ty.value_type(), ValType::F32); + assert_eq!(ty.value_ty(), ValType::F32); assert_eq!(ty.mutability(), Mutability::Var); } @@ -289,10 +258,7 @@ mod tests { fn test_global_conflict() { { // create a GlobalType instance - let result = GlobalType::create(ValType::F32, Mutability::Var); - assert!(result.is_ok()); - let ty = result.unwrap(); - assert!(!ty.inner.0.is_null()); + let ty = wasmedge_types::GlobalType::new(ValType::F32, Mutability::Var); // create a Var Global instance with a value of mis-matched Value::I32 type let result = Global::create(&ty, WasmValue::from_i32(520)); @@ -301,10 +267,7 @@ mod tests { { // create a GlobalType instance - let result = GlobalType::create(ValType::F32, Mutability::Var); - assert!(result.is_ok()); - let ty = result.unwrap(); - assert!(!ty.inner.0.is_null()); + let ty = wasmedge_types::GlobalType::new(ValType::F32, Mutability::Var); // create a Var Global instance with a value of Value::F32 type let result = Global::create(&ty, WasmValue::from_f32(13.14)); @@ -327,28 +290,7 @@ mod tests { fn test_global_send() { { // create a GlobalType instance - let result = GlobalType::create(ValType::I32, Mutability::Const); - assert!(result.is_ok()); - let global_ty = result.unwrap(); - - let handle = thread::spawn(move || { - assert!(!global_ty.inner.0.is_null()); - assert!(!global_ty.registered); - - // value type - assert_eq!(global_ty.value_type(), ValType::I32); - // Mutability - assert_eq!(global_ty.mutability(), Mutability::Const); - }); - - handle.join().unwrap() - } - - { - // create a GlobalType instance - let result = GlobalType::create(ValType::I32, Mutability::Const); - assert!(result.is_ok()); - let global_ty = result.unwrap(); + let global_ty = wasmedge_types::GlobalType::new(ValType::I32, Mutability::Const); // create a Global instance let result = Global::create(&global_ty, WasmValue::from_i32(5)); @@ -367,74 +309,20 @@ mod tests { #[test] fn test_global_sync() { // create a GlobalType instance - let result = GlobalType::create(ValType::I32, Mutability::Const); - assert!(result.is_ok()); - let global_ty = result.unwrap(); + let global_ty = wasmedge_types::GlobalType::new(ValType::I32, Mutability::Const); // create a Global instance let result = Global::create(&global_ty, WasmValue::from_i32(5)); assert!(result.is_ok()); - let global = Arc::new(Mutex::new(result.unwrap())); - - let global_cloned = Arc::clone(&global); - let handle = thread::spawn(move || { - let result = global_cloned.lock(); - assert!(result.is_ok()); - let global = result.unwrap(); - - assert_eq!(global.get_value().to_i32(), 5); - }); - - handle.join().unwrap() - } - - #[test] - fn test_global_clone() { - { - // create a GlobalType instance - let result = GlobalType::create(ValType::I32, Mutability::Const); - assert!(result.is_ok()); - let global_ty = result.unwrap(); - - // create a Global instance - let result = Global::create(&global_ty, WasmValue::from_i32(5)); - assert!(result.is_ok()); - let global = result.unwrap(); - - let global_cloned = global.clone(); - - drop(global); - - assert_eq!(global_cloned.get_value().to_i32(), 5); - } - - { - // create a GlobalType instance - let result = GlobalType::create(ValType::F32, Mutability::Var); - assert!(result.is_ok()); - let ty = result.unwrap(); - assert!(!ty.inner.0.is_null()); - - // create a Var Global instance - let result = Global::create(&ty, WasmValue::from_f32(13.14)); - assert!(result.is_ok()); - let mut global_var = result.unwrap(); - assert_eq!(global_var.get_value().to_f32(), 13.14); - - let global_var_cloned = global_var.clone(); - assert_eq!( - global_var_cloned.get_value().to_f32(), - global_var.get_value().to_f32() - ); - - // access the value held by global_var - let result = global_var.set_value(WasmValue::from_f32(1.314)); - assert!(result.is_ok()); - assert_eq!(global_var.get_value().to_f32(), 1.314); - - drop(global_var); - - assert_eq!(global_var_cloned.get_value().to_f32(), 1.314); - } + let global = result.unwrap(); + let global = &global; + + std::thread::scope(|s| { + let _ = s + .spawn(move || { + assert_eq!(global.get_value().to_i32(), 5); + }) + .join(); + }) } } diff --git a/crates/wasmedge-sys/src/instance/memory.rs b/crates/wasmedge-sys/src/instance/memory.rs index 4747bc356..bd90487de 100644 --- a/crates/wasmedge-sys/src/instance/memory.rs +++ b/crates/wasmedge-sys/src/instance/memory.rs @@ -24,17 +24,6 @@ impl Memory { /// /// * If fail to create the memory instance, then [WasmEdgeError::Mem(MemError::Create)](wasmedge_types::error::MemError) is returned. /// - /// # Example - /// - /// ``` - /// use wasmedge_sys::{MemType, Memory}; - /// - /// let ty = MemType::create(10, Some(20), false).expect("fail to create memory type"); - /// - /// let memory = Memory::create(&ty); - /// - /// ``` - /// pub fn create(ty: &wasmedge_types::MemoryType) -> WasmEdgeResult { let ty: MemType = ty.into(); let ctx = unsafe { ffi::WasmEdge_MemoryInstanceCreate(ty.inner.0 as *const _) }; @@ -106,40 +95,6 @@ impl Memory { /// If the sum of the `offset` and the data length is larger than the size of the [Memory], /// then an error is returned. /// - /// ``` - /// use wasmedge_sys::{Memory, MemType}; - /// use wasmedge_types::error::{CoreError, CoreExecutionError, WasmEdgeError}; - /// - /// // create a Memory: the min size 1 and the max size 2 - /// let ty = MemType::create(1, Some(2), false).expect("fail to create a memory type"); - /// let mut mem = Memory::create(&ty).expect("fail to create a Memory"); - /// - /// // set data and the data length is larger than the data size in the memory - /// let result = mem.set_data(vec![1; 10], u32::pow(2, 16) - 9); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err(), Box::new(WasmEdgeError::Core(CoreError::Execution(CoreExecutionError::MemoryOutOfBounds)))); - /// ``` - /// - /// # Example - /// - /// ``` - /// use wasmedge_sys::{MemType, Memory}; - /// - /// // create a Memory: the min size 1 and the max size 2 - /// let ty = MemType::create(1, Some(2), false).expect("fail to create a memory type"); - /// let mut mem = Memory::create(&ty).expect("fail to create a Memory"); - /// // page count - /// let count = mem.size(); - /// assert_eq!(count, 1); - /// - /// // set data - /// mem.set_data(vec![1; 10], 10).expect("fail to set data"); - /// - /// // get data - /// let data = mem.get_data(10, 10).expect("fail to get data"); - /// assert_eq!(data, vec![1; 10]); - /// ``` - /// pub fn set_data(&mut self, data: impl AsRef<[u8]>, offset: u32) -> WasmEdgeResult<()> { unsafe { check(ffi::WasmEdge_MemoryInstanceSetData( @@ -216,23 +171,6 @@ impl Memory { /// /// If fail to grow the page count, then an error is returned. /// - /// # Example - /// - /// ``` - /// use wasmedge_sys::{MemType, Memory}; - /// - /// // create a Memory with a limit range [10, 20] - /// let ty = MemType::create(10, Some(20), false).expect("fail to create a memory type"); - /// let mut mem = Memory::create(&ty).expect("fail to create a Memory"); - /// // check page count - /// let count = mem.size(); - /// assert_eq!(count, 10); - /// - /// // grow 5 pages - /// mem.grow(10).expect("fail to grow the page count"); - /// assert_eq!(mem.size(), 20); - /// ``` - /// pub fn grow(&mut self, count: u32) -> WasmEdgeResult<()> { unsafe { check(ffi::WasmEdge_MemoryInstanceGrowPage(self.inner.0, count)) } } @@ -387,14 +325,10 @@ pub(crate) struct InnerMemType(pub(crate) *mut ffi::WasmEdge_MemoryTypeContext); unsafe impl Send for InnerMemType {} unsafe impl Sync for InnerMemType {} -// #[cfg(test)] -#[cfg(ignore)] +#[cfg(test)] mod tests { use super::*; - use std::{ - sync::{Arc, Mutex}, - thread, - }; + use std::thread; use wasmedge_types::error::{CoreError, CoreExecutionError, WasmEdgeError}; #[test] @@ -404,7 +338,6 @@ mod tests { assert!(result.is_ok()); let ty = result.unwrap(); assert!(!ty.inner.0.is_null()); - assert!(!ty.registered); assert_eq!(ty.min(), 0); assert_eq!(ty.max(), Some(u32::MAX)); @@ -413,7 +346,6 @@ mod tests { assert!(result.is_ok()); let ty = result.unwrap(); assert!(!ty.inner.0.is_null()); - assert!(!ty.registered); assert_eq!(ty.min(), 10); assert_eq!(ty.max(), Some(101)); } @@ -422,24 +354,21 @@ mod tests { #[allow(clippy::assertions_on_result_states)] fn test_memory_grow() { // create a Memory with a limit range [10, 20] - let result = MemType::create(10, Some(20), false); + let result = wasmedge_types::MemoryType::new(10, Some(20), false); assert!(result.is_ok()); let ty = result.unwrap(); let result = Memory::create(&ty); assert!(result.is_ok()); let mut mem = result.unwrap(); - assert!(!mem.inner.lock().0.is_null()); - assert!(!mem.registered); + assert!(!mem.inner.0.is_null()); // get type let result = mem.ty(); assert!(result.is_ok()); let ty = result.unwrap(); - assert!(!ty.inner.0.is_null()); - assert!(ty.registered); // check limit - assert_eq!(ty.min(), 10); - assert_eq!(ty.max(), Some(20)); + assert_eq!(ty.minimum(), 10); + assert_eq!(ty.maximum(), Some(20)); // check page count let count = mem.size(); @@ -459,14 +388,13 @@ mod tests { #[allow(clippy::assertions_on_result_states)] fn test_memory_data() { // create a Memory: the min size 1 and the max size 2 - let result = MemType::create(1, Some(2), false); + let result = wasmedge_types::MemoryType::new(1, Some(2), false); assert!(result.is_ok()); let ty = result.unwrap(); let result = Memory::create(&ty); assert!(result.is_ok()); let mut mem = result.unwrap(); - assert!(!mem.inner.lock().0.is_null()); - assert!(!mem.registered); + assert!(!mem.inner.0.is_null()); // check page count let count = mem.size(); @@ -508,17 +436,13 @@ mod tests { #[test] fn test_memory_send() { { - let result = MemType::create(10, Some(101), false); + let result = wasmedge_types::MemoryType::new(10, Some(101), false); assert!(result.is_ok()); let ty = result.unwrap(); - assert!(!ty.inner.0.is_null()); - assert!(!ty.registered); let handle = thread::spawn(move || { - assert!(!ty.inner.0.is_null()); - assert!(!ty.registered); - assert_eq!(ty.min(), 10); - assert_eq!(ty.max(), Some(101)); + assert_eq!(ty.minimum(), 10); + assert_eq!(ty.maximum(), Some(101)); }); handle.join().unwrap() @@ -526,25 +450,22 @@ mod tests { { // create a Memory with a limit range [10, 20] - let result = MemType::create(10, Some(20), false); + let result = wasmedge_types::MemoryType::new(10, Some(20), false); assert!(result.is_ok()); let ty = result.unwrap(); let result = Memory::create(&ty); assert!(result.is_ok()); let mem = result.unwrap(); - assert!(!mem.inner.lock().0.is_null()); - assert!(!mem.registered); + assert!(!mem.inner.0.is_null()); let handle = thread::spawn(move || { // get type let result = mem.ty(); assert!(result.is_ok()); let ty = result.unwrap(); - assert!(!ty.inner.0.is_null()); - assert!(ty.registered); // check limit - assert_eq!(ty.min(), 10); - assert_eq!(ty.max(), Some(20)); + assert_eq!(ty.minimum(), 10); + assert_eq!(ty.maximum(), Some(20)); // check page count let count = mem.size(); @@ -558,59 +479,31 @@ mod tests { #[test] fn test_memory_sync() { // create a Memory with a limit range [10, 20] - let result = MemType::create(10, Some(20), false); + let result = wasmedge_types::MemoryType::new(10, Some(20), false); assert!(result.is_ok()); let ty = result.unwrap(); let result = Memory::create(&ty); assert!(result.is_ok()); let mem = result.unwrap(); - assert!(!mem.inner.lock().0.is_null()); - assert!(!mem.registered); - let memory = Arc::new(Mutex::new(mem)); - - let memory_cloned = Arc::clone(&memory); - let handle = thread::spawn(move || { - let mem = memory_cloned.lock().unwrap(); - - // get type - let result = mem.ty(); - assert!(result.is_ok()); - let ty = result.unwrap(); - assert!(!ty.inner.0.is_null()); - assert!(ty.registered); - // check limit - assert_eq!(ty.min(), 10); - assert_eq!(ty.max(), Some(20)); - - // check page count - let count = mem.size(); - assert_eq!(count, 10); - }); - - handle.join().unwrap() - } - - #[test] - fn test_memory_clone() { - #[derive(Debug, Clone)] - struct RecordsMemory { - memory: Memory, - } - - // create a Memory with a limit range [10, 20] - let result = MemType::create(10, Some(20), false); - assert!(result.is_ok()); - let ty = result.unwrap(); - let result = Memory::create(&ty); - assert!(result.is_ok()); - let memory = result.unwrap(); - - let rec_mem = RecordsMemory { memory }; - - let rec_mem_cloned = rec_mem.clone(); - - drop(rec_mem); - - assert_eq!(rec_mem_cloned.memory.size(), 10); + assert!(!mem.inner.0.is_null()); + let mem = &mem; + + std::thread::scope(|s| { + let _ = s + .spawn(|| { + // get type + let result = mem.ty(); + assert!(result.is_ok()); + let ty = result.unwrap(); + // check limit + assert_eq!(ty.minimum(), 10); + assert_eq!(ty.maximum(), Some(20)); + + // check page count + let count = mem.size(); + assert_eq!(count, 10); + }) + .join(); + }) } } diff --git a/crates/wasmedge-sys/src/instance/module.rs b/crates/wasmedge-sys/src/instance/module.rs index 1b7713757..4160f496e 100644 --- a/crates/wasmedge-sys/src/instance/module.rs +++ b/crates/wasmedge-sys/src/instance/module.rs @@ -702,63 +702,51 @@ impl WasiModule { } } -// #[cfg(test)] -#[cfg(iginore)] +#[cfg(test)] mod tests { use super::*; - use crate::{ - instance::function::FuncTypeOwn, CallingFrame, Config, Executor, GlobalType, ImportModule, - MemType, Store, TableType, WasmValue, HOST_FUNCS, HOST_FUNC_FOOTPRINTS, + use crate::{CallingFrame, Executor, GlobalType, ImportModule, Store, TableType, WasmValue}; + + use wasmedge_types::{ + error::{CoreError, CoreExecutionError}, + FuncType, MemoryType, Mutability, RefType, ValType, }; - #[cfg(not(feature = "async"))] - use std::sync::{Arc, Mutex}; - use std::thread; - use wasmedge_macro::sys_host_function; - use wasmedge_types::{error::HostFuncError, Mutability, NeverType, RefType, ValType}; #[test] - // #[cfg(not(feature = "async"))] #[allow(clippy::assertions_on_result_states)] fn test_instance_add_instance() { - assert_eq!(HOST_FUNCS.read().len(), 0); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 0); - let host_name = "extern"; // create an import module - let result = ImportModule::::create(host_name, None); + let result = ImportModule::<()>::create(host_name, Box::new(())); assert!(result.is_ok()); let mut import = result.unwrap(); // create a host function - let result = FuncTypeOwn::create([ValType::ExternRef, ValType::I32], [ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - let result = Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0); - assert!(result.is_ok()); + let func_ty = wasmedge_types::FuncType::new( + vec![ValType::ExternRef, ValType::I32], + vec![ValType::I32], + ); - assert_eq!(HOST_FUNCS.read().len(), 1); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1); + let result = unsafe { + Function::create_sync_func(&func_ty, real_add, import.get_host_data_mut(), 0) + }; + assert!(result.is_ok()); let host_func = result.unwrap(); // add the host function import.add_func("func-add", host_func); - assert_eq!(HOST_FUNCS.read().len(), 1); - assert_eq!(HOST_FUNC_FOOTPRINTS.lock().len(), 1); - // create a table - let result = TableType::create(RefType::FuncRef, 10, Some(20)); - assert!(result.is_ok()); - let table_ty = result.unwrap(); - let result = Table::create(&table_ty); + let table_ty = TableType::new(RefType::FuncRef, 10, Some(20)); + let result = Table::create(table_ty); assert!(result.is_ok()); let host_table = result.unwrap(); // add the table import.add_table("table", host_table); // create a memory - let result = MemType::create(1, Some(2), false); + let result = MemoryType::new(1, Some(2), false); assert!(result.is_ok()); let mem_ty = result.unwrap(); let result = Memory::create(&mem_ty); @@ -768,9 +756,7 @@ mod tests { import.add_memory("memory", host_memory); // create a global - let result = GlobalType::create(ValType::I32, Mutability::Const); - assert!(result.is_ok()); - let global_ty = result.unwrap(); + let global_ty = GlobalType::new(ValType::I32, Mutability::Const); let result = Global::create(&global_ty, WasmValue::from_i32(666)); assert!(result.is_ok()); let host_global = result.unwrap(); @@ -778,137 +764,8 @@ mod tests { import.add_global("global_i32", host_global); } + #[cfg(target_family = "unix")] #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_instance_import_module_send() { - let host_name = "extern"; - - // create an ImportModule instance - let result = ImportModule::::create(host_name, None); - assert!(result.is_ok()); - let import = result.unwrap(); - - let handle = thread::spawn(move || { - assert!(!import.inner.0.is_null()); - println!("{:?}", import.inner); - }); - - handle.join().unwrap(); - } - - #[test] - #[cfg(not(feature = "async"))] - #[allow(clippy::assertions_on_result_states)] - fn test_instance_import_module_sync() { - let host_name = "extern"; - - // create an ImportModule instance - let result = ImportModule::::create(host_name, None); - assert!(result.is_ok()); - let mut import = result.unwrap(); - - // add host function - let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - let result = Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0); - assert!(result.is_ok()); - let host_func = result.unwrap(); - import.add_func("add", host_func); - - // add table - let result = TableType::create(RefType::FuncRef, 0, Some(u32::MAX)); - assert!(result.is_ok()); - let ty = result.unwrap(); - let result = Table::create(&ty); - assert!(result.is_ok()); - let table = result.unwrap(); - import.add_table("table", table); - - // add memory - let memory = { - let result = MemType::create(10, Some(20), false); - assert!(result.is_ok()); - let mem_ty = result.unwrap(); - let result = Memory::create(&mem_ty); - assert!(result.is_ok()); - result.unwrap() - }; - import.add_memory("memory", memory); - - // add globals - let result = GlobalType::create(ValType::F32, Mutability::Const); - assert!(result.is_ok()); - let ty = result.unwrap(); - let result = Global::create(&ty, WasmValue::from_f32(3.5)); - assert!(result.is_ok()); - let global = result.unwrap(); - import.add_global("global", global); - - let import = Arc::new(Mutex::new(import)); - let import_cloned = Arc::clone(&import); - let handle = thread::spawn(move || { - let result = import_cloned.lock(); - assert!(result.is_ok()); - let import = result.unwrap(); - - // create a store - let result = Store::create(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - assert!(!store.inner.0.is_null()); - assert!(!store.registered); - - // create an executor - let result = Config::create(); - assert!(result.is_ok()); - let config = result.unwrap(); - let result = Executor::create(Some(&config), None); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - // register import object into store - let result = executor.register_import_module(&mut store, &import); - assert!(result.is_ok()); - - // get the exported module by name - let result = store.module("extern"); - assert!(result.is_ok()); - let instance = result.unwrap(); - - // get the exported function by name - let result = instance.get_func("add"); - assert!(result.is_ok()); - - // get the exported global by name - let result = instance.get_global("global"); - assert!(result.is_ok()); - let global = result.unwrap(); - assert!(!global.inner.lock().0.is_null() && global.registered); - let val = global.get_value(); - assert_eq!(val.to_f32(), 3.5); - - // get the exported memory by name - let result = instance.get_memory("memory"); - assert!(result.is_ok()); - let memory = result.unwrap(); - let result = memory.ty(); - assert!(result.is_ok()); - let ty = result.unwrap(); - assert_eq!(ty.min(), 10); - assert_eq!(ty.max(), Some(20)); - - // get the exported table by name - let result = instance.get_table("table"); - assert!(result.is_ok()); - }); - - handle.join().unwrap(); - } - - #[cfg(all(not(feature = "async"), target_family = "unix"))] - #[test] - #[allow(clippy::assertions_on_result_states)] fn test_instance_wasi() { // create a wasi module instance { @@ -946,36 +803,33 @@ mod tests { } #[test] - #[cfg(not(feature = "async"))] #[allow(clippy::assertions_on_result_states)] fn test_instance_find_xxx() -> Result<(), Box> { let module_name = "extern_module"; // create ImportModule instance - let result = ImportModule::::create(module_name, None); + let result = ImportModule::create(module_name, Box::new(())); assert!(result.is_ok()); let mut import = result.unwrap(); // add host function - let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - let result = Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0); + let func_ty = FuncType::new(vec![ValType::I32; 2], vec![ValType::I32]); + let result = unsafe { + Function::create_sync_func(&func_ty, real_add, import.get_host_data_mut(), 0) + }; assert!(result.is_ok()); let host_func = result.unwrap(); import.add_func("add", host_func); // add table - let result = TableType::create(RefType::FuncRef, 0, Some(u32::MAX)); - assert!(result.is_ok()); - let ty = result.unwrap(); - let result = Table::create(&ty); + let ty = TableType::new(RefType::FuncRef, 0, Some(u32::MAX)); + let result = Table::create(ty); assert!(result.is_ok()); let table = result.unwrap(); import.add_table("table", table); // add memory - let result = MemType::create(0, Some(u32::MAX), false); + let result = MemoryType::new(0, Some(u32::MAX), false); assert!(result.is_ok()); let mem_ty = result.unwrap(); let result = Memory::create(&mem_ty); @@ -984,9 +838,7 @@ mod tests { import.add_memory("mem", memory); // add global - let result = GlobalType::create(ValType::F32, Mutability::Const); - assert!(result.is_ok()); - let ty = result.unwrap(); + let ty = GlobalType::new(ValType::F32, Mutability::Const); let result = Global::create(&ty, WasmValue::from_f32(3.5)); assert!(result.is_ok()); let global = result.unwrap(); @@ -1016,16 +868,14 @@ mod tests { // check the type of the function let result = func.ty(); - assert!(result.is_ok()); + assert!(result.is_some()); let ty = result.unwrap(); // check the parameter types - let param_types = ty.params_type_iter().collect::>(); - assert_eq!(param_types, [ValType::I32, ValType::I32]); + assert_eq!(ty.args(), &[ValType::I32, ValType::I32]); // check the return types - let return_types = ty.returns_type_iter().collect::>(); - assert_eq!(return_types, [ValType::I32]); + assert_eq!(ty.returns(), &[ValType::I32]); // get the exported table named "table" let result = instance.get_table("table"); @@ -1037,11 +887,11 @@ mod tests { assert!(result.is_ok()); let ty = result.unwrap(); assert_eq!(ty.elem_ty(), RefType::FuncRef); - assert_eq!(ty.min(), 0); - assert_eq!(ty.max(), Some(u32::MAX)); + assert_eq!(ty.minimum(), 0); + assert_eq!(ty.maximum(), Some(u32::MAX)); // get the exported memory named "mem" - let result = instance.get_memory("mem"); + let result = instance.get_memory_ref("mem"); assert!(result.is_ok()); let memory = result.unwrap(); @@ -1049,8 +899,8 @@ mod tests { let result = memory.ty(); assert!(result.is_ok()); let ty = result.unwrap(); - assert_eq!(ty.min(), 0); - assert_eq!(ty.max(), Some(u32::MAX)); + assert_eq!(ty.minimum(), 0); + assert_eq!(ty.maximum(), Some(u32::MAX)); // get the exported global named "global" let result = instance.get_global("global"); @@ -1061,43 +911,40 @@ mod tests { let result = global.ty(); assert!(result.is_ok()); let global = result.unwrap(); - assert_eq!(global.value_type(), ValType::F32); + assert_eq!(global.value_ty(), ValType::F32); assert_eq!(global.mutability(), Mutability::Const); Ok(()) } #[test] - #[cfg(not(feature = "async"))] #[allow(clippy::assertions_on_result_states)] fn test_instance_find_names() -> Result<(), Box> { let module_name = "extern_module"; // create ImportModule instance - let result = ImportModule::::create(module_name, None); + let result = ImportModule::create(module_name, Box::new(())); assert!(result.is_ok()); let mut import = result.unwrap(); // add host function - let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - let result = Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0); + let func_ty = FuncType::new(vec![ValType::I32; 2], vec![ValType::I32]); + let result = unsafe { + Function::create_sync_func(&func_ty, real_add, import.get_host_data_mut(), 0) + }; assert!(result.is_ok()); let host_func = result.unwrap(); import.add_func("add", host_func); // add table - let result = TableType::create(RefType::FuncRef, 0, Some(u32::MAX)); - assert!(result.is_ok()); - let ty = result.unwrap(); - let result = Table::create(&ty); + let ty = TableType::new(RefType::FuncRef, 0, Some(u32::MAX)); + let result = Table::create(ty); assert!(result.is_ok()); let table = result.unwrap(); import.add_table("table", table); // add memory - let result = MemType::create(0, Some(u32::MAX), false); + let result = MemoryType::new(0, Some(u32::MAX), false); assert!(result.is_ok()); let mem_ty = result.unwrap(); let result = Memory::create(&mem_ty); @@ -1106,9 +953,7 @@ mod tests { import.add_memory("mem", memory); // add global - let result = GlobalType::create(ValType::F32, Mutability::Const); - assert!(result.is_ok()); - let ty = result.unwrap(); + let ty = GlobalType::new(ValType::F32, Mutability::Const); let result = Global::create(&ty, WasmValue::from_f32(3.5)); assert!(result.is_ok()); let global = result.unwrap(); @@ -1154,266 +999,30 @@ mod tests { Ok(()) } - #[test] - #[cfg(not(feature = "async"))] - #[allow(clippy::assertions_on_result_states)] - fn test_instance_get() { - let module_name = "extern_module"; - - let result = Store::create(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - assert!(!store.inner.0.is_null()); - assert!(!store.registered); - - // check the length of registered module list in store before instantiation - assert_eq!(store.module_len(), 0); - assert!(store.module_names().is_none()); - - // create ImportObject instance - let result = ImportModule::::create(module_name, None); - assert!(result.is_ok()); - let mut import = result.unwrap(); - - // add host function - let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - let result = Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0); - assert!(result.is_ok()); - let host_func = result.unwrap(); - import.add_func("add", host_func); - - // add table - let result = TableType::create(RefType::FuncRef, 0, Some(u32::MAX)); - assert!(result.is_ok()); - let ty = result.unwrap(); - let result = Table::create(&ty); - assert!(result.is_ok()); - let table = result.unwrap(); - import.add_table("table", table); - - // add memory - let memory = { - let result = MemType::create(10, Some(20), false); - assert!(result.is_ok()); - let mem_ty = result.unwrap(); - let result = Memory::create(&mem_ty); - assert!(result.is_ok()); - result.unwrap() - }; - import.add_memory("mem", memory); - - // add globals - let result = GlobalType::create(ValType::F32, Mutability::Const); - assert!(result.is_ok()); - let ty = result.unwrap(); - let result = Global::create(&ty, WasmValue::from_f32(3.5)); - assert!(result.is_ok()); - let global = result.unwrap(); - import.add_global("global", global); - - let result = Config::create(); - assert!(result.is_ok()); - let config = result.unwrap(); - let result = Executor::create(Some(&config), None); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - let result = executor.register_import_module(&mut store, &import); - assert!(result.is_ok()); - - let result = store.module(module_name); - assert!(result.is_ok()); - let mut instance = result.unwrap(); - - // get the exported memory - let result = instance.get_memory("mem"); - assert!(result.is_ok()); - let memory = result.unwrap(); - let result = memory.ty(); - assert!(result.is_ok()); - let ty = result.unwrap(); - assert_eq!(ty.min(), 10); - assert_eq!(ty.max(), Some(20)); - - // get host data - assert!(instance.host_data::().is_none()); - } - - #[sys_host_function] fn real_add( - _frame: CallingFrame, + _data: &mut (), + _inst: &mut Instance, + _frame: &mut CallingFrame, inputs: Vec, - ) -> Result, HostFuncError> { + ) -> Result, CoreError> { if inputs.len() != 2 { - return Err(HostFuncError::User(1)); + return Err(CoreError::Execution(CoreExecutionError::FuncTypeMismatch)); } let a = if inputs[0].ty() == ValType::I32 { inputs[0].to_i32() } else { - return Err(HostFuncError::User(2)); + return Err(CoreError::Execution(CoreExecutionError::FuncTypeMismatch)); }; let b = if inputs[1].ty() == ValType::I32 { inputs[1].to_i32() } else { - return Err(HostFuncError::User(3)); + return Err(CoreError::Execution(CoreExecutionError::FuncTypeMismatch)); }; let c = a + b; Ok(vec![WasmValue::from_i32(c)]) } - - #[cfg(not(feature = "async"))] - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_instance_clone() { - // clone of ImportModule - { - let host_name = "extern"; - - // create an import module - let result = ImportModule::::create(host_name, None); - assert!(result.is_ok()); - let mut import = result.unwrap(); - - // create a host function - let result = FuncType::create([ValType::ExternRef, ValType::I32], [ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - let result = - Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0); - assert!(result.is_ok()); - let host_func = result.unwrap(); - // add the host function - import.add_func("func-add", host_func); - - // create a table - let result = TableType::create(RefType::FuncRef, 10, Some(20)); - assert!(result.is_ok()); - let table_ty = result.unwrap(); - let result = Table::create(&table_ty); - assert!(result.is_ok()); - let host_table = result.unwrap(); - // add the table - import.add_table("table", host_table); - - // create a memory - let result = MemType::create(1, Some(2), false); - assert!(result.is_ok()); - let mem_ty = result.unwrap(); - let result = Memory::create(&mem_ty); - assert!(result.is_ok()); - let host_memory = result.unwrap(); - // add the memory - import.add_memory("memory", host_memory); - - // create a global - let result = GlobalType::create(ValType::I32, Mutability::Const); - assert!(result.is_ok()); - let global_ty = result.unwrap(); - let result = Global::create(&global_ty, WasmValue::from_i32(666)); - assert!(result.is_ok()); - let host_global = result.unwrap(); - // add the global - import.add_global("global_i32", host_global); - assert_eq!(Arc::strong_count(&import.inner), 1); - - // clone the import module - let import_clone = import.clone(); - assert_eq!(Arc::strong_count(&import.inner), 2); - - drop(import); - assert_eq!(Arc::strong_count(&import_clone.inner), 1); - drop(import_clone); - } - - // clone of WasiModule - { - let result = WasiModule::create(None, None, None); - assert!(result.is_ok()); - - let result = WasiModule::create( - Some(vec!["arg1", "arg2"]), - Some(vec!["ENV1=VAL1", "ENV1=VAL2", "ENV3=VAL3"]), - Some(vec![ - "apiTestData", - "Makefile", - "CMakeFiles", - "ssvmAPICoreTests", - ".:.", - ]), - ); - assert!(result.is_ok()); - - let result = WasiModule::create( - None, - Some(vec!["ENV1=VAL1", "ENV1=VAL2", "ENV3=VAL3"]), - Some(vec![ - "apiTestData", - "Makefile", - "CMakeFiles", - "ssvmAPICoreTests", - ".:.", - ]), - ); - assert!(result.is_ok()); - let wasi_import = result.unwrap(); - assert_eq!(wasi_import.exit_code(), 0); - assert_eq!(std::sync::Arc::strong_count(&wasi_import.inner), 1); - - // clone - let wasi_import_clone = wasi_import.clone(); - assert_eq!(std::sync::Arc::strong_count(&wasi_import.inner), 2); - - drop(wasi_import); - assert_eq!(std::sync::Arc::strong_count(&wasi_import_clone.inner), 1); - drop(wasi_import_clone); - } - } - - #[test] - fn test_instance_create_import_with_data() { - let module_name = "extern_module"; - - // define host data - #[derive(Clone, Debug)] - struct Circle { - radius: i32, - } - - let circle = Circle { radius: 10 }; - - // create an import module - let result = ImportModule::create(module_name, Some(Box::new(circle))); - - assert!(result.is_ok()); - let import = result.unwrap(); - - let result = Config::create(); - assert!(result.is_ok()); - let config = result.unwrap(); - let result = Executor::create(Some(&config), None); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - let result = Store::create(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - let result = executor.register_import_module(&mut store, &import); - assert!(result.is_ok()); - - let result = store.module(module_name); - assert!(result.is_ok()); - let mut instance = result.unwrap(); - - let result = instance.host_data::(); - assert!(result.is_some()); - let host_data = result.unwrap(); - assert_eq!(host_data.radius, 10); - } } diff --git a/crates/wasmedge-sys/src/instance/table.rs b/crates/wasmedge-sys/src/instance/table.rs index 4a8e46029..6ddc9a468 100644 --- a/crates/wasmedge-sys/src/instance/table.rs +++ b/crates/wasmedge-sys/src/instance/table.rs @@ -34,19 +34,6 @@ impl Table { /// # Error /// /// * If fail to create the table instance, then WasmEdgeError::Table(TableError::Create)(crate::error::TableError) is returned. - /// - /// # Example - /// - /// ``` - /// use wasmedge_sys::{TableType, Table}; - /// use wasmedge_types::RefType; - /// - /// // create a TableType instance - /// let ty = TableType::create(RefType::FuncRef, 10, Some(20)).expect("fail to create a TableType"); - /// - /// // create a Table instance - /// let table = Table::create(&ty).expect("fail to create a Table"); - /// ``` pub fn create(ty: wasmedge_types::TableType) -> WasmEdgeResult { let ty: TableType = ty.into(); let ctx = unsafe { ffi::WasmEdge_TableInstanceCreate(ty.inner.0) }; @@ -122,20 +109,6 @@ impl Table { /// Returns the capacity of the [Table]. /// - /// # Example - /// - /// ``` - /// use wasmedge_sys::{TableType, Table}; - /// use wasmedge_types::RefType; - /// - /// // create a TableType instance and a Table - /// let ty = TableType::create(RefType::FuncRef, 10, Some(20)).expect("fail to create a TableType"); - /// let table = Table::create(&ty).expect("fail to create a Table"); - /// - /// // check capacity - /// assert_eq!(table.capacity(), 10); - /// ``` - /// pub fn capacity(&self) -> usize { unsafe { ffi::WasmEdge_TableInstanceGetSize(self.inner.0) as usize } } @@ -269,20 +242,15 @@ pub(crate) struct InnerTableType(pub(crate) *mut ffi::WasmEdge_TableTypeContext) unsafe impl Send for InnerTableType {} unsafe impl Sync for InnerTableType {} -// #[cfg(test)] -#[cfg(ignore)] +#[cfg(test)] mod tests { use super::*; - use crate::{ - instance::function::{AsFunc, FuncTypeOwn}, - CallingFrame, Function, + use crate::{instance::function::AsFunc, CallingFrame, Function, Instance}; + use std::thread; + use wasmedge_types::{ + error::{CoreError, CoreExecutionError}, + RefType, ValType, }; - use std::{ - sync::{Arc, Mutex}, - thread, - }; - use wasmedge_macro::sys_host_function; - use wasmedge_types::{error::HostFuncError, NeverType, RefType, ValType}; #[test] #[allow(clippy::assertions_on_result_states)] @@ -292,7 +260,6 @@ mod tests { assert!(result.is_ok()); let ty = result.unwrap(); assert!(!ty.inner.0.is_null()); - assert!(!ty.registered); // check element type assert_eq!(ty.elem_ty(), RefType::FuncRef); @@ -305,12 +272,10 @@ mod tests { #[allow(clippy::assertions_on_result_states)] fn test_table() { // create a TableType instance - let result = TableType::create(RefType::FuncRef, 10, Some(20)); - assert!(result.is_ok()); - let ty = result.unwrap(); + let ty = wasmedge_types::TableType::new(RefType::FuncRef, 10, Some(20)); // create a Table instance - let result = Table::create(&ty); + let result = Table::create(ty); assert!(result.is_ok()); let mut table = result.unwrap(); @@ -321,12 +286,10 @@ mod tests { let result = table.ty(); assert!(result.is_ok()); let ty = result.unwrap(); - assert!(!ty.inner.0.is_null()); - assert!(ty.registered); // check limit and element type - assert_eq!(ty.min(), 10); - assert_eq!(ty.max(), Some(20)); + assert_eq!(ty.minimum(), 10); + assert_eq!(ty.maximum(), Some(20)); assert_eq!(ty.elem_ty(), RefType::FuncRef); // grow the capacity of table @@ -340,21 +303,19 @@ mod tests { #[allow(clippy::assertions_on_result_states)] fn test_table_data() { // create a FuncType - let result = FuncTypeOwn::create(vec![ValType::I32; 2], vec![ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); + let func_ty = wasmedge_types::FuncType::new(vec![ValType::I32; 2], vec![ValType::I32]); // create a host function - let result = Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0); + let mut host_data = (); + let result = + unsafe { Function::create_sync_func::<()>(&func_ty, real_add, &mut host_data, 0) }; assert!(result.is_ok()); let host_func = result.unwrap(); // create a TableType instance - let result = TableType::create(RefType::FuncRef, 10, Some(20)); - assert!(result.is_ok()); - let ty = result.unwrap(); + let ty = wasmedge_types::TableType::new(RefType::FuncRef, 10, Some(20)); // create a Table instance - let result = Table::create(&ty); + let result = Table::create(ty); assert!(result.is_ok()); let mut table = result.unwrap(); @@ -377,34 +338,30 @@ mod tests { let value = result.unwrap(); let result = value.func_ref(); assert!(result.is_some()); - let mut func_ref = result.unwrap(); + let func_ref = result.unwrap(); // get the function type by func_ref let result = func_ref.ty(); assert!(result.is_some()); let func_ty = result.unwrap(); - assert_eq!(func_ty.params_len(), 2); - let param_tys = func_ty.params_type_iter().collect::>(); - assert_eq!(param_tys, [ValType::I32, ValType::I32]); + assert_eq!(func_ty.args_len(), 2); + assert_eq!(func_ty.args(), &[ValType::I32, ValType::I32]); assert_eq!(func_ty.returns_len(), 1); - let return_tys = func_ty.returns_type_iter().collect::>(); - assert_eq!(return_tys, [ValType::I32]); + assert_eq!(func_ty.returns(), &[ValType::I32]); } #[test] fn test_table_send() { // create a TableType instance - let result = TableType::create(RefType::FuncRef, 10, Some(20)); - assert!(result.is_ok()); - let ty = result.unwrap(); + let ty = wasmedge_types::TableType::new(RefType::FuncRef, 10, Some(20)); // create a Table instance - let result = Table::create(&ty); + let result = Table::create(ty); assert!(result.is_ok()); let table = result.unwrap(); let handle = thread::spawn(move || { - assert!(!table.inner.lock().0.is_null()); + assert!(!table.inner.0.is_null()); // check capacity assert_eq!(table.capacity(), 10); @@ -413,12 +370,10 @@ mod tests { let result = table.ty(); assert!(result.is_ok()); let ty = result.unwrap(); - assert!(!ty.inner.0.is_null()); - assert!(ty.registered); // check limit and element type - assert_eq!(ty.min(), 10); - assert_eq!(ty.max(), Some(20)); + assert_eq!(ty.minimum(), 10); + assert_eq!(ty.maximum(), Some(20)); assert_eq!(ty.elem_ty(), RefType::FuncRef); }); @@ -428,84 +383,53 @@ mod tests { #[test] fn test_table_sync() { // create a TableType instance - let result = TableType::create(RefType::FuncRef, 10, Some(20)); - assert!(result.is_ok()); - let ty = result.unwrap(); + let ty = wasmedge_types::TableType::new(RefType::FuncRef, 10, Some(20)); // create a Table instance - let result = Table::create(&ty); - assert!(result.is_ok()); - let table = Arc::new(Mutex::new(result.unwrap())); - - let table_cloned = Arc::clone(&table); - let handle = thread::spawn(move || { - let result = table_cloned.lock(); - assert!(result.is_ok()); - let table = result.unwrap(); - - // check capacity - assert_eq!(table.capacity(), 10); - - // get type - let result = table.ty(); - assert!(result.is_ok()); - let ty = result.unwrap(); - assert!(!ty.inner.0.is_null()); - assert!(ty.registered); - - // check limit and element type - assert_eq!(ty.min(), 10); - assert_eq!(ty.max(), Some(20)); - assert_eq!(ty.elem_ty(), RefType::FuncRef); - }); + let result = Table::create(ty); - handle.join().unwrap(); - } - - #[test] - fn test_table_clone() { - // create a TableType instance - let result = TableType::create(RefType::FuncRef, 10, Some(20)); - assert!(result.is_ok()); - let ty = result.unwrap(); - - // create a Table instance - let result = Table::create(&ty); assert!(result.is_ok()); let table = result.unwrap(); - // check capacity - assert_eq!(table.capacity(), 10); - - let table_cloned = table.clone(); - assert_eq!(table_cloned.capacity(), table.capacity()); - - drop(table); - - assert_eq!(table_cloned.capacity(), 10); + let table = &table; + + std::thread::scope(move |s| { + let _ = s + .spawn(|| { + let result = table.ty(); + assert!(result.is_ok()); + let ty = result.unwrap(); + // check limit and element type + assert_eq!(ty.minimum(), 10); + assert_eq!(ty.maximum(), Some(20)); + assert_eq!(ty.elem_ty(), RefType::FuncRef); + }) + .join(); + }); } - #[sys_host_function] fn real_add( - _frame: CallingFrame, + _data: &mut (), + _inst: &mut Instance, + _frame: &mut CallingFrame, input: Vec, - ) -> Result, HostFuncError> { + ) -> Result, CoreError> { println!("Rust: Entering Rust function real_add"); if input.len() != 2 { - return Err(HostFuncError::User(1)); + return Err(CoreError::Execution(CoreExecutionError::FuncTypeMismatch)); } let a = if input[0].ty() == ValType::I32 { input[0].to_i32() } else { - return Err(HostFuncError::User(2)); + return Err(CoreError::Execution(CoreExecutionError::FuncTypeMismatch)); }; let b = if input[1].ty() == ValType::I32 { input[0].to_i32() } else { - return Err(HostFuncError::User(3)); + return Err(CoreError::Execution(CoreExecutionError::FuncTypeMismatch)); }; let c = a + b; diff --git a/crates/wasmedge-sys/src/store.rs b/crates/wasmedge-sys/src/store.rs index 4bf58a0af..884f3f6a4 100644 --- a/crates/wasmedge-sys/src/store.rs +++ b/crates/wasmedge-sys/src/store.rs @@ -120,250 +120,3 @@ impl Drop for Store { pub(crate) struct InnerStore(pub(crate) *mut ffi::WasmEdge_StoreContext); unsafe impl Send for InnerStore {} unsafe impl Sync for InnerStore {} - -// #[cfg(test)] -#[cfg(ignore)] -mod tests { - use super::Store; - use crate::{ - instance::{Function, Global, GlobalType, MemType, Memory, Table, TableType}, - types::WasmValue, - AsImport, CallingFrame, Config, Engine, Executor, FuncType, ImportModule, Loader, - Validator, - }; - use std::{ - sync::{Arc, Mutex}, - thread, - }; - use wasmedge_macro::sys_host_function; - use wasmedge_types::{error::HostFuncError, Mutability, NeverType, RefType, ValType}; - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_store_basic() { - let module_name = "extern_module"; - - let result = Store::create(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - assert!(!store.inner.0.is_null()); - assert!(!store.registered); - - // check the length of registered module list in store before instantiation - assert_eq!(store.module_len(), 0); - assert!(store.module_names().is_none()); - - // create ImportObject instance - let result = ImportModule::::create(module_name, None); - assert!(result.is_ok()); - let mut import = result.unwrap(); - - // add host function - let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - let result = Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0); - assert!(result.is_ok()); - let host_func = result.unwrap(); - import.add_func("add", host_func); - - // add table - let result = TableType::create(RefType::FuncRef, 0, Some(u32::MAX)); - assert!(result.is_ok()); - let ty = result.unwrap(); - let result = Table::create(&ty); - assert!(result.is_ok()); - let table = result.unwrap(); - import.add_table("table", table); - - // add memory - let memory = { - let result = MemType::create(10, Some(20), false); - assert!(result.is_ok()); - let mem_ty = result.unwrap(); - let result = Memory::create(&mem_ty); - assert!(result.is_ok()); - result.unwrap() - }; - import.add_memory("mem", memory); - - // add globals - let result = GlobalType::create(ValType::F32, Mutability::Const); - assert!(result.is_ok()); - let ty = result.unwrap(); - let result = Global::create(&ty, WasmValue::from_f32(3.5)); - assert!(result.is_ok()); - let global = result.unwrap(); - import.add_global("global", global); - - let result = Config::create(); - assert!(result.is_ok()); - let config = result.unwrap(); - let result = Executor::create(Some(&config), None); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - let result = executor.register_import_module(&mut store, &import); - assert!(result.is_ok()); - - // check the module list after instantiation - assert_eq!(store.module_len(), 1); - assert!(store.module_names().is_some()); - assert_eq!(store.module_names().unwrap()[0], module_name); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_store_send() { - let result = Store::create(); - assert!(result.is_ok()); - let store = result.unwrap(); - assert!(!store.inner.0.is_null()); - assert!(!store.registered); - - let handle = thread::spawn(move || { - let s = store; - assert!(!s.inner.0.is_null()); - }); - - handle.join().unwrap(); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_store_sync() { - let result = Store::create(); - assert!(result.is_ok()); - let store = Arc::new(Mutex::new(result.unwrap())); - - let store_cloned = Arc::clone(&store); - let handle = thread::spawn(move || { - // create ImportObject instance - let result = ImportModule::::create("extern_module", None); - assert!(result.is_ok()); - let mut import = result.unwrap(); - - // add host function - let result = FuncType::create(vec![ValType::I32; 2], vec![ValType::I32]); - assert!(result.is_ok()); - let func_ty = result.unwrap(); - let result = - Function::create_sync_func::(&func_ty, Box::new(real_add), None, 0); - assert!(result.is_ok()); - let host_func = result.unwrap(); - import.add_func("add", host_func); - - // create an Executor - let result = Config::create(); - assert!(result.is_ok()); - let config = result.unwrap(); - let result = Executor::create(Some(&config), None); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - let result = store_cloned.lock(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - let result = executor.register_import_module(&mut store, &import); - assert!(result.is_ok()); - - // get module instance - let result = store.module("extern_module"); - assert!(result.is_ok()); - let instance = result.unwrap(); - - // get function instance - let result = instance.get_func("add"); - assert!(result.is_ok()); - let add = result.unwrap(); - - // run the function - let result = - executor.run_func(&add, vec![WasmValue::from_i32(12), WasmValue::from_i32(21)]); - assert!(result.is_ok()); - let returns = result.unwrap(); - assert_eq!(returns[0].to_i32(), 33); - }); - - handle.join().unwrap(); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_store_named_module() -> Result<(), Box> { - // create a Config context - let result = Config::create(); - assert!(result.is_ok()); - let mut config = result.unwrap(); - config.bulk_memory_operations(true); - assert!(config.bulk_memory_operations_enabled()); - - // create an executor with the given config - let mut executor = Executor::create(Some(&config), None)?; - - // create a store - let mut store = Store::create()?; - - // register a wasm module from a wasm file - let path = std::env::current_dir() - .unwrap() - .ancestors() - .nth(2) - .unwrap() - .join("examples/wasmedge-sys/data/fibonacci.wat"); - let module = Loader::create(Some(&config))?.from_file(path)?; - Validator::create(Some(&config))?.validate(&module)?; - let instance = executor.register_named_module(&mut store, &module, "extern")?; - - // check the name of the module - assert!(instance.name().is_some()); - assert_eq!(instance.name().unwrap(), "extern"); - - // get the exported function named "fib" - let result = instance.get_func("fib"); - assert!(result.is_ok()); - let func = result.unwrap(); - - // check the type of the function - let result = func.ty(); - assert!(result.is_ok()); - let ty = result.unwrap(); - - // check the parameter types - let param_types = ty.params_type_iter().collect::>(); - assert_eq!(param_types, [ValType::I32]); - - // check the return types - let return_types = ty.returns_type_iter().collect::>(); - assert_eq!(return_types, [ValType::I32]); - - Ok(()) - } - - #[sys_host_function] - fn real_add( - _frame: CallingFrame, - inputs: Vec, - ) -> Result, HostFuncError> { - if inputs.len() != 2 { - return Err(HostFuncError::User(1)); - } - - let a = if inputs[0].ty() == ValType::I32 { - inputs[0].to_i32() - } else { - return Err(HostFuncError::User(2)); - }; - - let b = if inputs[1].ty() == ValType::I32 { - inputs[1].to_i32() - } else { - return Err(HostFuncError::User(3)); - }; - - let c = a + b; - - Ok(vec![WasmValue::from_i32(c)]) - } -} diff --git a/src/async/vm.rs b/src/async/vm.rs index 979efac63..462552f14 100644 --- a/src/async/vm.rs +++ b/src/async/vm.rs @@ -276,29 +276,21 @@ impl<'inst, T: ?Sized + Send + AsyncInst> Vm<'inst, T> { } } -// #[cfg(test)] -#[cfg(ignore)] +#[cfg(test)] mod tests { + use std::collections::HashMap; + + use wasmedge_types::wat2wasm; + use super::*; - use crate::{ - config::{ - CommonConfigOptions, ConfigBuilder, HostRegistrationConfigOptions, - StatisticsConfigOptions, - }, - error::HostFuncError, - io::WasmVal, - params, - types::Val, - wat2wasm, CallingFrame, Global, GlobalType, ImportObjectBuilder, Memory, MemoryType, - Mutability, NeverType, RefType, Table, TableType, ValType, WasmValue, - }; + use crate::{io::WasmVal, params}; - #[test] - fn test_vm_run_func_from_file() { + #[tokio::test] + async fn test_vm_run_func_from_file() { // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let mut vm = result.unwrap(); + let mut vm = Vm::new( + Store::new(None, HashMap::::new()).unwrap(), + ); // register a wasm module from a specified wasm file let file = std::env::current_dir() @@ -306,19 +298,21 @@ mod tests { .join("examples/wasmedge-sys/data/fibonacci.wat"); // run `fib` function from the wasm file - let result = vm.run_func_from_file(file, "fib", params!(10)); + let fib_module = Module::from_file(None, file).unwrap(); + vm.register_module(None, fib_module).unwrap(); + let result = vm.run_func(None, "fib", params!(10)).await; assert!(result.is_ok()); let returns = result.unwrap(); assert_eq!(returns.len(), 1); assert_eq!(returns[0].to_i32(), 89); } - #[test] - fn test_vm_run_func_from_bytes() { + #[tokio::test] + async fn test_vm_run_func_from_bytes() { // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let mut vm = result.unwrap(); + let mut vm = Vm::new( + Store::new(None, HashMap::::new()).unwrap(), + ); // register a wasm module from the given in-memory wasm bytes // load wasm module @@ -359,74 +353,21 @@ mod tests { let wasm_bytes = result.unwrap(); // run `fib` function from the wasm bytes - let result = vm.run_func_from_bytes(&wasm_bytes, "fib", params!(10)); + let fib_module = Module::from_bytes(None, wasm_bytes).unwrap(); + vm.register_module(None, fib_module).unwrap(); + let result = vm.run_func(None, "fib", params!(10)).await; assert!(result.is_ok()); let returns = result.unwrap(); assert_eq!(returns.len(), 1); assert_eq!(returns[0].to_i32(), 89); } - #[test] - fn test_vm_run_func_from_module() { + #[tokio::test] + async fn test_vm_run_func_in_named_module_instance() { // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let mut vm = result.unwrap(); - - // load wasm module - let result = wat2wasm( - br#"(module - (export "fib" (func $fib)) - (func $fib (param $n i32) (result i32) - (if - (i32.lt_s - (get_local $n) - (i32.const 2) - ) - (return - (i32.const 1) - ) - ) - (return - (i32.add - (call $fib - (i32.sub - (get_local $n) - (i32.const 2) - ) - ) - (call $fib - (i32.sub - (get_local $n) - (i32.const 1) - ) - ) - ) - ) - ) - ) - "#, + let mut vm = Vm::new( + Store::new(None, HashMap::::new()).unwrap(), ); - assert!(result.is_ok()); - let wasm_bytes = result.unwrap(); - let result = Module::from_bytes(None, wasm_bytes); - assert!(result.is_ok()); - let module = result.unwrap(); - - // run `fib` function from the compiled module - let result = vm.run_func_from_module(module, "fib", params!(10)); - assert!(result.is_ok()); - let returns = result.unwrap(); - assert_eq!(returns.len(), 1); - assert_eq!(returns[0].to_i32(), 89); - } - - #[test] - fn test_vm_run_func_in_named_module_instance() { - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let vm = result.unwrap(); // register a wasm module from the given in-memory wasm bytes // load wasm module @@ -465,474 +406,13 @@ mod tests { ); assert!(result.is_ok()); let wasm_bytes = result.unwrap(); - let result = vm.register_module_from_bytes("extern", wasm_bytes); - assert!(result.is_ok()); - let vm = result.unwrap(); - + let fib_module = Module::from_bytes(None, wasm_bytes).unwrap(); + vm.register_module(Some("extern"), fib_module).unwrap(); // run `fib` function in the named module instance - let result = vm.run_func(Some("extern"), "fib", params!(10)); - assert!(result.is_ok()); - let returns = result.unwrap(); - assert_eq!(returns.len(), 1); - assert_eq!(returns[0].to_i32(), 89); - } - - #[test] - fn test_vm_run_func_in_active_module_instance() { - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // load wasm module - let result = wat2wasm( - br#"(module - (export "fib" (func $fib)) - (func $fib (param $n i32) (result i32) - (if - (i32.lt_s - (get_local $n) - (i32.const 2) - ) - (return - (i32.const 1) - ) - ) - (return - (i32.add - (call $fib - (i32.sub - (get_local $n) - (i32.const 2) - ) - ) - (call $fib - (i32.sub - (get_local $n) - (i32.const 1) - ) - ) - ) - ) - ) - ) - "#, - ); - assert!(result.is_ok()); - let wasm_bytes = result.unwrap(); - let result = Module::from_bytes(None, wasm_bytes); - assert!(result.is_ok()); - let module = result.unwrap(); - - // register the wasm module into vm - let result = vm.register_module(None, module); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // run `fib` function in the active module instance - let result = vm.run_func(None, "fib", params!(10)); + let result = vm.run_func(Some("extern"), "fib", params!(10)).await; assert!(result.is_ok()); let returns = result.unwrap(); assert_eq!(returns.len(), 1); assert_eq!(returns[0].to_i32(), 89); } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_vm_create() { - { - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - } - - { - // create a Config - let result = ConfigBuilder::new(CommonConfigOptions::default()).build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - // create a Vm context - let result = VmBuilder::new().with_config(config).build(); - assert!(result.is_ok()); - let _vm = result.unwrap(); - } - } - - #[test] - fn test_vm_wasi_module() { - let host_reg_options = HostRegistrationConfigOptions::default().wasi(true); - let result = ConfigBuilder::new(CommonConfigOptions::default()) - .with_host_registration_config(host_reg_options) - .build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - // create a vm with the config settings - let result = VmBuilder::new().with_config(config).build(); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // get the wasi module - let result = vm.wasi_module(); - assert!(result.is_some()); - let wasi_instance = result.unwrap(); - - assert_eq!(wasi_instance.name(), "wasi_snapshot_preview1"); - } - - #[test] - fn test_vm_statistics() { - // set config options related to Statistics - let stat_config_options = StatisticsConfigOptions::new() - .measure_cost(true) - .measure_time(true) - .count_instructions(true); - // create a Config - let result = ConfigBuilder::new(CommonConfigOptions::default()) - .with_statistics_config(stat_config_options) - .build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - // create a Vm context - let result = VmBuilder::new().with_config(config).build(); - assert!(result.is_ok()); - let _vm = result.unwrap(); - - // get the statistics - // let _stat = vm.statistics_mut(); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_vm_register_module_from_file() { - { - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // register a wasm module from a specified wasm file - let file = std::env::current_dir() - .unwrap() - .join("examples/wasmedge-sys/data/fibonacci.wat"); - let result = vm.register_module_from_file("extern", file); - assert!(result.is_ok()); - let vm = result.unwrap(); - - assert!(vm.named_instance_count() >= 1); - assert!(vm.instance_names().iter().any(|x| x == "extern")); - } - - { - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // register a wasm module from a specified wasm file - let file = std::env::current_dir() - .unwrap() - .join("examples/wasmedge-sys/data/fibonacci.wat"); - let result = vm.register_module_from_file("extern", file); - assert!(result.is_ok()); - let vm = result.unwrap(); - - assert!(vm.named_instance_count() >= 1); - assert!(vm.instance_names().iter().any(|x| x == "extern")); - } - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_vm_register_module_from_bytes() { - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // register a wasm module from the given in-memory wasm bytes - // load wasm module - let result = wat2wasm( - br#"(module - (export "fib" (func $fib)) - (func $fib (param $n i32) (result i32) - (if - (i32.lt_s - (get_local $n) - (i32.const 2) - ) - (return - (i32.const 1) - ) - ) - (return - (i32.add - (call $fib - (i32.sub - (get_local $n) - (i32.const 2) - ) - ) - (call $fib - (i32.sub - (get_local $n) - (i32.const 1) - ) - ) - ) - ) - ) - ) - "#, - ); - assert!(result.is_ok()); - let wasm_bytes = result.unwrap(); - let result = vm.register_module_from_bytes("extern", wasm_bytes); - assert!(result.is_ok()); - let vm = result.unwrap(); - - assert!(vm.named_instance_count() >= 1); - assert!(vm.instance_names().iter().any(|x| x == "extern")); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_vm_register_import_module() { - // create a Const global instance - let result = Global::new( - GlobalType::new(ValType::F32, Mutability::Const), - Val::F32(3.5), - ); - assert!(result.is_ok()); - let global_const = result.unwrap(); - - // create a memory instance - let result = MemoryType::new(10, None, false); - assert!(result.is_ok()); - let memory_type = result.unwrap(); - let result = Memory::new(memory_type); - assert!(result.is_ok()); - let memory = result.unwrap(); - - // create a table instance - let result = Table::new(TableType::new(RefType::FuncRef, 5, None)); - assert!(result.is_ok()); - let table = result.unwrap(); - - // create an ImportModule instance - let result = ImportObjectBuilder::new() - .with_func::<(i32, i32), i32, NeverType>("add", real_add, None) - .expect("failed to add host function") - .with_global("global", global_const) - .with_memory("mem", memory) - .with_table("table", table) - .build::("extern-module", None); - assert!(result.is_ok()); - let import = result.unwrap(); - - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let mut vm = result.unwrap(); - - // register an import module into vm - let result = vm.register_import_module(&import); - assert!(result.is_ok()); - - assert!(vm.named_instance_count() >= 1); - assert!(vm.instance_names().iter().any(|x| x == "extern-module")); - - // get active module instance - let result = vm.named_module("extern-module"); - assert!(result.is_ok()); - let instance = result.unwrap(); - assert!(instance.name().is_some()); - assert_eq!(instance.name().unwrap(), "extern-module"); - - let result = instance.global("global"); - assert!(result.is_ok()); - let global = result.unwrap(); - let ty = global.ty(); - assert_eq!(*ty, GlobalType::new(ValType::F32, Mutability::Const)); - } - - #[test] - fn test_vm_register_named_module() { - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // load wasm module - let result = wat2wasm( - br#"(module - (export "fib" (func $fib)) - (func $fib (param $n i32) (result i32) - (if - (i32.lt_s - (get_local $n) - (i32.const 2) - ) - (return - (i32.const 1) - ) - ) - (return - (i32.add - (call $fib - (i32.sub - (get_local $n) - (i32.const 2) - ) - ) - (call $fib - (i32.sub - (get_local $n) - (i32.const 1) - ) - ) - ) - ) - ) - ) - "#, - ); - assert!(result.is_ok()); - let wasm_bytes = result.unwrap(); - let result = Module::from_bytes(None, wasm_bytes); - assert!(result.is_ok()); - let module = result.unwrap(); - - // register the wasm module into vm - let result = vm.register_module(Some("extern"), module); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // check the exported functions in the "extern" module - assert!(vm.named_instance_count() >= 1); - let result = vm.named_module("extern"); - assert!(result.is_ok()); - let instance = result.unwrap(); - - assert_eq!(instance.func_count(), 1); - let result = instance.func_names(); - assert!(result.is_some()); - let func_names = result.unwrap(); - assert_eq!(func_names, ["fib"]); - - // get host_func - let result = instance.func("fib"); - assert!(result.is_ok()); - let fib = result.unwrap(); - - // check the type of host_func - let ty = fib.ty(); - assert!(ty.args().is_some()); - assert_eq!(ty.args().unwrap(), [ValType::I32]); - assert!(ty.returns().is_some()); - assert_eq!(ty.returns().unwrap(), [ValType::I32]); - } - - #[test] - fn test_vm_register_active_module() { - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // load wasm module - let result = wat2wasm( - br#"(module - (export "fib" (func $fib)) - (func $fib (param $n i32) (result i32) - (if - (i32.lt_s - (get_local $n) - (i32.const 2) - ) - (return - (i32.const 1) - ) - ) - (return - (i32.add - (call $fib - (i32.sub - (get_local $n) - (i32.const 2) - ) - ) - (call $fib - (i32.sub - (get_local $n) - (i32.const 1) - ) - ) - ) - ) - ) - ) - "#, - ); - assert!(result.is_ok()); - let wasm_bytes = result.unwrap(); - let result = Module::from_bytes(None, wasm_bytes); - assert!(result.is_ok()); - let module = result.unwrap(); - - // register the wasm module into vm - let result = vm.register_module(None, module); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // check the exported functions in the "extern" module - let result = vm.active_module(); - assert!(result.is_ok()); - let instance = result.unwrap(); - - assert_eq!(instance.func_count(), 1); - let result = instance.func_names(); - assert!(result.is_some()); - let func_names = result.unwrap(); - assert_eq!(func_names, ["fib"]); - - // get host_func - let result = instance.func("fib"); - assert!(result.is_ok()); - let fib = result.unwrap(); - - // check the type of host_func - let ty = fib.ty(); - assert!(ty.args().is_some()); - assert_eq!(ty.args().unwrap(), [ValType::I32]); - assert!(ty.returns().is_some()); - assert_eq!(ty.returns().unwrap(), [ValType::I32]); - } - - fn real_add( - _frame: CallingFrame, - inputs: Vec, - _data: *mut std::os::raw::c_void, - ) -> std::result::Result, HostFuncError> { - if inputs.len() != 2 { - return Err(HostFuncError::User(1)); - } - - let a = if inputs[0].ty() == ValType::I32 { - inputs[0].to_i32() - } else { - return Err(HostFuncError::User(2)); - }; - - let b = if inputs[1].ty() == ValType::I32 { - inputs[1].to_i32() - } else { - return Err(HostFuncError::User(3)); - }; - - let c = a + b; - - Ok(vec![WasmValue::from_i32(c)]) - } } diff --git a/src/config.rs b/src/config.rs index 958d41d63..9c151254d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -117,7 +117,7 @@ impl ConfigBuilder { /// /// ```rust /// -/// use wasmedge_sdk::{config::{Config, ConfigBuilder, CommonConfigOptions, StatisticsConfigOptions, RuntimeConfigOptions, HostRegistrationConfigOptions}}; +/// use wasmedge_sdk::{config::{Config, ConfigBuilder, CommonConfigOptions, StatisticsConfigOptions, RuntimeConfigOptions}}; /// use wasmedge_types::{CompilerOutputFormat, CompilerOptimizationLevel}; /// /// let common_options = CommonConfigOptions::default() @@ -136,13 +136,10 @@ impl ConfigBuilder { /// /// let runtime_options = RuntimeConfigOptions::default().max_memory_pages(1024); /// -/// let host_options = HostRegistrationConfigOptions::default() -/// .wasi(true); /// /// let result = ConfigBuilder::new(common_options) /// .with_statistics_config(stat_options) /// .with_runtime_config(runtime_options) -/// .with_host_registration_config(host_options) /// .build(); /// assert!(result.is_ok()); /// let config = result.unwrap(); @@ -754,13 +751,10 @@ mod tests { let runtime_options = RuntimeConfigOptions::default().max_memory_pages(1024); - let host_options = HostRegistrationConfigOptions::default().wasi(true); - let result = ConfigBuilder::new(common_options) .with_statistics_config(stat_options) .with_compiler_config(compiler_options) .with_runtime_config(runtime_options) - .with_host_registration_config(host_options) .build(); assert!(result.is_ok()); let config = result.unwrap(); @@ -790,8 +784,6 @@ mod tests { // check runtime config options assert_eq!(config.max_memory_pages(), 1024); - - assert!(config.wasi_enabled()); } #[test] @@ -803,13 +795,11 @@ mod tests { CompilerConfigOptions::default().optimization_level(CompilerOptimizationLevel::O0); let stat_config = StatisticsConfigOptions::default().measure_time(false); let runtime_config = RuntimeConfigOptions::default().max_memory_pages(1024); - let host_config = HostRegistrationConfigOptions::default().wasi(true); let result = ConfigBuilder::new(common_config) .with_statistics_config(stat_config) .with_compiler_config(compiler_config) .with_runtime_config(runtime_config) - .with_host_registration_config(host_config) .build(); assert!(result.is_ok()); let config = result.unwrap(); @@ -818,7 +808,6 @@ mod tests { assert_eq!(config.optimization_level(), CompilerOptimizationLevel::O0); assert!(!config.time_measuring_enabled()); assert_eq!(config.max_memory_pages(), 1024); - assert!(config.wasi_enabled()); // make a copy let config_copied = config.clone(); @@ -830,6 +819,5 @@ mod tests { ); assert!(!config.time_measuring_enabled()); assert_eq!(config_copied.max_memory_pages(), 1024); - assert!(config_copied.wasi_enabled()); } } diff --git a/src/import.rs b/src/import.rs index 84c313c3e..25c2d6dc4 100644 --- a/src/import.rs +++ b/src/import.rs @@ -140,722 +140,3 @@ impl ImportObjectBuilder { /// /// An [ImportObject] instance is created with [ImportObjectBuilder](crate::ImportObjectBuilder). pub type ImportObject = sys::ImportModule; - -// #[cfg(test)] -#[cfg(ignore)] -mod tests { - use super::*; - #[cfg(not(feature = "async"))] - use crate::VmBuilder; - use crate::{ - config::{CommonConfigOptions, ConfigBuilder}, - error::{GlobalError, HostFuncError, WasmEdgeError}, - params, - types::Val, - CallingFrame, Executor, Global, GlobalType, Memory, MemoryType, Mutability, NeverType, - RefType, Statistics, Store, Table, TableType, ValType, WasmVal, WasmValue, - }; - use std::{ - sync::{Arc, Mutex}, - thread, - }; - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_import_builder() { - let result = ImportObjectBuilder::new().build::("extern", None); - assert!(result.is_ok()); - let import = result.unwrap(); - assert_eq!(import.name(), "extern"); - } - - #[test] - #[cfg(not(feature = "async"))] - #[allow(clippy::assertions_on_result_states)] - fn test_import_builder_with_data() { - // define host data - #[derive(Clone, Debug)] - struct Circle { - radius: i32, - } - - let circle = Circle { radius: 10 }; - - let result = ImportObjectBuilder::new().build("extern", Some(Box::new(circle))); - assert!(result.is_ok()); - - let import = result.unwrap(); - assert_eq!(import.name(), "extern"); - - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let mut vm = result.unwrap(); - - // register an import module into vm - let result = vm.register_import_module(&import); - assert!(result.is_ok()); - - // get active module instance - let result = vm.named_module_mut("extern"); - assert!(result.is_ok()); - let instance = result.unwrap(); - - let result = instance.host_data::(); - assert!(result.is_some()); - let host_data = result.unwrap(); - assert_eq!(host_data.radius, 10); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_import_add_func() { - fn real_add( - _frame: CallingFrame, - inputs: Vec, - _data: *mut std::os::raw::c_void, - ) -> std::result::Result, HostFuncError> { - if inputs.len() != 2 { - return Err(HostFuncError::User(1)); - } - - let a = if inputs[0].ty() == ValType::I32 { - inputs[0].to_i32() - } else { - return Err(HostFuncError::User(2)); - }; - - let b = if inputs[1].ty() == ValType::I32 { - inputs[1].to_i32() - } else { - return Err(HostFuncError::User(3)); - }; - - let c = a + b; - - Ok(vec![WasmValue::from_i32(c)]) - } - - // create an import object - let result = ImportObjectBuilder::new() - .with_func::<(i32, i32), i32, NeverType>("add", real_add, None) - .expect("failed to add host func") - .build::("extern", None); - assert!(result.is_ok()); - let import = result.unwrap(); - - // create an executor - let result = ConfigBuilder::new(CommonConfigOptions::default()).build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - let result = Statistics::new(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - - let result = Executor::new(Some(&config), Some(&mut stat)); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - // create a store - let result = Store::new(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - let result = store.register_import_module(&mut executor, &import); - assert!(result.is_ok()); - - // get the instance of the ImportObject module - let result = store.named_instance("extern"); - assert!(result.is_ok()); - let instance = result.unwrap(); - - // get the exported host function - let result = instance.func("add"); - assert!(result.is_ok()); - let host_func = result.unwrap(); - - // check the signature of the host function - let func_ty = host_func.ty(); - assert!(func_ty.args().is_some()); - assert_eq!(func_ty.args().unwrap(), [ValType::I32; 2]); - assert!(func_ty.returns().is_some()); - assert_eq!(func_ty.returns().unwrap(), [ValType::I32]); - - let returns = host_func.run(&mut executor, params![1, 2]).unwrap(); - assert_eq!(returns[0].to_i32(), 3); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_import_add_memory() { - // create a memory - let result = MemoryType::new(10, Some(20), false); - assert!(result.is_ok()); - let memory_type = result.unwrap(); - let result = Memory::new(memory_type); - assert!(result.is_ok()); - let memory = result.unwrap(); - - // create an import object - let result = ImportObjectBuilder::new() - .with_memory("memory", memory) - .build::("extern", None); - assert!(result.is_ok()); - let import = result.unwrap(); - - // create an executor - let result = ConfigBuilder::new(CommonConfigOptions::default()).build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - let result = Statistics::new(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - - let result = Executor::new(Some(&config), Some(&mut stat)); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - // create a store - let result = Store::new(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - let result = store.named_instance("extern"); - assert!(result.is_err()); - - let result = store.register_import_module(&mut executor, &import); - assert!(result.is_ok()); - - let result = store.named_instance("extern"); - assert!(result.is_ok()); - let instance = result.unwrap(); - - // get the exported memory - let result = instance.memory("memory"); - assert!(result.is_ok()); - let mut memory = result.unwrap(); - - // check memory - assert!(memory.name().is_some()); - assert_eq!(memory.name().unwrap(), "memory"); - assert_eq!(memory.mod_name(), Some("extern")); - assert_eq!(memory.page(), 10); - let ty = memory.ty(); - assert_eq!(ty.minimum(), 10); - assert_eq!(ty.maximum(), Some(20)); - - // grow memory - let result = memory.grow(5); - assert!(result.is_ok()); - assert_eq!(memory.page(), 15); - - // get memory from instance again - let result = instance.memory("memory"); - assert!(result.is_ok()); - let memory = result.unwrap(); - assert_eq!(memory.page(), 15); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_import_add_global() { - // create a Const global variable - let result = Global::new( - GlobalType::new(ValType::I32, Mutability::Const), - Val::I32(1314), - ); - assert!(result.is_ok()); - let global_const = result.unwrap(); - - // create a Var global variable - let result = Global::new( - GlobalType::new(ValType::F32, Mutability::Var), - Val::F32(13.14), - ); - assert!(result.is_ok()); - let global_var = result.unwrap(); - - // create an import object - let result = ImportObjectBuilder::new() - .with_global("const-global", global_const) - .with_global("var-global", global_var) - .build::("extern", None); - assert!(result.is_ok()); - let import = result.unwrap(); - - // create an executor - let result = ConfigBuilder::new(CommonConfigOptions::default()).build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - let result = Statistics::new(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - - let result = Executor::new(Some(&config), Some(&mut stat)); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - // create a store - let result = Store::new(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - let result = store.register_import_module(&mut executor, &import); - assert!(result.is_ok()); - - let result = store.named_instance("extern"); - assert!(result.is_ok()); - let instance = result.unwrap(); - - // get the Const global from the store of vm - let result = instance.global("const-global"); - assert!(result.is_ok()); - let mut const_global = result.unwrap(); - - // check global - assert!(const_global.name().is_some()); - assert_eq!(const_global.name().unwrap(), "const-global"); - assert!(const_global.mod_name().is_some()); - assert_eq!(const_global.mod_name().unwrap(), "extern"); - let ty = const_global.ty(); - assert_eq!(ty.value_ty(), ValType::I32); - assert_eq!(ty.mutability(), Mutability::Const); - - // get value of global - if let Val::I32(value) = const_global.get_value() { - assert_eq!(value, 1314); - } - - // set a new value - let result = const_global.set_value(Val::I32(314)); - assert!(result.is_err()); - assert_eq!( - result.unwrap_err(), - Box::new(WasmEdgeError::Global(GlobalError::ModifyConst)) - ); - - // get the Var global from the store of vm - let result = store.named_instance("extern"); - assert!(result.is_ok()); - let instance = result.unwrap(); - - // get the Var global from the store of vm - let result = instance.global("var-global"); - assert!(result.is_ok()); - let mut var_global = result.unwrap(); - - // check global - assert!(var_global.name().is_some()); - assert_eq!(var_global.name().unwrap(), "var-global"); - assert!(var_global.mod_name().is_some()); - assert_eq!(var_global.mod_name().unwrap(), "extern"); - let ty = var_global.ty(); - assert_eq!(ty.value_ty(), ValType::F32); - assert_eq!(ty.mutability(), Mutability::Var); - - // get the value of var_global - if let Val::F32(value) = var_global.get_value() { - assert_eq!(value, 13.14); - } - - // set a new value - let result = var_global.set_value(Val::F32(1.314)); - assert!(result.is_ok()); - - // get the value of var_global again - let result = instance.global("var-global"); - assert!(result.is_ok()); - let var_global = result.unwrap(); - if let Val::F32(value) = var_global.get_value() { - assert_eq!(value, 1.314); - } - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_import_add_table() { - // create a wasm table instance - let result = Table::new(TableType::new(RefType::FuncRef, 10, Some(20))); - assert!(result.is_ok()); - let table = result.unwrap(); - - // create an import object - let result = ImportObjectBuilder::new() - .with_func::<(i32, i32), i32, NeverType>("add", real_add, None) - .expect("failed to add host func") - .with_table("table", table) - .build::("extern", None); - assert!(result.is_ok()); - let import = result.unwrap(); - - // create an executor - let result = ConfigBuilder::new(CommonConfigOptions::default()).build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - let result = Statistics::new(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - - let result = Executor::new(Some(&config), Some(&mut stat)); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - // create a store - let result = Store::new(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - let result = store.register_import_module(&mut executor, &import); - assert!(result.is_ok()); - - let result = store.named_instance("extern"); - assert!(result.is_ok()); - let instance = result.unwrap(); - - // get the exported host function - let result = instance.func("add"); - assert!(result.is_ok()); - let host_func = result.unwrap(); - - // get the exported table - let result = instance.table("table"); - assert!(result.is_ok()); - let mut table = result.unwrap(); - - // check table - assert!(table.name().is_some()); - assert_eq!(table.name().unwrap(), "table"); - assert!(table.mod_name().is_some()); - assert_eq!(table.mod_name().unwrap(), "extern"); - assert_eq!(table.size(), 10); - let ty = table.ty(); - assert_eq!(ty.elem_ty(), RefType::FuncRef); - assert_eq!(ty.minimum(), 10); - assert_eq!(ty.maximum(), Some(20)); - - // get value from table[0] - let result = table.get(0); - assert!(result.is_ok()); - if let Val::FuncRef(func_ref) = result.unwrap() { - assert!(func_ref.is_none()); - } - - // set value to table[0] - let func_ref = host_func.as_ref(); - let result = table.set(0, Val::FuncRef(Some(func_ref))); - assert!(result.is_ok()); - // get the value in table[0] - let result = table.get(0); - assert!(result.is_ok()); - if let Val::FuncRef(func_ref) = result.unwrap() { - assert!(func_ref.is_some()); - let func_ref = func_ref.unwrap(); - // check the signature of the host function - let func_ty = func_ref.ty(); - assert!(func_ty.args().is_some()); - assert_eq!(func_ty.args().unwrap(), [ValType::I32; 2]); - assert!(func_ty.returns().is_some()); - assert_eq!(func_ty.returns().unwrap(), [ValType::I32]); - } - - let result = store.named_instance("extern"); - assert!(result.is_ok()); - let instance = result.unwrap(); - - let result = instance.table("table"); - assert!(result.is_ok()); - let table = result.unwrap(); - - // get the value in table[0] - let result = table.get(0); - assert!(result.is_ok()); - if let Val::FuncRef(func_ref) = result.unwrap() { - assert!(func_ref.is_some()); - let func_ref = func_ref.unwrap(); - // check the signature of the host function - let func_ty = func_ref.ty(); - assert!(func_ty.args().is_some()); - assert_eq!(func_ty.args().unwrap(), [ValType::I32; 2]); - assert!(func_ty.returns().is_some()); - assert_eq!(func_ty.returns().unwrap(), [ValType::I32]); - } - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_import_send() { - // create a Const global instance - let result = Global::new( - GlobalType::new(ValType::F32, Mutability::Const), - Val::F32(3.5), - ); - assert!(result.is_ok()); - let global_const = result.unwrap(); - - // create a memory instance - let result = MemoryType::new(10, Some(20), false); - assert!(result.is_ok()); - let memory_type = result.unwrap(); - let result = Memory::new(memory_type); - assert!(result.is_ok()); - let memory = result.unwrap(); - - // create a table instance - let result = Table::new(TableType::new(RefType::FuncRef, 10, Some(20))); - assert!(result.is_ok()); - let table = result.unwrap(); - - // create an ImportModule instance - let result = ImportObjectBuilder::new() - .with_func::<(i32, i32), i32, NeverType>("add", real_add, None) - .expect("failed to add host function") - .with_global("global", global_const) - .with_memory("memory", memory) - .with_table("table", table) - .build::("extern-module-send", None); - assert!(result.is_ok()); - let import = result.unwrap(); - - let handle = thread::spawn(move || { - // create an executor - let result = ConfigBuilder::new(CommonConfigOptions::default()).build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - let result = Statistics::new(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - - let result = Executor::new(Some(&config), Some(&mut stat)); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - // create a store - let result = Store::new(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - // register an import module into store - let result = store.register_import_module(&mut executor, &import); - assert!(result.is_ok()); - - // get active module instance - let result = store.named_instance("extern-module-send"); - assert!(result.is_ok()); - let instance = result.unwrap(); - assert!(instance.name().is_some()); - assert_eq!(instance.name().unwrap(), "extern-module-send"); - - // check the exported global - let result = instance.global("global"); - assert!(result.is_ok()); - let global = result.unwrap(); - let ty = global.ty(); - assert_eq!(*ty, GlobalType::new(ValType::F32, Mutability::Const)); - if let Val::F32(value) = global.get_value() { - assert_eq!(value, 3.5); - } - - // get the exported memory - let result = instance.memory("memory"); - assert!(result.is_ok()); - let mut memory = result.unwrap(); - // write data - let result = memory.write(vec![1; 10], 10); - assert!(result.is_ok()); - // read data after write data - let result = memory.read(10, 10); - assert!(result.is_ok()); - let data = result.unwrap(); - assert_eq!(data, vec![1; 10]); - - // get the exported table by name - let result = instance.table("table"); - assert!(result.is_ok()); - let table = result.unwrap(); - // check table - assert!(table.name().is_some()); - assert_eq!(table.name().unwrap(), "table"); - assert!(table.mod_name().is_some()); - assert_eq!(table.mod_name().unwrap(), "extern-module-send"); - assert_eq!(table.size(), 10); - let ty = table.ty(); - assert_eq!(ty.elem_ty(), RefType::FuncRef); - assert_eq!(ty.minimum(), 10); - assert_eq!(ty.maximum(), Some(20)); - - // get the exported host function - let result = instance.func("add"); - assert!(result.is_ok()); - let host_func = result.unwrap(); - // check the signature of the host function - let func_ty = host_func.ty(); - assert!(func_ty.args().is_some()); - assert_eq!(func_ty.args().unwrap(), [ValType::I32; 2]); - assert!(func_ty.returns().is_some()); - assert_eq!(func_ty.returns().unwrap(), [ValType::I32]); - }); - - handle.join().unwrap(); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_import_sync() { - // create a Const global instance - let result = Global::new( - GlobalType::new(ValType::F32, Mutability::Const), - Val::F32(3.5), - ); - assert!(result.is_ok()); - let global_const = result.unwrap(); - - // create a memory instance - let result = MemoryType::new(10, Some(20), false); - assert!(result.is_ok()); - let memory_type = result.unwrap(); - let result = Memory::new(memory_type); - assert!(result.is_ok()); - let memory = result.unwrap(); - - // create a table instance - let result = Table::new(TableType::new(RefType::FuncRef, 10, Some(20))); - assert!(result.is_ok()); - let table = result.unwrap(); - - // create an import object - let result = ImportObjectBuilder::new() - .with_func::<(i32, i32), i32, NeverType>("add", real_add, None) - .expect("failed to add host function") - .with_global("global", global_const) - .with_memory("memory", memory) - .with_table("table", table) - .build::("extern-module-sync", None); - assert!(result.is_ok()); - let import = result.unwrap(); - let import = Arc::new(Mutex::new(import)); - - let import_cloned = Arc::clone(&import); - let handle = thread::spawn(move || { - let result = import_cloned.lock(); - assert!(result.is_ok()); - let import = result.unwrap(); - - // create an executor - let result = ConfigBuilder::new(CommonConfigOptions::default()).build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - let result = Statistics::new(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - - let result = Executor::new(Some(&config), Some(&mut stat)); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - // create a store - let result = Store::new(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - // register an import module into store - let result = store.register_import_module(&mut executor, &import); - assert!(result.is_ok()); - - // get active module instance - let result = store.named_instance("extern-module-sync"); - assert!(result.is_ok()); - let instance = result.unwrap(); - assert!(instance.name().is_some()); - assert_eq!(instance.name().unwrap(), "extern-module-sync"); - - // check the exported global - let result = instance.global("global"); - assert!(result.is_ok()); - let global = result.unwrap(); - let ty = global.ty(); - assert_eq!(*ty, GlobalType::new(ValType::F32, Mutability::Const)); - if let Val::F32(v) = global.get_value() { - assert_eq!(v, 3.5); - } - - // get the exported memory - let result = instance.memory("memory"); - assert!(result.is_ok()); - let mut memory = result.unwrap(); - // write data - let result = memory.write(vec![1; 10], 10); - assert!(result.is_ok()); - // read data after write data - let result = memory.read(10, 10); - assert!(result.is_ok()); - let data = result.unwrap(); - assert_eq!(data, vec![1; 10]); - - // get the exported table by name - let result = instance.table("table"); - assert!(result.is_ok()); - let table = result.unwrap(); - // check table - assert!(table.name().is_some()); - assert_eq!(table.name().unwrap(), "table"); - assert!(table.mod_name().is_some()); - assert_eq!(table.mod_name().unwrap(), "extern-module-sync"); - assert_eq!(table.size(), 10); - let ty = table.ty(); - assert_eq!(ty.elem_ty(), RefType::FuncRef); - assert_eq!(ty.minimum(), 10); - assert_eq!(ty.maximum(), Some(20)); - - // get the exported host function - let result = instance.func("add"); - assert!(result.is_ok()); - let host_func = result.unwrap(); - // check the signature of the host function - let func_ty = host_func.ty(); - assert!(func_ty.args().is_some()); - assert_eq!(func_ty.args().unwrap(), [ValType::I32; 2]); - assert!(func_ty.returns().is_some()); - assert_eq!(func_ty.returns().unwrap(), [ValType::I32]); - - // run host func - let result = host_func.run(&mut executor, params!(2, 3)); - assert!(result.is_ok()); - let returns = result.unwrap(); - assert_eq!(returns[0].to_i32(), 5); - }); - - handle.join().unwrap(); - } - - fn real_add( - _frame: CallingFrame, - inputs: Vec, - _data: *mut std::os::raw::c_void, - ) -> std::result::Result, HostFuncError> { - if inputs.len() != 2 { - return Err(HostFuncError::User(1)); - } - - let a = if inputs[0].ty() == ValType::I32 { - inputs[0].to_i32() - } else { - return Err(HostFuncError::User(2)); - }; - - let b = if inputs[1].ty() == ValType::I32 { - inputs[1].to_i32() - } else { - return Err(HostFuncError::User(3)); - }; - - let c = a + b; - - Ok(vec![WasmValue::from_i32(c)]) - } -} diff --git a/src/instance.rs b/src/instance.rs index b7e8625fe..60ac70205 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -5,207 +5,3 @@ use wasmedge_sys as sys; /// /// An [Instance] represents an instantiated module. In the instantiation process, A [module instance](crate::Instance) is created based on a [compiled module](crate::Module). From a [module instance] the exported [host function](crate::Func), [table](crate::Table), [memory](crate::Memory), and [global](crate::Global) instances can be fetched. pub type Instance = sys::Instance; - -// #[cfg(test)] -#[cfg(ignore)] -#[cfg(target_os = "linux")] -mod tests { - use crate::{ - config::{CommonConfigOptions, ConfigBuilder}, - error::HostFuncError, - types::Val, - CallingFrame, Executor, FuncTypeBuilder, Global, GlobalType, ImportObjectBuilder, Memory, - MemoryType, Module, Mutability, NeverType, RefType, Statistics, Store, Table, TableType, - ValType, WasmValue, - }; - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_instance_basic() { - // create an executor - let result = ConfigBuilder::new(CommonConfigOptions::default()).build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - let result = Statistics::new(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - - let result = Executor::new(Some(&config), Some(&mut stat)); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - // create a store - let result = Store::new(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - // check the exported instances - assert_eq!(store.named_instance_count(), 0); - assert_eq!(store.instance_names().len(), 0); - - // create a Const global instance - let result = Global::new( - GlobalType::new(ValType::F32, Mutability::Const), - Val::F32(3.5), - ); - assert!(result.is_ok()); - let global_const = result.unwrap(); - - // create a memory instance - let result = MemoryType::new(10, None, false); - assert!(result.is_ok()); - let memory_type = result.unwrap(); - let result = Memory::new(memory_type); - assert!(result.is_ok()); - let memory = result.unwrap(); - - // create a table instance - let result = Table::new(TableType::new(RefType::FuncRef, 5, None)); - assert!(result.is_ok()); - let table = result.unwrap(); - - // create an ImportModule instance - let result = ImportObjectBuilder::new() - .with_func::<(i32, i32), i32, NeverType>("add", real_add, None) - .expect("failed to add host function") - .with_global("global", global_const) - .with_memory("mem", memory) - .with_table("table", table) - .build::("extern-module", None); - assert!(result.is_ok()); - let import = result.unwrap(); - - let result = store.register_import_module(&mut executor, &import); - assert!(result.is_ok()); - - // add a wasm module from a file - let file = std::env::current_dir() - .unwrap() - .join("examples/wasmedge-sys/data/fibonacci.wat"); - let result = Module::from_file(Some(&config), file); - assert!(result.is_ok()); - let module = result.unwrap(); - - // register a module into store as a named module - let result = store.register_named_module(&mut executor, "fib-module", &module); - assert!(result.is_ok()); - - // check the exported instances - assert_eq!(store.named_instance_count(), 2); - assert_eq!(store.instance_names().len(), 2); - let mod_names = store.instance_names(); - assert_eq!(mod_names[0], "extern-module"); - assert_eq!(mod_names[1], "fib-module"); - - // check the module instance named "extern-module" - { - assert_eq!(mod_names[0], "extern-module"); - let result = store.named_instance(mod_names[0].as_str()); - assert!(result.is_ok()); - let instance = result.unwrap(); - assert!(instance.name().is_some()); - assert_eq!(instance.name().unwrap(), mod_names[0]); - - assert_eq!(instance.func_count(), 1); - assert_eq!(instance.table_count(), 1); - assert_eq!(instance.global_count(), 1); - assert_eq!(instance.memory_count(), 1); - - // check the exported host function - let result = instance.func("add"); - assert!(result.is_ok()); - let host_func = result.unwrap(); - assert_eq!( - host_func.ty(), - &FuncTypeBuilder::new() - .with_args(vec![ValType::I32; 2]) - .with_returns(vec![ValType::I32]) - .build() - ); - - // check the exported table - let result = instance.table("table"); - assert!(result.is_ok()); - let table = result.unwrap(); - - let table_name = table.name(); - assert!(table_name.is_some()); - assert_eq!(table.name().unwrap(), "table"); - assert_eq!(table.mod_name().unwrap(), "extern-module"); - assert_eq!(table.size(), 5); - - // check the exported memory - let result = instance.memory("mem"); - assert!(result.is_ok()); - let memory = result.unwrap(); - - assert_eq!(memory.name().unwrap(), "mem"); - assert_eq!(memory.mod_name().unwrap(), "extern-module"); - assert_eq!(memory.page(), 10); - assert_eq!(memory.size(), 65536 * 10); - - // check the exported global - let result = instance.global("global"); - assert!(result.is_ok()); - let global = result.unwrap(); - let val = global.get_value(); - if let Val::F32(val) = val { - assert_eq!(val, 3.5); - } - } - - // check the module instance named "fib-module" - { - assert_eq!(mod_names[1], "fib-module"); - let result = store.named_instance(mod_names[1].as_str()); - assert!(result.is_ok()); - let instance = result.unwrap(); - assert!(instance.name().is_some()); - assert_eq!(instance.name().unwrap(), mod_names[1]); - - assert_eq!(instance.func_count(), 1); - assert_eq!(instance.table_count(), 0); - assert_eq!(instance.global_count(), 0); - assert_eq!(instance.memory_count(), 0); - - // check the exported host function - let result = instance.func("fib"); - assert!(result.is_ok()); - let host_func = result.unwrap(); - assert_eq!( - host_func.ty(), - &FuncTypeBuilder::new() - .with_args(vec![ValType::I32]) - .with_returns(vec![ValType::I32]) - .build() - ); - } - } - - fn real_add( - _frame: CallingFrame, - inputs: Vec, - _data: *mut std::os::raw::c_void, - ) -> std::result::Result, HostFuncError> { - if inputs.len() != 2 { - return Err(HostFuncError::User(1)); - } - - let a = if inputs[0].ty() == ValType::I32 { - inputs[0].to_i32() - } else { - return Err(HostFuncError::User(2)); - }; - - let b = if inputs[1].ty() == ValType::I32 { - inputs[1].to_i32() - } else { - return Err(HostFuncError::User(3)); - }; - - let c = a + b; - - Ok(vec![WasmValue::from_i32(c)]) - } -} diff --git a/src/io.rs b/src/io.rs index 131eccdf5..ded23999a 100644 --- a/src/io.rs +++ b/src/io.rs @@ -65,11 +65,11 @@ mod test_wasm_val_type { /// Describes the mapping of a tuple of Rust types to Wasm types. /// /// ```rust -/// use wasmedge_sdk::{FuncRef, types::ExternRef, ValType, WasmValTypeList}; +/// use wasmedge_sdk::{types::ExternRef, ValType, WasmValTypeList}; /// /// assert_eq!( -/// <(i32, i64, f32, f64, FuncRef, ExternRef)>::wasm_types(), -/// [ValType::I32, ValType::I64, ValType::F32, ValType::F64, ValType::FuncRef, ValType::ExternRef] +/// <(i32, i64, f32, f64, ExternRef)>::wasm_types(), +/// [ValType::I32, ValType::I64, ValType::F32, ValType::F64, ValType::ExternRef] /// ); /// ``` pub trait WasmValTypeList diff --git a/src/store.rs b/src/store.rs index 36f6e64f4..4e05b289a 100644 --- a/src/store.rs +++ b/src/store.rs @@ -136,312 +136,3 @@ impl<'inst, T: AsInstance + ?Sized> Store<'inst, T> { &mut self.executor } } - -// #[cfg(test)] -#[cfg(ignore)] -mod tests { - use super::*; - use crate::{ - config::{CommonConfigOptions, ConfigBuilder}, - error::HostFuncError, - types::Val, - CallingFrame, Executor, Global, GlobalType, ImportObjectBuilder, Memory, MemoryType, - Module, Mutability, NeverType, RefType, Statistics, Table, TableType, ValType, WasmValue, - }; - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_store_create() { - let result = ConfigBuilder::new(CommonConfigOptions::default()).build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - let result = Statistics::new(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - - let result = Executor::new(Some(&config), Some(&mut stat)); - assert!(result.is_ok()); - - let result = Store::new(); - assert!(result.is_ok()); - let store = result.unwrap(); - - assert_eq!(store.named_instance_count(), 0); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_store_register_import_module() { - // create a Const global instance - let result = Global::new( - GlobalType::new(ValType::F32, Mutability::Const), - Val::F32(3.5), - ); - assert!(result.is_ok()); - let global_const = result.unwrap(); - - // create a memory instance - let result = MemoryType::new(10, None, false); - assert!(result.is_ok()); - let memory_type = result.unwrap(); - let result = Memory::new(memory_type); - assert!(result.is_ok()); - let memory = result.unwrap(); - - // create a table instance - let result = Table::new(TableType::new(RefType::FuncRef, 5, None)); - assert!(result.is_ok()); - let table = result.unwrap(); - - // create an ImportModule instance - let result = ImportObjectBuilder::new() - .with_func::<(i32, i32), i32, NeverType>("add", real_add, None) - .expect("failed to add host function") - .with_global("global", global_const) - .with_memory("mem", memory) - .with_table("table", table) - .build::("extern-module", None); - assert!(result.is_ok()); - let import = result.unwrap(); - - // create an executor - let result = ConfigBuilder::new(CommonConfigOptions::default()).build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - let result = Statistics::new(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - - let result = Executor::new(Some(&config), Some(&mut stat)); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - // create a store - let result = Store::new(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - // register an import module into store - let result = store.register_import_module(&mut executor, &import); - assert!(result.is_ok()); - - assert_eq!(store.named_instance_count(), 1); - assert_eq!(store.instance_names(), ["extern-module"]); - - // get active module instance - let result = store.named_instance("extern-module"); - assert!(result.is_ok()); - let instance = result.unwrap(); - assert!(instance.name().is_some()); - assert_eq!(instance.name().unwrap(), "extern-module"); - - let result = instance.global("global"); - assert!(result.is_ok()); - let global = result.unwrap(); - let ty = global.ty(); - assert_eq!(*ty, GlobalType::new(ValType::F32, Mutability::Const)); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_store_register_named_module() { - // create an executor - let result = ConfigBuilder::new(CommonConfigOptions::default()).build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - let result = Statistics::new(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - - let result = Executor::new(Some(&config), Some(&mut stat)); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - // create a store - let result = Store::new(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - // load wasm module - let file = std::env::current_dir() - .unwrap() - .join("examples/wasmedge-sys/data/fibonacci.wat"); - - let result = Module::from_file(Some(&config), file); - assert!(result.is_ok()); - let module = result.unwrap(); - - // register a module into store as a named module - let result = store.register_named_module(&mut executor, "extern-module", &module); - assert!(result.is_ok()); - - assert_eq!(store.named_instance_count(), 1); - assert_eq!(store.instance_names(), ["extern-module"]); - - // get active module instance - let result = store.named_instance("extern-module"); - assert!(result.is_ok()); - let instance = result.unwrap(); - assert!(instance.name().is_some()); - assert_eq!(instance.name().unwrap(), "extern-module"); - } - - #[test] - fn test_store_register_active_module() { - // create an executor - let result = ConfigBuilder::new(CommonConfigOptions::default()).build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - let result = Statistics::new(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - - let result = Executor::new(Some(&config), Some(&mut stat)); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - // create a store - let result = Store::new(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - // load wasm module - let file = std::env::current_dir() - .unwrap() - .join("examples/wasmedge-sys/data/fibonacci.wat"); - - let result = Module::from_file(Some(&config), file); - assert!(result.is_ok()); - let module = result.unwrap(); - - // register a module into store as active module - let result = store.register_active_module(&mut executor, &module); - assert!(result.is_ok()); - let active_instance = result.unwrap(); - assert!(active_instance.name().is_none()); - let result = active_instance.func("fib"); - assert!(result.is_ok()); - - assert_eq!(store.named_instance_count(), 0); - assert_eq!(store.instance_names().len(), 0); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_store_basic() { - // create an executor - let result = ConfigBuilder::new(CommonConfigOptions::default()).build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - let result = Statistics::new(); - assert!(result.is_ok()); - let mut stat = result.unwrap(); - - let result = Executor::new(Some(&config), Some(&mut stat)); - assert!(result.is_ok()); - let mut executor = result.unwrap(); - - // create a store - let result = Store::new(); - assert!(result.is_ok()); - let mut store = result.unwrap(); - - // create a Const global instance - let result = Global::new( - GlobalType::new(ValType::F32, Mutability::Const), - Val::F32(3.5), - ); - assert!(result.is_ok()); - let global_const = result.unwrap(); - - // create a memory instance - let result = MemoryType::new(10, None, false); - assert!(result.is_ok()); - let memory_type = result.unwrap(); - let result = Memory::new(memory_type); - assert!(result.is_ok()); - let memory = result.unwrap(); - - // create a table instance - let result = Table::new(TableType::new(RefType::FuncRef, 5, None)); - assert!(result.is_ok()); - let table = result.unwrap(); - - // create an ImportModule instance - let result = ImportObjectBuilder::new() - .with_func::<(i32, i32), i32, NeverType>("add", real_add, None) - .expect("failed to add host function") - .with_global("global", global_const) - .with_memory("mem", memory) - .with_table("table", table) - .build::("extern-module", None); - assert!(result.is_ok()); - let import = result.unwrap(); - - // register a module into store as a named module - let result = store.register_import_module(&mut executor, &import); - assert!(result.is_ok()); - - // add a wasm module from a file - let file = std::env::current_dir() - .unwrap() - .join("examples/wasmedge-sys/data/fibonacci.wat"); - let result = Module::from_file(Some(&config), file); - assert!(result.is_ok()); - let module = result.unwrap(); - - let result = store.register_named_module(&mut executor, "fib-module", &module); - assert!(result.is_ok()); - - // check the exported instances - assert_eq!(store.named_instance_count(), 2); - let mod_names = store.instance_names(); - assert_eq!(mod_names[0], "extern-module"); - assert_eq!(mod_names[1], "fib-module"); - - assert_eq!(mod_names[0], "extern-module"); - let result = store.named_instance(&mod_names[0]); - assert!(result.is_ok()); - let instance = result.unwrap(); - assert!(instance.name().is_some()); - assert_eq!(instance.name().unwrap(), mod_names[0]); - - assert_eq!(mod_names[1], "fib-module"); - let result = store.named_instance(&mod_names[1]); - assert!(result.is_ok()); - let instance = result.unwrap(); - assert!(instance.name().is_some()); - assert_eq!(instance.name().unwrap(), mod_names[1]); - } - - fn real_add( - _frame: CallingFrame, - inputs: Vec, - _data: *mut std::os::raw::c_void, - ) -> std::result::Result, HostFuncError> { - if inputs.len() != 2 { - return Err(HostFuncError::User(1)); - } - - let a = if inputs[0].ty() == ValType::I32 { - inputs[0].to_i32() - } else { - return Err(HostFuncError::User(2)); - }; - - let b = if inputs[1].ty() == ValType::I32 { - inputs[1].to_i32() - } else { - return Err(HostFuncError::User(3)); - }; - - let c = a + b; - - Ok(vec![WasmValue::from_i32(c)]) - } -} diff --git a/src/vm.rs b/src/vm.rs index c586b5f76..2ee3431a0 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -17,62 +17,57 @@ impl SyncInst for Instance {} /// The example below presents how to register a module as named module in a Vm instance and run a target wasm function. /// /// ```rust -/// // If the version of rust used is less than v1.63, please uncomment the follow attribute. -/// // #![feature(explicit_generic_args_with_impl_trait)] -/// #[cfg(not(feature = "async"))] -/// use wasmedge_sdk::{params, VmBuilder, WasmVal, wat2wasm, ValType, NeverType}; +/// use std::collections::HashMap; +/// use wasmedge_sdk::{params, Store, Module, WasmVal, wat2wasm, ValType, NeverType, Vm, vm::SyncInst}; /// -/// #[cfg_attr(test, test)] -/// fn main() -> Result<(), Box> { -/// #[cfg(not(feature = "async"))] -/// { -/// // create a Vm context -/// let vm = VmBuilder::new().build()?; -/// -/// // register a wasm module from the given in-memory wasm bytes -/// let wasm_bytes = wat2wasm( -/// br#"(module -/// (export "fib" (func $fib)) -/// (func $fib (param $n i32) (result i32) -/// (if -/// (i32.lt_s -/// (get_local $n) -/// (i32.const 2) -/// ) -/// (return -/// (i32.const 1) -/// ) -/// ) -/// (return -/// (i32.add -/// (call $fib -/// (i32.sub -/// (get_local $n) -/// (i32.const 2) -/// ) -/// ) -/// (call $fib -/// (i32.sub -/// (get_local $n) -/// (i32.const 1) -/// ) -/// ) -/// ) -/// ) -/// ) -/// ) -/// "#, -/// )?; -/// let mut vm = vm.register_module_from_bytes("extern", wasm_bytes)?; -/// -/// // run `fib` function in the named module instance -/// let returns = vm.run_func(Some("extern"), "fib", params!(10))?; -/// assert_eq!(returns.len(), 1); -/// assert_eq!(returns[0].to_i32(), 89); -/// } -/// -/// Ok(()) -/// } +/// // create a Vm context +/// let mut vm = +/// Vm::new(Store::new(None, HashMap::::new()).unwrap()); +/// // register a wasm module from the given in-memory wasm bytes +/// // load wasm module +/// let result = wat2wasm( +/// br#"(module +/// (export "fib" (func $fib)) +/// (func $fib (param $n i32) (result i32) +/// (if +/// (i32.lt_s +/// (get_local $n) +/// (i32.const 2) +/// ) +/// (return +/// (i32.const 1) +/// ) +/// ) +/// (return +/// (i32.add +/// (call $fib +/// (i32.sub +/// (get_local $n) +/// (i32.const 2) +/// ) +/// ) +/// (call $fib +/// (i32.sub +/// (get_local $n) +/// (i32.const 1) +/// ) +/// ) +/// ) +/// ) +/// ) +/// ) +/// "#, +/// ); +/// assert!(result.is_ok()); +/// let wasm_bytes = result.unwrap(); +/// // run `fib` function from the wasm bytes +/// let fib_module = Module::from_bytes(None, wasm_bytes).unwrap(); +/// vm.register_module(None, fib_module).unwrap(); +/// let result = vm.run_func(None, "fib", params!(10i32)); +/// assert!(result.is_ok()); +/// let returns = result.unwrap(); +/// assert_eq!(returns.len(), 1); +/// assert_eq!(returns[0].to_i32(), 89); /// ``` #[derive(Debug)] pub struct Vm<'inst, T: ?Sized + SyncInst> { @@ -266,29 +261,20 @@ impl<'inst, T: ?Sized + SyncInst> Vm<'inst, T> { } } -// #[cfg(test)] -#[cfg(ignore)] +#[cfg(test)] mod tests { + use std::collections::HashMap; + + use wasmedge_types::wat2wasm; + use super::*; - use crate::{ - config::{ - CommonConfigOptions, ConfigBuilder, HostRegistrationConfigOptions, - StatisticsConfigOptions, - }, - error::HostFuncError, - io::WasmVal, - params, - types::Val, - wat2wasm, CallingFrame, Global, GlobalType, ImportObjectBuilder, Memory, MemoryType, - Mutability, NeverType, RefType, Table, TableType, ValType, WasmValue, - }; + use crate::{params, WasmVal}; #[test] fn test_vm_run_func_from_file() { // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let mut vm = result.unwrap(); + let mut vm = + Vm::new(Store::new(None, HashMap::::new()).unwrap()); // register a wasm module from a specified wasm file let file = std::env::current_dir() @@ -296,7 +282,9 @@ mod tests { .join("examples/wasmedge-sys/data/fibonacci.wat"); // run `fib` function from the wasm file - let result = vm.run_func_from_file(file, "fib", params!(10)); + let fib_module = Module::from_file(None, file).unwrap(); + vm.register_module(None, fib_module).unwrap(); + let result = vm.run_func(None, "fib", params!(10i32)); assert!(result.is_ok()); let returns = result.unwrap(); assert_eq!(returns.len(), 1); @@ -306,9 +294,8 @@ mod tests { #[test] fn test_vm_run_func_from_bytes() { // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let mut vm = result.unwrap(); + let mut vm = + Vm::new(Store::new(None, HashMap::::new()).unwrap()); // register a wasm module from the given in-memory wasm bytes // load wasm module @@ -349,62 +336,9 @@ mod tests { let wasm_bytes = result.unwrap(); // run `fib` function from the wasm bytes - let result = vm.run_func_from_bytes(&wasm_bytes, "fib", params!(10)); - assert!(result.is_ok()); - let returns = result.unwrap(); - assert_eq!(returns.len(), 1); - assert_eq!(returns[0].to_i32(), 89); - } - - #[test] - fn test_vm_run_func_from_module() { - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let mut vm = result.unwrap(); - - // load wasm module - let result = wat2wasm( - br#"(module - (export "fib" (func $fib)) - (func $fib (param $n i32) (result i32) - (if - (i32.lt_s - (get_local $n) - (i32.const 2) - ) - (return - (i32.const 1) - ) - ) - (return - (i32.add - (call $fib - (i32.sub - (get_local $n) - (i32.const 2) - ) - ) - (call $fib - (i32.sub - (get_local $n) - (i32.const 1) - ) - ) - ) - ) - ) - ) - "#, - ); - assert!(result.is_ok()); - let wasm_bytes = result.unwrap(); - let result = Module::from_bytes(None, wasm_bytes); - assert!(result.is_ok()); - let module = result.unwrap(); - - // run `fib` function from the compiled module - let result = vm.run_func_from_module(module, "fib", params!(10)); + let fib_module = Module::from_bytes(None, wasm_bytes).unwrap(); + vm.register_module(None, fib_module).unwrap(); + let result = vm.run_func(None, "fib", params!(10i32)); assert!(result.is_ok()); let returns = result.unwrap(); assert_eq!(returns.len(), 1); @@ -414,9 +348,8 @@ mod tests { #[test] fn test_vm_run_func_in_named_module_instance() { // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let vm = result.unwrap(); + let mut vm = + Vm::new(Store::new(None, HashMap::::new()).unwrap()); // register a wasm module from the given in-memory wasm bytes // load wasm module @@ -455,10 +388,8 @@ mod tests { ); assert!(result.is_ok()); let wasm_bytes = result.unwrap(); - let result = vm.register_module_from_bytes("extern", wasm_bytes); - assert!(result.is_ok()); - let vm = result.unwrap(); - + let fib_module = Module::from_bytes(None, wasm_bytes).unwrap(); + vm.register_module(Some("extern"), fib_module).unwrap(); // run `fib` function in the named module instance let result = vm.run_func(Some("extern"), "fib", params!(10)); assert!(result.is_ok()); @@ -466,463 +397,4 @@ mod tests { assert_eq!(returns.len(), 1); assert_eq!(returns[0].to_i32(), 89); } - - #[test] - fn test_vm_run_func_in_active_module_instance() { - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // load wasm module - let result = wat2wasm( - br#"(module - (export "fib" (func $fib)) - (func $fib (param $n i32) (result i32) - (if - (i32.lt_s - (get_local $n) - (i32.const 2) - ) - (return - (i32.const 1) - ) - ) - (return - (i32.add - (call $fib - (i32.sub - (get_local $n) - (i32.const 2) - ) - ) - (call $fib - (i32.sub - (get_local $n) - (i32.const 1) - ) - ) - ) - ) - ) - ) - "#, - ); - assert!(result.is_ok()); - let wasm_bytes = result.unwrap(); - let result = Module::from_bytes(None, wasm_bytes); - assert!(result.is_ok()); - let module = result.unwrap(); - - // register the wasm module into vm - let result = vm.register_module(None, module); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // run `fib` function in the active module instance - let result = vm.run_func(None, "fib", params!(10)); - assert!(result.is_ok()); - let returns = result.unwrap(); - assert_eq!(returns.len(), 1); - assert_eq!(returns[0].to_i32(), 89); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_vm_create() { - { - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - } - - { - // create a Config - let result = ConfigBuilder::new(CommonConfigOptions::default()).build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - // create a Vm context - let result = VmBuilder::new().with_config(config).build(); - assert!(result.is_ok()); - let _vm = result.unwrap(); - } - } - - #[test] - fn test_vm_wasi_module() { - let host_reg_options = HostRegistrationConfigOptions::default().wasi(true); - let result = ConfigBuilder::new(CommonConfigOptions::default()) - .with_host_registration_config(host_reg_options) - .build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - // create a vm with the config settings - let result = VmBuilder::new().with_config(config).build(); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // get the wasi module - let result = vm.wasi_module(); - assert!(result.is_some()); - let wasi_instance = result.unwrap(); - - assert_eq!(wasi_instance.name(), "wasi_snapshot_preview1"); - } - - #[test] - fn test_vm_statistics() { - // set config options related to Statistics - let stat_config_options = StatisticsConfigOptions::new() - .measure_cost(true) - .measure_time(true) - .count_instructions(true); - // create a Config - let result = ConfigBuilder::new(CommonConfigOptions::default()) - .with_statistics_config(stat_config_options) - .build(); - assert!(result.is_ok()); - let config = result.unwrap(); - - // create a Vm context - let result = VmBuilder::new().with_config(config).build(); - assert!(result.is_ok()); - let _vm = result.unwrap(); - - // get the statistics - // let _stat = vm.statistics_mut(); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_vm_register_module_from_file() { - { - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // register a wasm module from a specified wasm file - let file = std::env::current_dir() - .unwrap() - .join("examples/wasmedge-sys/data/fibonacci.wat"); - let result = vm.register_module_from_file("extern", file); - assert!(result.is_ok()); - let vm = result.unwrap(); - - assert!(vm.named_instance_count() >= 1); - assert!(vm.instance_names().iter().any(|x| x == "extern")); - } - - { - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // register a wasm module from a specified wasm file - let file = std::env::current_dir() - .unwrap() - .join("examples/wasmedge-sys/data/fibonacci.wat"); - let result = vm.register_module_from_file("extern", file); - assert!(result.is_ok()); - let vm = result.unwrap(); - - assert!(vm.named_instance_count() >= 1); - assert!(vm.instance_names().iter().any(|x| x == "extern")); - } - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_vm_register_module_from_bytes() { - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // register a wasm module from the given in-memory wasm bytes - // load wasm module - let result = wat2wasm( - br#"(module - (export "fib" (func $fib)) - (func $fib (param $n i32) (result i32) - (if - (i32.lt_s - (get_local $n) - (i32.const 2) - ) - (return - (i32.const 1) - ) - ) - (return - (i32.add - (call $fib - (i32.sub - (get_local $n) - (i32.const 2) - ) - ) - (call $fib - (i32.sub - (get_local $n) - (i32.const 1) - ) - ) - ) - ) - ) - ) - "#, - ); - assert!(result.is_ok()); - let wasm_bytes = result.unwrap(); - let result = vm.register_module_from_bytes("extern", wasm_bytes); - assert!(result.is_ok()); - let vm = result.unwrap(); - - assert!(vm.named_instance_count() >= 1); - assert!(vm.instance_names().iter().any(|x| x == "extern")); - } - - #[test] - #[allow(clippy::assertions_on_result_states)] - fn test_vm_register_import_module() { - // create a Const global instance - let result = Global::new( - GlobalType::new(ValType::F32, Mutability::Const), - Val::F32(3.5), - ); - assert!(result.is_ok()); - let global_const = result.unwrap(); - - // create a memory instance - let result = MemoryType::new(10, None, false); - assert!(result.is_ok()); - let memory_type = result.unwrap(); - let result = Memory::new(memory_type); - assert!(result.is_ok()); - let memory = result.unwrap(); - - // create a table instance - let result = Table::new(TableType::new(RefType::FuncRef, 5, None)); - assert!(result.is_ok()); - let table = result.unwrap(); - - // create an ImportModule instance - let result = ImportObjectBuilder::new() - .with_func::<(i32, i32), i32, NeverType>("add", real_add, None) - .expect("failed to add host function") - .with_global("global", global_const) - .with_memory("mem", memory) - .with_table("table", table) - .build::("extern-module", None); - assert!(result.is_ok()); - let import = result.unwrap(); - - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let mut vm = result.unwrap(); - - // register an import module into vm - let result = vm.register_import_module(&import); - assert!(result.is_ok()); - - assert!(vm.named_instance_count() >= 1); - assert!(vm.instance_names().iter().any(|x| x == "extern-module")); - - // get active module instance - let result = vm.named_module("extern-module"); - assert!(result.is_ok()); - let instance = result.unwrap(); - assert!(instance.name().is_some()); - assert_eq!(instance.name().unwrap(), "extern-module"); - - let result = instance.global("global"); - assert!(result.is_ok()); - let global = result.unwrap(); - let ty = global.ty(); - assert_eq!(*ty, GlobalType::new(ValType::F32, Mutability::Const)); - } - - #[test] - fn test_vm_register_named_module() { - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // load wasm module - let result = wat2wasm( - br#"(module - (export "fib" (func $fib)) - (func $fib (param $n i32) (result i32) - (if - (i32.lt_s - (get_local $n) - (i32.const 2) - ) - (return - (i32.const 1) - ) - ) - (return - (i32.add - (call $fib - (i32.sub - (get_local $n) - (i32.const 2) - ) - ) - (call $fib - (i32.sub - (get_local $n) - (i32.const 1) - ) - ) - ) - ) - ) - ) - "#, - ); - assert!(result.is_ok()); - let wasm_bytes = result.unwrap(); - let result = Module::from_bytes(None, wasm_bytes); - assert!(result.is_ok()); - let module = result.unwrap(); - - // register the wasm module into vm - let result = vm.register_module(Some("extern"), module); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // check the exported functions in the "extern" module - assert!(vm.named_instance_count() >= 1); - let result = vm.named_module("extern"); - assert!(result.is_ok()); - let instance = result.unwrap(); - - assert_eq!(instance.func_count(), 1); - let result = instance.func_names(); - assert!(result.is_some()); - let func_names = result.unwrap(); - assert_eq!(func_names, ["fib"]); - - // get host_func - let result = instance.func("fib"); - assert!(result.is_ok()); - let fib = result.unwrap(); - - // check the type of host_func - let ty = fib.ty(); - assert!(ty.args().is_some()); - assert_eq!(ty.args().unwrap(), [ValType::I32]); - assert!(ty.returns().is_some()); - assert_eq!(ty.returns().unwrap(), [ValType::I32]); - } - - #[test] - fn test_vm_register_active_module() { - // create a Vm context - let result = VmBuilder::new().build(); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // load wasm module - let result = wat2wasm( - br#"(module - (export "fib" (func $fib)) - (func $fib (param $n i32) (result i32) - (if - (i32.lt_s - (get_local $n) - (i32.const 2) - ) - (return - (i32.const 1) - ) - ) - (return - (i32.add - (call $fib - (i32.sub - (get_local $n) - (i32.const 2) - ) - ) - (call $fib - (i32.sub - (get_local $n) - (i32.const 1) - ) - ) - ) - ) - ) - ) - "#, - ); - assert!(result.is_ok()); - let wasm_bytes = result.unwrap(); - let result = Module::from_bytes(None, wasm_bytes); - assert!(result.is_ok()); - let module = result.unwrap(); - - // register the wasm module into vm - let result = vm.register_module(None, module); - assert!(result.is_ok()); - let vm = result.unwrap(); - - // check the exported functions in the "extern" module - let result = vm.active_module(); - assert!(result.is_ok()); - let instance = result.unwrap(); - - assert_eq!(instance.func_count(), 1); - let result = instance.func_names(); - assert!(result.is_some()); - let func_names = result.unwrap(); - assert_eq!(func_names, ["fib"]); - - // get host_func - let result = instance.func("fib"); - assert!(result.is_ok()); - let fib = result.unwrap(); - - // check the type of host_func - let ty = fib.ty(); - assert!(ty.args().is_some()); - assert_eq!(ty.args().unwrap(), [ValType::I32]); - assert!(ty.returns().is_some()); - assert_eq!(ty.returns().unwrap(), [ValType::I32]); - } - - fn real_add( - _frame: CallingFrame, - inputs: Vec, - _data: *mut std::os::raw::c_void, - ) -> std::result::Result, HostFuncError> { - if inputs.len() != 2 { - return Err(HostFuncError::User(1)); - } - - let a = if inputs[0].ty() == ValType::I32 { - inputs[0].to_i32() - } else { - return Err(HostFuncError::User(2)); - }; - - let b = if inputs[1].ty() == ValType::I32 { - inputs[1].to_i32() - } else { - return Err(HostFuncError::User(3)); - }; - - let c = a + b; - - Ok(vec![WasmValue::from_i32(c)]) - } }