From 12a0261051a276c18f1b7b4e7032f694efc1c363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Sch=C3=BCtt?= Date: Wed, 31 Aug 2022 14:25:46 +0200 Subject: [PATCH 01/14] Unify tests between -sys and -js API --- lib/api/tests/externals.rs | 477 +++++++++++++++ lib/api/tests/instance.rs | 89 +++ lib/api/tests/js_externals.rs | 445 -------------- lib/api/tests/js_instance.rs | 852 --------------------------- lib/api/tests/js_module.rs | 293 --------- lib/api/tests/module.rs | 297 ++++++++++ lib/api/tests/reference_types.rs | 551 +++++++++++++++++ lib/api/tests/sys_externals.rs | 519 ---------------- lib/api/tests/sys_instance.rs | 76 --- lib/api/tests/sys_module.rs | 267 --------- lib/api/tests/sys_reference_types.rs | 490 --------------- 11 files changed, 1414 insertions(+), 2942 deletions(-) create mode 100644 lib/api/tests/externals.rs create mode 100644 lib/api/tests/instance.rs delete mode 100644 lib/api/tests/js_externals.rs delete mode 100644 lib/api/tests/js_instance.rs delete mode 100644 lib/api/tests/js_module.rs create mode 100644 lib/api/tests/module.rs create mode 100644 lib/api/tests/reference_types.rs delete mode 100644 lib/api/tests/sys_externals.rs delete mode 100644 lib/api/tests/sys_instance.rs delete mode 100644 lib/api/tests/sys_module.rs delete mode 100644 lib/api/tests/sys_reference_types.rs diff --git a/lib/api/tests/externals.rs b/lib/api/tests/externals.rs new file mode 100644 index 00000000000..eb23b5e7aa4 --- /dev/null +++ b/lib/api/tests/externals.rs @@ -0,0 +1,477 @@ +use anyhow::Result; +#[cfg(feature = "js")] +use wasm_bindgen_test::*; + +use wasmer::*; + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn global_new_js() { + global_new().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn global_new() -> Result<()> { + let mut store = Store::default(); + let global = Global::new(&mut store, Value::I32(10)); + assert_eq!( + global.ty(&mut store), + GlobalType { + ty: Type::I32, + mutability: Mutability::Const + } + ); + + let global_mut = Global::new_mut(&mut store, Value::I32(10)); + assert_eq!( + global_mut.ty(&mut store), + GlobalType { + ty: Type::I32, + mutability: Mutability::Var + } + ); + + Ok(()) +} + + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn global_get_js() { + global_get().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn global_get() -> Result<()> { + let mut store = Store::default(); + let global_i32 = Global::new(&mut store, Value::I32(10)); + assert_eq!(global_i32.get(&mut store), Value::I32(10)); + let global_i64 = Global::new(&mut store, Value::I64(20)); + assert_eq!(global_i64.get(&mut store), Value::I64(20)); + let global_f32 = Global::new(&mut store, Value::F32(10.0)); + assert_eq!(global_f32.get(&mut store), Value::F32(10.0)); + let global_f64 = Global::new(&mut store, Value::F64(20.0)); + assert_eq!(global_f64.get(&mut store), Value::F64(20.0)); + + Ok(()) +} + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn global_set_js() { + global_set().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn global_set() -> Result<()> { + let mut store = Store::default(); + let global_i32 = Global::new(&mut store, Value::I32(10)); + // Set on a constant should error + assert!(global_i32.set(&mut store, Value::I32(20)).is_err()); + + let global_i32_mut = Global::new_mut(&mut store, Value::I32(10)); + // Set on different type should error + assert!(global_i32_mut.set(&mut store, Value::I64(20)).is_err()); + + // Set on same type should succeed + global_i32_mut.set(&mut store, Value::I32(20))?; + assert_eq!(global_i32_mut.get(&mut store), Value::I32(20)); + + Ok(()) +} + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn table_new_js() { + table_new().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn table_new() -> Result<()> { + let mut store = Store::default(); + let table_type = TableType { + ty: Type::FuncRef, + minimum: 0, + maximum: None, + }; + let f = Function::new_typed(&mut store, || {}); + let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f)))?; + assert_eq!(table.ty(&mut store), table_type); + + // Anyrefs not yet supported + // let table_type = TableType { + // ty: Type::ExternRef, + // minimum: 0, + // maximum: None, + // }; + // let table = Table::new(&store, table_type, Value::ExternRef(ExternRef::Null))?; + // assert_eq!(*table.ty(), table_type); + + Ok(()) +} + +#[cfg_attr(feature = "sys", test)] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +#[ignore] +fn table_get_js() { + table_get().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn table_get() -> Result<()> { + let mut store = Store::default(); + let table_type = TableType { + ty: Type::FuncRef, + minimum: 0, + maximum: Some(1), + }; + let f = Function::new_typed(&mut store, |num: i32| num + 1); + let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f)))?; + assert_eq!(table.ty(&mut store), table_type); + let _elem = table.get(&mut store, 0).unwrap(); + // assert_eq!(elem.funcref().unwrap(), f); + Ok(()) +} + +#[cfg_attr(feature = "sys", test)] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +#[ignore] +fn table_set_js() { + table_set().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn table_set() -> Result<()> { + // Table set not yet tested + Ok(()) +} + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn table_grow_js() { + table_grow().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn table_grow() -> Result<()> { + let mut store = Store::default(); + let table_type = TableType { + ty: Type::FuncRef, + minimum: 0, + maximum: Some(10), + }; + let f = Function::new_typed(&mut store, |num: i32| num + 1); + let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f.clone())))?; + // Growing to a bigger maximum should return None + let old_len = table.grow(&mut store, 12, Value::FuncRef(Some(f.clone()))); + assert!(old_len.is_err()); + + // Growing to a bigger maximum should return None + let old_len = table.grow(&mut store, 5, Value::FuncRef(Some(f)))?; + assert_eq!(old_len, 0); + + Ok(()) +} + +#[cfg_attr(feature = "sys", test)] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +#[ignore] +fn table_copy_js() { + table_copy().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn table_copy() -> Result<()> { + // TODO: table copy test not yet implemented + Ok(()) +} + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn memory_new_js() { + memory_new().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn memory_new() -> Result<()> { + let mut store = Store::default(); + let memory_type = MemoryType { + shared: false, + minimum: Pages(0), + maximum: Some(Pages(10)), + }; + let memory = Memory::new(&mut store, memory_type)?; + assert_eq!(memory.view(&mut store).size(), Pages(0)); + assert_eq!(memory.ty(&mut store), memory_type); + Ok(()) +} + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn memory_grow_js() { + memory_grow().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn memory_grow() -> Result<()> { + let mut store = Store::default(); + let desc = MemoryType::new(Pages(10), Some(Pages(16)), false); + let memory = Memory::new(&mut store, desc)?; + assert_eq!(memory.view(&mut store).size(), Pages(10)); + + let result = memory.grow(&mut store, Pages(2)).unwrap(); + assert_eq!(result, Pages(10)); + assert_eq!(memory.view(&mut store).size(), Pages(12)); + + let result = memory.grow(&mut store, Pages(10)); + assert_eq!( + result, + Err(MemoryError::CouldNotGrow { + current: 12.into(), + attempted_delta: 10.into() + }) + ); + + let bad_desc = MemoryType::new(Pages(15), Some(Pages(10)), false); + let bad_result = Memory::new(&mut store, bad_desc); + + assert!(matches!(bad_result, Err(MemoryError::InvalidMemory { .. }))); + + Ok(()) +} + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn function_new_js() { + function_new().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn function_new() -> Result<()> { + let mut store = Store::default(); + let function = Function::new_typed(&mut store, || {}); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![], vec![]) + ); + let function = Function::new_typed(&mut store, |_a: i32| {}); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![Type::I32], vec![]) + ); + let function = Function::new_typed(&mut store, |_a: i32, _b: i64, _c: f32, _d: f64| {}); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) + ); + let function = Function::new_typed(&mut store, || -> i32 { 1 }); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![], vec![Type::I32]) + ); + let function = + Function::new_typed(&mut store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) + ); + Ok(()) +} + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn function_new_env_js() { + function_new_env().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn function_new_env() -> Result<()> { + let mut store = Store::default(); + #[derive(Clone)] + struct MyEnv {} + + let my_env = MyEnv {}; + let env = FunctionEnv::new(&mut store, my_env); + let function = + Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut| {}); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![], vec![]) + ); + let function = Function::new_typed_with_env( + &mut store, + &env, + |_env: FunctionEnvMut, _a: i32| {}, + ); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![Type::I32], vec![]) + ); + let function = Function::new_typed_with_env( + &mut store, + &env, + |_env: FunctionEnvMut, _a: i32, _b: i64, _c: f32, _d: f64| {}, + ); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) + ); + let function = + Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut| -> i32 { + 1 + }); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![], vec![Type::I32]) + ); + let function = Function::new_typed_with_env( + &mut store, + &env, + |_env: FunctionEnvMut| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, + ); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) + ); + Ok(()) +} + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn function_new_dynamic_js() { + function_new_dynamic().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn function_new_dynamic() -> Result<()> { + let mut store = Store::default(); + + // Using &FunctionType signature + let function_type = FunctionType::new(vec![], vec![]); + let function = Function::new( + &mut store, + &function_type, + |_values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = FunctionType::new(vec![Type::I32], vec![]); + let function = Function::new( + &mut store, + &function_type, + |_values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = + FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); + let function = Function::new( + &mut store, + &function_type, + |_values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = FunctionType::new(vec![], vec![Type::I32]); + let function = Function::new( + &mut store, + &function_type, + |_values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = + FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); + let function = Function::new( + &mut store, + &function_type, + |_values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + + // Using array signature + let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); + let function = Function::new( + &mut store, + function_type, + |_values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).params(), [Type::V128]); + assert_eq!( + function.ty(&mut store).results(), + [Type::I32, Type::F32, Type::F64] + ); + + Ok(()) +} + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn function_new_dynamic_env_js() { + function_new_dynamic_env().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn function_new_dynamic_env() -> Result<()> { + let mut store = Store::default(); + #[derive(Clone)] + struct MyEnv {} + let my_env = MyEnv {}; + let env = FunctionEnv::new(&mut store, my_env); + + // Using &FunctionType signature + let function_type = FunctionType::new(vec![], vec![]); + let function = Function::new_with_env( + &mut store, + &env, + &function_type, + |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = FunctionType::new(vec![Type::I32], vec![]); + let function = Function::new_with_env( + &mut store, + &env, + &function_type, + |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = + FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); + let function = Function::new_with_env( + &mut store, + &env, + &function_type, + |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = FunctionType::new(vec![], vec![Type::I32]); + let function = Function::new_with_env( + &mut store, + &env, + &function_type, + |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = + FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); + let function = Function::new_with_env( + &mut store, + &env, + &function_type, + |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + + // Using array signature + let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); + let function = Function::new_with_env( + &mut store, + &env, + function_type, + |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).params(), [Type::V128]); + assert_eq!( + function.ty(&mut store).results(), + [Type::I32, Type::F32, Type::F64] + ); + + Ok(()) +} \ No newline at end of file diff --git a/lib/api/tests/instance.rs b/lib/api/tests/instance.rs new file mode 100644 index 00000000000..c3268d8cc46 --- /dev/null +++ b/lib/api/tests/instance.rs @@ -0,0 +1,89 @@ +use anyhow::Result; +#[cfg(feature = "js")] +use wasm_bindgen_test::*; + +use wasmer::*; + + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn exports_work_after_multiple_instances_have_been_freed_js() { + exports_work_after_multiple_instances_have_been_freed().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn exports_work_after_multiple_instances_have_been_freed() -> Result<()> { + let mut store = Store::default(); + let module = Module::new( + &store, + " +(module + (type $sum_t (func (param i32 i32) (result i32))) + (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) + local.get $x + local.get $y + i32.add) + (export \"sum\" (func $sum_f))) +", + )?; + + let imports = Imports::new(); + let instance = Instance::new(&mut store, &module, &imports)?; + let instance2 = instance.clone(); + let instance3 = instance.clone(); + + // The function is cloned to “break” the connection with `instance`. + let sum = instance.exports.get_function("sum")?.clone(); + + drop(instance); + drop(instance2); + drop(instance3); + + // All instances have been dropped, but `sum` continues to work! + assert_eq!( + sum.call(&mut store, &[Value::I32(1), Value::I32(2)])? + .into_vec(), + vec![Value::I32(3)], + ); + + Ok(()) +} + + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn unit_native_function_env_js() { + unit_native_function_env().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn unit_native_function_env() -> Result<()> { + let mut store = Store::default(); + + #[derive(Clone)] + struct Env { + multiplier: u32, + } + + fn imported_fn( + env: FunctionEnvMut, + args: &[Value], + ) -> Result, RuntimeError> { + let value = env.data().multiplier * args[0].unwrap_i32() as u32; + Ok(vec![Value::I32(value as _)]) + } + + // We create the environment + let env = Env { multiplier: 3 }; + // We move the environment to the store, so it can be used by the `Function` + let env = FunctionEnv::new(&mut store, env); + + let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); + let imported = Function::new_with_env(&mut store, &env, imported_signature, imported_fn); + + let expected = vec![Value::I32(12)].into_boxed_slice(); + let result = imported.call(&mut store, &[Value::I32(4)])?; + assert_eq!(result, expected); + + Ok(()) +} \ No newline at end of file diff --git a/lib/api/tests/js_externals.rs b/lib/api/tests/js_externals.rs deleted file mode 100644 index 90a181ec874..00000000000 --- a/lib/api/tests/js_externals.rs +++ /dev/null @@ -1,445 +0,0 @@ -#[cfg(feature = "js")] -mod js { - use wasm_bindgen_test::*; - use wasmer::*; - - #[wasm_bindgen_test] - fn global_new() { - let mut store = Store::default(); - let global = Global::new(&mut store, Value::I32(10)); - assert_eq!( - global.ty(&store), - GlobalType { - ty: Type::I32, - mutability: Mutability::Const - } - ); - - let global_mut = Global::new_mut(&mut store, Value::I32(10)); - assert_eq!( - global_mut.ty(&store), - GlobalType { - ty: Type::I32, - mutability: Mutability::Var - } - ); - } - - #[wasm_bindgen_test] - fn global_get() { - let mut store = Store::default(); - let global_i32 = Global::new(&mut store, Value::I32(10)); - assert_eq!(global_i32.get(&mut store), Value::I32(10)); - // 64-bit values are not yet fully supported in some versions of Node - // Commenting this tests for now: - - // let global_i64 = Global::new(&store, Value::I64(20)); - // assert_eq!(global_i64.get(), Value::I64(20)); - let global_f32 = Global::new(&mut store, Value::F32(10.0)); - assert_eq!(global_f32.get(&store), Value::F32(10.0)); - // let global_f64 = Global::new(&store, Value::F64(20.0)); - // assert_eq!(global_f64.get(), Value::F64(20.0)); - } - - #[wasm_bindgen_test] - fn global_set() { - let mut store = Store::default(); - let global_i32 = Global::new(&mut store, Value::I32(10)); - // Set on a constant should error - assert!(global_i32.set(&mut store, Value::I32(20)).is_err()); - - let global_i32_mut = Global::new_mut(&mut store, Value::I32(10)); - // Set on different type should error - assert!(global_i32_mut.set(&mut store, Value::I64(20)).is_err()); - - // Set on same type should succeed - global_i32_mut.set(&mut store, Value::I32(20)).unwrap(); - assert_eq!(global_i32_mut.get(&store), Value::I32(20)); - } - - #[wasm_bindgen_test] - fn table_new() { - let mut store = Store::default(); - let table_type = TableType { - ty: Type::FuncRef, - minimum: 0, - maximum: None, - }; - let f = Function::new_typed(&mut store, || {}); - let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f))).unwrap(); - assert_eq!(table.ty(&store), table_type); - - // table.get() - // Anyrefs not yet supported - // let table_type = TableType { - // ty: Type::ExternRef, - // minimum: 0, - // maximum: None, - // }; - // let table = Table::new(&store, table_type, Value::ExternRef(ExternRef::Null))?; - // assert_eq!(*table.ty(&store), table_type); - } - - // Tables are not yet fully supported in Wasm - // Commenting this tests for now - - // #[test] - // #[ignore] - // fn table_get() -> Result<()> { - // let mut store = Store::default(); - // let mut env = FunctionEnv::new(&mut store, ()); - // let table_type = TableType { - // ty: Type::FuncRef, - // minimum: 0, - // maximum: Some(1), - // }; - // let f = Function::new(&mut store, |num: i32| num + 1); - // let table = Table::new(&store, table_type, Value::FuncRef(Some(f.clone())))?; - // assert_eq!(*table.ty(&store), table_type); - // let _elem = table.get(0).unwrap(); - // // assert_eq!(elem.funcref().unwrap(), f); - // Ok(()) - // } - - // #[test] - // #[ignore] - // fn table_set() -> Result<()> { - // // Table set not yet tested - // Ok(()) - // } - - // #[test] - // fn table_grow() -> Result<()> { - // let mut store = Store::default(); - // let mut env = FunctionEnv::new(&mut store, ()); - // let table_type = TableType { - // ty: Type::FuncRef, - // minimum: 0, - // maximum: Some(10), - // }; - // let f = Function::new(&mut store, &env, |num: i32| num + 1); - // let table = Table::new(&store, table_type, Value::FuncRef(Some(f.clone())))?; - // // Growing to a bigger maximum should return None - // let old_len = table.grow(12, Value::FuncRef(Some(f.clone()))); - // assert!(old_len.is_err()); - - // // Growing to a bigger maximum should return None - // let old_len = table.grow(5, Value::FuncRef(Some(f.clone())))?; - // assert_eq!(old_len, 0); - - // Ok(()) - // } - - // #[test] - // #[ignore] - // fn table_copy() -> Result<()> { - // // TODO: table copy test not yet implemented - // Ok(()) - // } - - #[wasm_bindgen_test] - fn memory_new() { - let mut store = Store::default(); - let memory_type = MemoryType { - shared: false, - minimum: Pages(0), - maximum: Some(Pages(10)), - }; - let memory = Memory::new(&mut store, memory_type).unwrap(); - assert_eq!(memory.view(&store).size(), Pages(0)); - assert_eq!(memory.ty(&store), memory_type); - } - - #[wasm_bindgen_test] - fn memory_grow() { - let mut store = Store::default(); - - let desc = MemoryType::new(Pages(10), Some(Pages(16)), false); - let memory = Memory::new(&mut store, desc).unwrap(); - assert_eq!(memory.view(&store).size(), Pages(10)); - - let result = memory.grow(&mut store, Pages(2)).unwrap(); - assert_eq!(result, Pages(10)); - assert_eq!(memory.view(&store).size(), Pages(12)); - - let result = memory.grow(&mut store, Pages(10)); - assert!(result.is_err()); - assert_eq!( - result, - Err(MemoryError::CouldNotGrow { - current: 12.into(), - attempted_delta: 10.into() - }) - ); - } - - #[wasm_bindgen_test] - fn function_new() { - let mut store = Store::default(); - let function = Function::new_typed(&mut store, || {}); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![], vec![]) - ); - let function = Function::new_typed(&mut store, |_a: i32| {}); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![Type::I32], vec![]) - ); - let function = Function::new_typed(&mut store, |_a: i32, _b: i64, _c: f32, _d: f64| {}); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) - ); - let function = Function::new_typed(&mut store, || -> i32 { 1 }); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![], vec![Type::I32]) - ); - let function = - Function::new_typed(&mut store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) - ); - } - - #[wasm_bindgen_test] - fn function_new_env() { - let mut store = Store::default(); - #[derive(Clone)] - struct MyEnv {} - - let my_env = MyEnv {}; - let env = FunctionEnv::new(&mut store, my_env); - - let function = - Function::new_typed_with_env(&mut store, &env, |_: FunctionEnvMut<'_, MyEnv>| {}); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![], vec![]) - ); - let function = Function::new_typed_with_env( - &mut store, - &env, - |_: FunctionEnvMut<'_, MyEnv>, _a: i32| {}, - ); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![Type::I32], vec![]) - ); - let function = Function::new_typed_with_env( - &mut store, - &env, - |_: FunctionEnvMut<'_, MyEnv>, _a: i32, _b: i64, _c: f32, _d: f64| {}, - ); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) - ); - let function = - Function::new_typed_with_env(&mut store, &env, |_: FunctionEnvMut<'_, MyEnv>| -> i32 { - 1 - }); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![], vec![Type::I32]) - ); - let function = Function::new_typed_with_env( - &mut store, - &env, - |_: FunctionEnvMut<'_, MyEnv>| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, - ); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) - ); - } - - #[wasm_bindgen_test] - fn function_new_dynamic() { - let mut store = Store::default(); - - // Using &FunctionType signature - let function_type = FunctionType::new(vec![], vec![]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = FunctionType::new(vec![Type::I32], vec![]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = FunctionType::new(vec![], vec![Type::I32]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - - // Using array signature - let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); - let function = Function::new( - &mut store, - function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).params(), [Type::V128]); - assert_eq!( - function.ty(&store).results(), - [Type::I32, Type::F32, Type::F64] - ); - } - - #[wasm_bindgen_test] - fn function_new_dynamic_env() { - let mut store = Store::default(); - #[derive(Clone)] - struct MyEnv {} - - let my_env = MyEnv {}; - let env = FunctionEnv::new(&mut store, my_env); - - // Using &FunctionType signature - let function_type = FunctionType::new(vec![], vec![]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = FunctionType::new(vec![Type::I32], vec![]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = FunctionType::new(vec![], vec![Type::I32]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - - // Using array signature - let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); - let function = Function::new_with_env( - &mut store, - &env, - function_type, - |_env: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).params(), [Type::V128]); - assert_eq!( - function.ty(&store).results(), - [Type::I32, Type::F32, Type::F64] - ); - } - - #[wasm_bindgen_test] - fn native_function_works() { - let mut store = Store::default(); - let function = Function::new_typed(&mut store, || {}); - let typed_function: TypedFunction<(), ()> = function.typed(&mut store).unwrap(); - let result = typed_function.call(&mut store); - assert!(result.is_ok()); - - let function = Function::new_typed(&mut store, |a: i32| -> i32 { a + 1 }); - let typed_function: TypedFunction = function.typed(&mut store).unwrap(); - assert_eq!(typed_function.call(&mut store, 3).unwrap(), 4); - - // fn rust_abi(a: i32, b: i64, c: f32, d: f64) -> u64 { - // (a as u64 * 1000) + (b as u64 * 100) + (c as u64 * 10) + (d as u64) - // } - // let function = Function::new(&mut store, &env, rust_abi); - // let typed_function: TypedFunction<(i32, i64, f32, f64), u64> = function.native(&mut store).unwrap(); - // assert_eq!(typed_function.call(8, 4, 1.5, 5.).unwrap(), 8415); - - let function = Function::new_typed(&mut store, || -> i32 { 1 }); - let typed_function: TypedFunction<(), i32> = function.typed(&mut store).unwrap(); - assert_eq!(typed_function.call(&mut store).unwrap(), 1); - - let function = Function::new_typed(&mut store, |_a: i32| {}); - let typed_function: TypedFunction = function.typed(&mut store).unwrap(); - assert!(typed_function.call(&mut store, 4).is_ok()); - - // let function = Function::new(&mut store, &env, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); - // let typed_function: TypedFunction<(), (i32, i64, f32, f64)> = function.native(&mut store).unwrap(); - // assert_eq!(typed_function.call().unwrap(), (1, 2, 3.0, 4.0)); - } - - #[wasm_bindgen_test] - fn function_outlives_instance() { - let mut store = Store::default(); - let wat = r#"(module - (type $sum_t (func (param i32 i32) (result i32))) - (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) - local.get $x - local.get $y - i32.add) - (export "sum" (func $sum_f))) - "#; - - let f = { - let module = Module::new(&store, wat).unwrap(); - let instance = Instance::new(&mut store, &module, &imports! {}).unwrap(); - let f = instance.exports.get_function("sum").unwrap(); - - assert_eq!( - f.call(&mut store, &[Val::I32(4), Val::I32(5)]).unwrap(), - vec![Val::I32(9)].into_boxed_slice() - ); - f.clone() - }; - - assert_eq!( - f.call(&mut store, &[Val::I32(4), Val::I32(5)]).unwrap(), - vec![Val::I32(9)].into_boxed_slice() - ); - } -} diff --git a/lib/api/tests/js_instance.rs b/lib/api/tests/js_instance.rs deleted file mode 100644 index 26e1054e62c..00000000000 --- a/lib/api/tests/js_instance.rs +++ /dev/null @@ -1,852 +0,0 @@ -#[cfg(feature = "js")] -mod js { - use anyhow::Result; - use wasm_bindgen_test::*; - use wasmer::*; - - /* - * For debugging, put web_sys in dev dependencies in Cargo.toml with the "console" feature - * on. - * - extern crate web_sys; - - // A macro to provide `println!(..)`-style syntax for `console.log` logging. - macro_rules! log { - ( $( $t:tt )* ) => { - web_sys::console::log_1(&format!( $( $t )* ).into()); - } - } - */ - macro_rules! log { - ( $( $t:tt )* ) => {}; - } - - #[wasm_bindgen_test] - fn test_exported_memory() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (memory (export "mem") 1) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![], - exports: vec![ExternType::Memory(MemoryType::new(Pages(1), None, false))], - }) - .unwrap(); - - let import_object = imports! {}; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let memory = instance.exports.get_memory("mem").unwrap(); - assert!(memory.is_from_store(&store)); - assert_eq!(memory.ty(&store), MemoryType::new(Pages(1), None, false)); - assert_eq!(memory.view(&store).size(), Pages(1)); - assert_eq!(memory.view(&store).data_size(), 65536); - - memory.grow(&mut store, Pages(1)).unwrap(); - assert_eq!(memory.ty(&store), MemoryType::new(Pages(1), None, false)); - assert_eq!(memory.view(&store).size(), Pages(2)); - assert_eq!(memory.view(&store).data_size(), 65536 * 2); - } - - #[wasm_bindgen_test] - fn test_exported_function() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func (export "get_magic") (result i32) - (i32.const 42) - ) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![], - exports: vec![ExternType::Function(FunctionType::new( - vec![], - vec![Type::I32], - ))], - }) - .unwrap(); - - let import_object = imports! {}; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let get_magic = instance.exports.get_function("get_magic").unwrap(); - assert_eq!( - get_magic.ty(&store).clone(), - FunctionType::new(vec![], vec![Type::I32]) - ); - - let expected = vec![Val::I32(42)].into_boxed_slice(); - assert_eq!(get_magic.call(&mut store, &[]).unwrap(), expected); - } - - #[wasm_bindgen_test] - fn test_imports_from_js_object() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) - ) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - exports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - }) - .unwrap(); - - let obj: js_sys::Object = js_sys::Function::new_with_args( - "", - "return { - \"env\": { - \"imported\": function(num) { - console.log(\"Calling `imported`...\"); - var result = num * 2; - console.log(\"Result of `imported`: \", result); - return result; - } - } - };", - ) - .call0(&wasm_bindgen::JsValue::UNDEFINED) - .unwrap() - .into(); - - let import_object = Imports::new_from_js_object(&mut store, &module, obj) - .expect("Can't get imports from js object"); - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let exported = instance.exports.get_function("exported").unwrap(); - - let expected = vec![Val::I32(6)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(3)]).unwrap(), expected); - } - - #[wasm_bindgen_test] - fn test_imported_function_dynamic() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) - ) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - exports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - }) - .unwrap(); - - let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - - let imported = Function::new(&mut store, imported_signature, |args| { - log!("Calling `imported`..."); - let result = args[0].unwrap_i32() * 2; - log!("Result of `imported`: {:?}", result); - Ok(vec![Value::I32(result)]) - }); - - let import_object = imports! { - "env" => { - "imported" => imported, - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let exported = instance.exports.get_function("exported").unwrap(); - - let expected = vec![Val::I32(6)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(3)]).unwrap(), expected); - } - - // We comment it for now because in old versions of Node, only single return values are supported - - // #[wasm_bindgen_test] - // fn test_imported_function_dynamic_multivalue() { - // let mut store = Store::default(); - // let mut module = Module::new( - // &store, - // br#" - // (module - // (func $multivalue (import "env" "multivalue") (param i32 i32) (result i32 i32)) - // (func (export "multivalue") (param i32 i32) (result i32 i32) - // (call $multivalue (local.get 0) (local.get 1)) - // ) - // ) - // "#, - // ) - // .unwrap(); - // module.set_type_hints(ModuleTypeHints { - // imports: vec![ - // ExternType::Function(FunctionType::new( - // vec![Type::I32, Type::I32], - // vec![Type::I32, Type::I32], - // )), - // ], - // exports: vec![ - // ExternType::Function(FunctionType::new( - // vec![Type::I32, Type::I32], - // vec![Type::I32, Type::I32], - // )), - // ], - // }); - - // let multivalue_signature = - // FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32, Type::I32]); - // let multivalue = Function::new(&store, &multivalue_signature, |args| { - // log!("Calling `imported`..."); - // // let result = args[0].unwrap_i32() * ; - // // log!("Result of `imported`: {:?}", result); - // Ok(vec![args[1].clone(), args[0].clone()]) - // }); - - // let import_object = imports! { - // "env" => { - // "multivalue" => multivalue, - // } - // }; - // let instance = Instance::new(&module, &import_object).unwrap(); - - // let exported_multivalue = instance - // .exports - // .get_function("multivalue") - // .unwrap(); - - // let expected = vec![Val::I32(2), Val::I32(3)].into_boxed_slice(); - // assert_eq!( - // exported_multivalue.call(&[Val::I32(3), Val::I32(2)]), - // Ok(expected) - // ); - // } - - #[wasm_bindgen_test] - fn test_imported_function_dynamic_with_env() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) - ) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - exports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - }) - .unwrap(); - - #[derive(Clone)] - struct Env { - multiplier: i32, - } - - let env = FunctionEnv::new(&mut store, Env { multiplier: 3 }); - - let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = - Function::new_with_env(&mut store, &env, &imported_signature, |env, args| { - log!("Calling `imported`..."); - let result = args[0].unwrap_i32() * env.data().multiplier; - log!("Result of `imported`: {:?}", result); - Ok(vec![Value::I32(result)]) - }); - - let import_object = imports! { - "env" => { - "imported" => imported, - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let exported = instance.exports.get_function("exported").unwrap(); - - let expected = vec![Val::I32(9)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(3)]), Ok(expected)); - } - - #[wasm_bindgen_test] - fn test_imported_function_native() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) - ) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - exports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - }) - .unwrap(); - - fn imported_fn(arg: u32) -> u32 { - return arg + 1; - } - - let imported = Function::new_typed(&mut store, imported_fn); - - let import_object = imports! { - "env" => { - "imported" => imported, - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let exported = instance.exports.get_function("exported").unwrap(); - - let expected = vec![Val::I32(5)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); - } - - #[wasm_bindgen_test] - fn test_imported_function_native_with_env() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) - ) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - exports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - }) - .unwrap(); - - #[derive(Clone, Debug)] - struct Env { - multiplier: u32, - } - - fn imported_fn(env: FunctionEnvMut<'_, Env>, arg: u32) -> u32 { - log!("inside imported_fn: env.data is {:?}", env.data()); - // log!("inside call id is {:?}", env.as_store_ref().objects().id); - return env.data().multiplier * arg; - } - - let env = FunctionEnv::new(&mut store, Env { multiplier: 3 }); - - let imported = Function::new_typed_with_env(&mut store, &env, imported_fn); - - let import_object = imports! { - "env" => { - "imported" => imported, - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let exported = instance.exports.get_function("exported").unwrap(); - - let expected = vec![Val::I32(12)].into_boxed_slice(); - env.as_mut(&mut store).multiplier = 3; - assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); - } - - #[wasm_bindgen_test] - fn test_imported_function_native_with_wasmer_env() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) - ) - (memory (export "memory") 1) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - exports: vec![ - ExternType::Function(FunctionType::new(vec![Type::I32], vec![Type::I32])), - ExternType::Memory(MemoryType::new(Pages(1), None, false)), - ], - }) - .unwrap(); - - #[derive(Clone, Debug)] - struct Env { - multiplier: u32, - memory: Option, - } - - fn imported_fn(env: FunctionEnvMut<'_, Env>, arg: u32) -> u32 { - let memory: &Memory = env.data().memory.as_ref().unwrap(); - let memory_val = memory.view(&env).read_u8(0).unwrap(); - return (memory_val as u32) * env.data().multiplier * arg; - } - - let env = FunctionEnv::new( - &mut store, - Env { - multiplier: 3, - memory: None, - }, - ); - let imported = Function::new_typed_with_env(&mut store, &env, imported_fn); - - let import_object = imports! { - "env" => { - "imported" => imported, - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let memory = instance.exports.get_memory("memory").unwrap(); - assert_eq!(memory.view(&store).data_size(), 65536); - let memory_val = memory.view(&store).read_u8(0).unwrap(); - assert_eq!(memory_val, 0); - - memory.view(&store).write_u8(0, 2).unwrap(); - let memory_val = memory.view(&store).read_u8(0).unwrap(); - assert_eq!(memory_val, 2); - - env.as_mut(&mut store).memory = Some(memory.clone()); - - let exported = instance.exports.get_function("exported").unwrap(); - - // It works with the provided memory - let expected = vec![Val::I32(24)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); - - // It works if we update the memory - memory.view(&store).write_u8(0, 3).unwrap(); - let expected = vec![Val::I32(36)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); - } - - #[wasm_bindgen_test] - fn test_unit_native_function_env() { - let mut store = Store::default(); - #[derive(Clone)] - struct Env { - multiplier: u32, - } - - let env = FunctionEnv::new(&mut store, Env { multiplier: 3 }); - - fn imported_fn(env: FunctionEnvMut, args: &[Val]) -> Result, RuntimeError> { - let value = env.data().multiplier * args[0].unwrap_i32() as u32; - return Ok(vec![Val::I32(value as _)]); - } - - let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new_with_env(&mut store, &env, imported_signature, imported_fn); - - let expected = vec![Val::I32(12)].into_boxed_slice(); - assert_eq!(imported.call(&mut store, &[Val::I32(4)]), Ok(expected)); - } - - #[wasm_bindgen_test] - fn test_imported_function_with_wasmer_env() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) - ) - (memory (export "memory") 1) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - exports: vec![ - ExternType::Function(FunctionType::new(vec![Type::I32], vec![Type::I32])), - ExternType::Memory(MemoryType::new(Pages(1), None, false)), - ], - }) - .unwrap(); - - #[derive(Clone, Debug)] - struct Env { - multiplier: u32, - memory: Option, - } - - fn imported_fn( - env: FunctionEnvMut<'_, Env>, - args: &[Val], - ) -> Result, RuntimeError> { - let memory: &Memory = env.data().memory.as_ref().unwrap(); - let memory_val = memory.view(&env).read_u8(0).unwrap(); - let value = (memory_val as u32) * env.data().multiplier * args[0].unwrap_i32() as u32; - return Ok(vec![Val::I32(value as _)]); - } - - let env = FunctionEnv::new( - &mut store, - Env { - multiplier: 3, - memory: None, - }, - ); - - let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new_with_env(&mut store, &env, imported_signature, imported_fn); - - let import_object = imports! { - "env" => { - "imported" => imported, - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let memory = instance.exports.get_memory("memory").unwrap(); - assert_eq!(memory.view(&store).data_size(), 65536); - let memory_val = memory.view(&store).read_u8(0).unwrap(); - assert_eq!(memory_val, 0); - - memory.view(&store).write_u8(0, 2).unwrap(); - let memory_val = memory.view(&store).read_u8(0).unwrap(); - assert_eq!(memory_val, 2); - - env.as_mut(&mut store).memory = Some(memory.clone()); - - let exported = instance.exports.get_function("exported").unwrap(); - - // It works with the provided memory - let expected = vec![Val::I32(24)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); - - // It works if we update the memory - memory.view(&store).write_u8(0, 3).unwrap(); - let expected = vec![Val::I32(36)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); - } - - #[wasm_bindgen_test] - fn test_imported_exported_global() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (global $mut_i32_import (import "" "global") (mut i32)) - (func (export "getGlobal") (result i32) (global.get $mut_i32_import)) - (func (export "incGlobal") (global.set $mut_i32_import ( - i32.add (i32.const 1) (global.get $mut_i32_import) - ))) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Global(GlobalType::new( - ValType::I32, - Mutability::Var, - ))], - exports: vec![ - ExternType::Function(FunctionType::new(vec![], vec![Type::I32])), - ExternType::Function(FunctionType::new(vec![], vec![])), - ], - }) - .unwrap(); - let global = Global::new_mut(&mut store, Value::I32(0)); - let import_object = imports! { - "" => { - "global" => global.clone() - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let get_global = instance.exports.get_function("getGlobal").unwrap(); - assert_eq!( - get_global.call(&mut store, &[]), - Ok(vec![Val::I32(0)].into_boxed_slice()) - ); - - global.set(&mut store, Value::I32(42)).unwrap(); - assert_eq!( - get_global.call(&mut store, &[]), - Ok(vec![Val::I32(42)].into_boxed_slice()) - ); - - let inc_global = instance.exports.get_function("incGlobal").unwrap(); - inc_global.call(&mut store, &[]).unwrap(); - assert_eq!( - get_global.call(&mut store, &[]), - Ok(vec![Val::I32(43)].into_boxed_slice()) - ); - assert_eq!(global.get(&store), Val::I32(43)); - } - - #[wasm_bindgen_test] - fn test_native_function() { - let mut store = Store::default(); - let module = Module::new( - &store, - br#"(module - (func $add (import "env" "sum") (param i32 i32) (result i32)) - (func (export "add_one") (param i32) (result i32) - (call $add (local.get 0) (i32.const 1)) - ) - )"#, - ) - .unwrap(); - - fn sum(a: i32, b: i32) -> i32 { - a + b - } - - let import_object = imports! { - "env" => { - "sum" => Function::new_typed(&mut store, sum), - } - }; - - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let add_one: TypedFunction = instance - .exports - .get_typed_function(&mut store, "add_one") - .unwrap(); - assert_eq!(add_one.call(&mut store, 1), Ok(2)); - } - - #[wasm_bindgen_test] - fn test_panic() { - let mut store = Store::default(); - let module = Module::new( - &store, - br#" - (module - (type $run_t (func (param i32 i32) (result i32))) - (type $early_exit_t (func (param) (result))) - (import "env" "early_exit" (func $early_exit (type $early_exit_t))) - (func $run (type $run_t) (param $x i32) (param $y i32) (result i32) - (call $early_exit) - (i32.add - local.get $x - local.get $y)) - (export "run" (func $run))) - "#, - ) - .unwrap(); - - fn early_exit() { - panic!("Do panic") - } - - let import_object = imports! { - "env" => { - "early_exit" => Function::new_typed(&mut store, early_exit), - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let run_func: TypedFunction<(i32, i32), i32> = instance - .exports - .get_typed_function(&mut store, "run") - .unwrap(); - - assert!( - run_func.call(&mut store, 1, 7).is_err(), - "Expected early termination", - ); - let run_func = instance.exports.get_function("run").unwrap(); - - assert!( - run_func - .call(&mut store, &[Val::I32(1), Val::I32(7)]) - .is_err(), - "Expected early termination", - ); - } - - #[wasm_bindgen_test] - fn test_custom_error() { - let mut store = Store::default(); - let module = Module::new( - &store, - br#" - (module - (type $run_t (func (param i32 i32) (result i32))) - (type $early_exit_t (func (param) (result))) - (import "env" "early_exit" (func $early_exit (type $early_exit_t))) - (func $run (type $run_t) (param $x i32) (param $y i32) (result i32) - (call $early_exit) - (i32.add - local.get $x - local.get $y)) - (export "run" (func $run))) - "#, - ) - .unwrap(); - - use std::fmt; - - #[derive(Debug, Clone, Copy)] - struct ExitCode(u32); - - impl fmt::Display for ExitCode { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.0) - } - } - - impl std::error::Error for ExitCode {} - - fn early_exit() -> Result<(), ExitCode> { - Err(ExitCode(1)) - } - - let import_object = imports! { - "env" => { - "early_exit" => Function::new_typed(&mut store, early_exit), - } - }; - - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - fn test_result(result: Result) { - match result { - Ok(result) => { - assert!( - false, - "Expected early termination with `ExitCode`, found: {:?}", - result - ); - } - Err(e) => { - match e.downcast::() { - // We found the exit code used to terminate execution. - Ok(exit_code) => { - assert_eq!(exit_code.0, 1); - } - Err(e) => { - assert!(false, "Unknown error `{:?}` found. expected `ErrorCode`", e); - } - } - } - } - } - - let run_func: TypedFunction<(i32, i32), i32> = instance - .exports - .get_typed_function(&mut store, "run") - .unwrap(); - test_result(run_func.call(&mut store, 1, 7)); - - let run_func = instance.exports.get_function("run").unwrap(); - test_result(run_func.call(&mut store, &[Val::I32(1), Val::I32(7)])); - } - - #[wasm_bindgen_test] - fn test_start_function_fails() { - let mut store = Store::default(); - let module = Module::new( - &store, - br#" - (module - (func $start_function - (i32.div_u - (i32.const 1) - (i32.const 0) - ) - drop - ) - (start $start_function) - ) - "#, - ) - .unwrap(); - - let import_object = imports! {}; - let result = Instance::new(&mut store, &module, &import_object); - let err = result.unwrap_err(); - assert!(format!("{:?}", err).contains("zero")) - } -} diff --git a/lib/api/tests/js_module.rs b/lib/api/tests/js_module.rs deleted file mode 100644 index 44b525f1ac4..00000000000 --- a/lib/api/tests/js_module.rs +++ /dev/null @@ -1,293 +0,0 @@ -#[cfg(feature = "js")] -mod js { - use js_sys::{Uint8Array, WebAssembly}; - use wasm_bindgen_test::*; - use wasmer::*; - - #[wasm_bindgen_test] - fn module_get_name() { - let store = Store::default(); - let wat = r#"(module)"#; - let module = Module::new(&store, wat).unwrap(); - assert_eq!(module.name(), None); - } - - #[wasm_bindgen_test] - fn module_set_name() { - let store = Store::default(); - let wat = r#"(module $name)"#; - let mut module = Module::new(&store, wat).unwrap(); - - #[cfg(feature = "wasm-types-polyfill")] - assert_eq!(module.name(), Some("name")); - - module.set_name("new_name"); - assert_eq!(module.name(), Some("new_name")); - } - - #[wasm_bindgen_test] - fn module_from_jsmodule() { - let wat = br#"(module $name)"#; - let binary = wat2wasm(wat).unwrap(); - let js_bytes = unsafe { Uint8Array::view(&binary) }; - let js_module = WebAssembly::Module::new(&js_bytes.into()).unwrap(); - let _module: Module = js_module.into(); - } - - #[wasm_bindgen_test] - fn imports() { - let store = Store::default(); - let wat = r#"(module - (import "host" "func" (func)) - (import "host" "memory" (memory 1)) - (import "host" "table" (table 1 anyfunc)) - (import "host" "global" (global i32)) -)"#; - let module = Module::new(&store, wat).unwrap(); - assert_eq!( - module.imports().collect::>(), - vec![ - ImportType::new( - "host", - "func", - ExternType::Function(FunctionType::new(vec![], vec![])) - ), - ImportType::new( - "host", - "memory", - ExternType::Memory(MemoryType::new(Pages(1), None, false)) - ), - ImportType::new( - "host", - "table", - ExternType::Table(TableType::new(Type::FuncRef, 1, None)) - ), - ImportType::new( - "host", - "global", - ExternType::Global(GlobalType::new(Type::I32, Mutability::Const)) - ) - ] - ); - - // Now we test the iterators - assert_eq!( - module.imports().functions().collect::>(), - vec![ImportType::new( - "host", - "func", - FunctionType::new(vec![], vec![]) - ),] - ); - assert_eq!( - module.imports().memories().collect::>(), - vec![ImportType::new( - "host", - "memory", - MemoryType::new(Pages(1), None, false) - ),] - ); - assert_eq!( - module.imports().tables().collect::>(), - vec![ImportType::new( - "host", - "table", - TableType::new(Type::FuncRef, 1, None) - ),] - ); - assert_eq!( - module.imports().globals().collect::>(), - vec![ImportType::new( - "host", - "global", - GlobalType::new(Type::I32, Mutability::Const) - ),] - ); - } - - #[wasm_bindgen_test] - fn exports() { - let store = Store::default(); - let wat = r#"(module - (func (export "func") nop) - (memory (export "memory") 2) - (table (export "table") 2 funcref) - (global (export "global") i32 (i32.const 0)) -)"#; - let mut module = Module::new(&store, wat).unwrap(); - module - .set_type_hints(ModuleTypeHints { - exports: vec![ - ExternType::Function(FunctionType::new(vec![], vec![])), - ExternType::Memory(MemoryType::new(Pages(2), None, false)), - ExternType::Table(TableType::new(Type::FuncRef, 2, None)), - ExternType::Global(GlobalType::new(Type::I32, Mutability::Const)), - ], - imports: vec![], - }) - .unwrap(); - assert_eq!( - module.exports().collect::>(), - vec![ - ExportType::new( - "func", - ExternType::Function(FunctionType::new(vec![], vec![])) - ), - ExportType::new( - "memory", - ExternType::Memory(MemoryType::new(Pages(2), None, false)) - ), - ExportType::new( - "table", - ExternType::Table(TableType::new(Type::FuncRef, 2, None)) - ), - ExportType::new( - "global", - ExternType::Global(GlobalType::new(Type::I32, Mutability::Const)) - ) - ] - ); - - // Now we test the iterators - assert_eq!( - module.exports().functions().collect::>(), - vec![ExportType::new("func", FunctionType::new(vec![], vec![])),] - ); - assert_eq!( - module.exports().memories().collect::>(), - vec![ExportType::new( - "memory", - MemoryType::new(Pages(2), None, false) - ),] - ); - assert_eq!( - module.exports().tables().collect::>(), - vec![ExportType::new( - "table", - TableType::new(Type::FuncRef, 2, None) - ),] - ); - assert_eq!( - module.exports().globals().collect::>(), - vec![ExportType::new( - "global", - GlobalType::new(Type::I32, Mutability::Const) - ),] - ); - } - - // Test commented because it doesn't work in old versions of Node - // which makes the CI to fail. - - // #[wasm_bindgen_test] - // fn calling_host_functions_with_negative_values_works() { - // let mut store = Store::default(); - // let wat = r#"(module - // (import "host" "host_func1" (func (param i64))) - // (import "host" "host_func2" (func (param i32))) - // (import "host" "host_func3" (func (param i64))) - // (import "host" "host_func4" (func (param i32))) - // (import "host" "host_func5" (func (param i32))) - // (import "host" "host_func6" (func (param i32))) - // (import "host" "host_func7" (func (param i32))) - // (import "host" "host_func8" (func (param i32))) - - // (func (export "call_host_func1") - // (call 0 (i64.const -1))) - // (func (export "call_host_func2") - // (call 1 (i32.const -1))) - // (func (export "call_host_func3") - // (call 2 (i64.const -1))) - // (func (export "call_host_func4") - // (call 3 (i32.const -1))) - // (func (export "call_host_func5") - // (call 4 (i32.const -1))) - // (func (export "call_host_func6") - // (call 5 (i32.const -1))) - // (func (export "call_host_func7") - // (call 6 (i32.const -1))) - // (func (export "call_host_func8") - // (call 7 (i32.const -1))) - // )"#; - // let module = Module::new(&store, wat).unwrap(); - // let imports = imports! { - // "host" => { - // "host_func1" => Function::new_typed(&store, |p: u64| { - // println!("host_func1: Found number {}", p); - // assert_eq!(p, u64::max_value()); - // }), - // "host_func2" => Function::new_typed(&store, |p: u32| { - // println!("host_func2: Found number {}", p); - // assert_eq!(p, u32::max_value()); - // }), - // "host_func3" => Function::new_typed(&store, |p: i64| { - // println!("host_func3: Found number {}", p); - // assert_eq!(p, -1); - // }), - // "host_func4" => Function::new_typed(&store, |p: i32| { - // println!("host_func4: Found number {}", p); - // assert_eq!(p, -1); - // }), - // "host_func5" => Function::new_typed(&store, |p: i16| { - // println!("host_func5: Found number {}", p); - // assert_eq!(p, -1); - // }), - // "host_func6" => Function::new_typed(&store, |p: u16| { - // println!("host_func6: Found number {}", p); - // assert_eq!(p, u16::max_value()); - // }), - // "host_func7" => Function::new_typed(&store, |p: i8| { - // println!("host_func7: Found number {}", p); - // assert_eq!(p, -1); - // }), - // "host_func8" => Function::new_typed(&store, |p: u8| { - // println!("host_func8: Found number {}", p); - // assert_eq!(p, u8::max_value()); - // }), - // } - // }; - // let instance = Instance::new(&module, &imports).unwrap(); - - // let f1: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func1") - // .unwrap(); - // let f2: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func2") - // .unwrap(); - // let f3: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func3") - // .unwrap(); - // let f4: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func4") - // .unwrap(); - // let f5: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func5") - // .unwrap(); - // let f6: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func6") - // .unwrap(); - // let f7: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func7") - // .unwrap(); - // let f8: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func8") - // .unwrap(); - - // f1.call().unwrap(); - // f2.call().unwrap(); - // f3.call().unwrap(); - // f4.call().unwrap(); - // f5.call().unwrap(); - // f6.call().unwrap(); - // f7.call().unwrap(); - // f8.call().unwrap(); - // } -} diff --git a/lib/api/tests/module.rs b/lib/api/tests/module.rs new file mode 100644 index 00000000000..4eb779cc735 --- /dev/null +++ b/lib/api/tests/module.rs @@ -0,0 +1,297 @@ +use anyhow::Result; +#[cfg(feature = "js")] +use wasm_bindgen_test::*; + +use wasmer::*; + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn module_get_name_js() { + module_get_name().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn module_get_name() -> Result<()> { + let store = Store::default(); + let wat = r#"(module)"#; + let module = Module::new(&store, wat)?; + assert_eq!(module.name(), None); + + Ok(()) +} + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn module_set_name_js() { + module_set_name().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn module_set_name() -> Result<()> { + let store = Store::default(); + let wat = r#"(module $name)"#; + let mut module = Module::new(&store, wat)?; + assert_eq!(module.name(), Some("name")); + + module.set_name("new_name"); + assert_eq!(module.name(), Some("new_name")); + + Ok(()) +} + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn imports_js() { + imports().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn imports() -> Result<()> { + let store = Store::default(); + let wat = r#"(module +(import "host" "func" (func)) +(import "host" "memory" (memory 1)) +(import "host" "table" (table 1 anyfunc)) +(import "host" "global" (global i32)) +)"#; + let module = Module::new(&store, wat)?; + assert_eq!( + module.imports().collect::>(), + vec![ + ImportType::new( + "host", + "func", + ExternType::Function(FunctionType::new(vec![], vec![])) + ), + ImportType::new( + "host", + "memory", + ExternType::Memory(MemoryType::new(Pages(1), None, false)) + ), + ImportType::new( + "host", + "table", + ExternType::Table(TableType::new(Type::FuncRef, 1, None)) + ), + ImportType::new( + "host", + "global", + ExternType::Global(GlobalType::new(Type::I32, Mutability::Const)) + ) + ] + ); + + // Now we test the iterators + assert_eq!( + module.imports().functions().collect::>(), + vec![ImportType::new( + "host", + "func", + FunctionType::new(vec![], vec![]) + ),] + ); + assert_eq!( + module.imports().memories().collect::>(), + vec![ImportType::new( + "host", + "memory", + MemoryType::new(Pages(1), None, false) + ),] + ); + assert_eq!( + module.imports().tables().collect::>(), + vec![ImportType::new( + "host", + "table", + TableType::new(Type::FuncRef, 1, None) + ),] + ); + assert_eq!( + module.imports().globals().collect::>(), + vec![ImportType::new( + "host", + "global", + GlobalType::new(Type::I32, Mutability::Const) + ),] + ); + Ok(()) +} + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn exports_js() { + exports().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn exports() -> Result<()> { + let store = Store::default(); + let wat = r#"(module +(func (export "func") nop) +(memory (export "memory") 1) +(table (export "table") 1 funcref) +(global (export "global") i32 (i32.const 0)) +)"#; + let module = Module::new(&store, wat)?; + assert_eq!( + module.exports().collect::>(), + vec![ + ExportType::new( + "func", + ExternType::Function(FunctionType::new(vec![], vec![])) + ), + ExportType::new( + "memory", + ExternType::Memory(MemoryType::new(Pages(1), None, false)) + ), + ExportType::new( + "table", + ExternType::Table(TableType::new(Type::FuncRef, 1, None)) + ), + ExportType::new( + "global", + ExternType::Global(GlobalType::new(Type::I32, Mutability::Const)) + ) + ] + ); + + // Now we test the iterators + assert_eq!( + module.exports().functions().collect::>(), + vec![ExportType::new("func", FunctionType::new(vec![], vec![])),] + ); + assert_eq!( + module.exports().memories().collect::>(), + vec![ExportType::new( + "memory", + MemoryType::new(Pages(1), None, false) + ),] + ); + assert_eq!( + module.exports().tables().collect::>(), + vec![ExportType::new( + "table", + TableType::new(Type::FuncRef, 1, None) + ),] + ); + assert_eq!( + module.exports().globals().collect::>(), + vec![ExportType::new( + "global", + GlobalType::new(Type::I32, Mutability::Const) + ),] + ); + Ok(()) +} + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn calling_host_functions_with_negative_values_works_js() { + calling_host_functions_with_negative_values_works().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn calling_host_functions_with_negative_values_works() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module +(import "host" "host_func1" (func (param i64))) +(import "host" "host_func2" (func (param i32))) +(import "host" "host_func3" (func (param i64))) +(import "host" "host_func4" (func (param i32))) +(import "host" "host_func5" (func (param i32))) +(import "host" "host_func6" (func (param i32))) +(import "host" "host_func7" (func (param i32))) +(import "host" "host_func8" (func (param i32))) + +(func (export "call_host_func1") + (call 0 (i64.const -1))) +(func (export "call_host_func2") + (call 1 (i32.const -1))) +(func (export "call_host_func3") + (call 2 (i64.const -1))) +(func (export "call_host_func4") + (call 3 (i32.const -1))) +(func (export "call_host_func5") + (call 4 (i32.const -1))) +(func (export "call_host_func6") + (call 5 (i32.const -1))) +(func (export "call_host_func7") + (call 6 (i32.const -1))) +(func (export "call_host_func8") + (call 7 (i32.const -1))) +)"#; + let module = Module::new(&store, wat)?; + let imports = imports! { + "host" => { + "host_func1" => Function::new_typed(&mut store, |p: u64| { + println!("host_func1: Found number {}", p); + assert_eq!(p, u64::max_value()); + }), + "host_func2" => Function::new_typed(&mut store, |p: u32| { + println!("host_func2: Found number {}", p); + assert_eq!(p, u32::max_value()); + }), + "host_func3" => Function::new_typed(&mut store, |p: i64| { + println!("host_func3: Found number {}", p); + assert_eq!(p, -1); + }), + "host_func4" => Function::new_typed(&mut store, |p: i32| { + println!("host_func4: Found number {}", p); + assert_eq!(p, -1); + }), + "host_func5" => Function::new_typed(&mut store, |p: i16| { + println!("host_func5: Found number {}", p); + assert_eq!(p, -1); + }), + "host_func6" => Function::new_typed(&mut store, |p: u16| { + println!("host_func6: Found number {}", p); + assert_eq!(p, u16::max_value()); + }), + "host_func7" => Function::new_typed(&mut store, |p: i8| { + println!("host_func7: Found number {}", p); + assert_eq!(p, -1); + }), + "host_func8" => Function::new_typed(&mut store, |p: u8| { + println!("host_func8: Found number {}", p); + assert_eq!(p, u8::max_value()); + }), + } + }; + let instance = Instance::new(&mut store, &module, &imports)?; + + let f1: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func1")?; + let f2: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func2")?; + let f3: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func3")?; + let f4: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func4")?; + let f5: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func5")?; + let f6: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func6")?; + let f7: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func7")?; + let f8: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func8")?; + + f1.call(&mut store)?; + f2.call(&mut store)?; + f3.call(&mut store)?; + f4.call(&mut store)?; + f5.call(&mut store)?; + f6.call(&mut store)?; + f7.call(&mut store)?; + f8.call(&mut store)?; + + Ok(()) +} \ No newline at end of file diff --git a/lib/api/tests/reference_types.rs b/lib/api/tests/reference_types.rs new file mode 100644 index 00000000000..9acf9f3be0e --- /dev/null +++ b/lib/api/tests/reference_types.rs @@ -0,0 +1,551 @@ +use anyhow::Result; +#[cfg(feature = "js")] +use wasm_bindgen_test::*; + +use wasmer::*; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn func_ref_passed_and_returned_js() { + func_ref_passed_and_returned().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn func_ref_passed_and_returned() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module +(import "env" "func_ref_identity" (func (param funcref) (result funcref))) +(type $ret_i32_ty (func (result i32))) +(table $table (export "table") 2 2 funcref) + +(func (export "run") (param) (result funcref) + (call 0 (ref.null func))) +(func (export "call_set_value") (param $fr funcref) (result i32) + (table.set $table (i32.const 0) (local.get $fr)) + (call_indirect $table (type $ret_i32_ty) (i32.const 0))) +)"#; + let module = Module::new(&store, wat)?; + #[derive(Clone, Debug)] + pub struct Env(Arc); + let env = Env(Arc::new(AtomicBool::new(false))); + let env = FunctionEnv::new(&mut store, env); + let imports = imports! { + "env" => { + "func_ref_identity" => Function::new_with_env(&mut store, &env, FunctionType::new([Type::FuncRef], [Type::FuncRef]), |_env: FunctionEnvMut, values: &[Value]| -> Result, _> { + Ok(vec![values[0].clone()]) + }) + }, + }; + + let instance = Instance::new(&mut store, &module, &imports)?; + + let f: &Function = instance.exports.get_function("run")?; + let results = f.call(&mut store, &[]).unwrap(); + if let Value::FuncRef(fr) = &results[0] { + assert!(fr.is_none()); + } else { + panic!("funcref not found!"); + } + + let func_to_call = + Function::new_typed_with_env(&mut store, &env, |mut env: FunctionEnvMut| -> i32 { + env.data_mut().0.store(true, Ordering::SeqCst); + 343 + }); + let call_set_value: &Function = instance.exports.get_function("call_set_value")?; + let results: Box<[Value]> = + call_set_value.call(&mut store, &[Value::FuncRef(Some(func_to_call))])?; + assert!(env + .as_mut(&mut store.as_store_mut()) + .0 + .load(Ordering::SeqCst)); + assert_eq!(&*results, &[Value::I32(343)]); + + Ok(()) +} + + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn func_ref_passed_and_called_js() { + func_ref_passed_and_called().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn func_ref_passed_and_called() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module +(func $func_ref_call (import "env" "func_ref_call") (param funcref) (result i32)) +(type $ret_i32_ty (func (result i32))) +(table $table (export "table") 2 2 funcref) + +(func $product (param $x i32) (param $y i32) (result i32) + (i32.mul (local.get $x) (local.get $y))) +;; TODO: figure out exactly why this statement is needed +(elem declare func $product) +(func (export "call_set_value") (param $fr funcref) (result i32) + (table.set $table (i32.const 0) (local.get $fr)) + (call_indirect $table (type $ret_i32_ty) (i32.const 0))) +(func (export "call_func") (param $fr funcref) (result i32) + (call $func_ref_call (local.get $fr))) +(func (export "call_host_func_with_wasm_func") (result i32) + (call $func_ref_call (ref.func $product))) +)"#; + let module = Module::new(&store, wat)?; + let env = FunctionEnv::new(&mut store, ()); + fn func_ref_call( + mut env: FunctionEnvMut<()>, + values: &[Value], + ) -> Result, RuntimeError> { + // TODO: look into `Box<[Value]>` being returned breakage + let f = values[0].unwrap_funcref().as_ref().unwrap(); + let f: TypedFunction<(i32, i32), i32> = f.typed(&mut env)?; + Ok(vec![Value::I32(f.call(&mut env, 7, 9)?)]) + } + + let imports = imports! { + "env" => { + "func_ref_call" => Function::new_with_env( + &mut store, + &env, + FunctionType::new([Type::FuncRef], [Type::I32]), + func_ref_call + ), + // "func_ref_call_native" => Function::new_native(&mut store, |f: Function| -> Result { + // let f: TypedFunction::<(i32, i32), i32> = f.typed(&mut store)?; + // f.call(&mut store, 7, 9) + // }) + }, + }; + + let instance = Instance::new(&mut store, &module, &imports)?; + { + fn sum(a: i32, b: i32) -> i32 { + a + b + } + let sum_func = Function::new_typed(&mut store, sum); + + let call_func: &Function = instance.exports.get_function("call_func")?; + let result = call_func.call(&mut store, &[Value::FuncRef(Some(sum_func))])?; + assert_eq!(result[0].unwrap_i32(), 16); + } + + { + let f: TypedFunction<(), i32> = instance + .exports + .get_typed_function(&mut store, "call_host_func_with_wasm_func")?; + let result = f.call(&mut store)?; + assert_eq!(result, 63); + } + + Ok(()) +} + + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn extern_ref_passed_and_returned_js() { + extern_ref_passed_and_returned().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn extern_ref_passed_and_returned() -> Result<()> { + use std::collections::HashMap; + let mut store = Store::default(); + let wat = r#"(module + (func $extern_ref_identity (import "env" "extern_ref_identity") (param externref) (result externref)) + (func $extern_ref_identity_native (import "env" "extern_ref_identity_native") (param externref) (result externref)) + (func $get_new_extern_ref (import "env" "get_new_extern_ref") (result externref)) + (func $get_new_extern_ref_native (import "env" "get_new_extern_ref_native") (result externref)) + + (func (export "run") (param) (result externref) + (call $extern_ref_identity (ref.null extern))) + (func (export "run_native") (param) (result externref) + (call $extern_ref_identity_native (ref.null extern))) + (func (export "get_hashmap") (param) (result externref) + (call $get_new_extern_ref)) + (func (export "get_hashmap_native") (param) (result externref) + (call $get_new_extern_ref_native)) +)"#; + let module = Module::new(&store, wat)?; + let env = FunctionEnv::new(&mut store, ()); + let imports = imports! { + "env" => { + "extern_ref_identity" => Function::new_with_env(&mut store, &env, FunctionType::new([Type::ExternRef], [Type::ExternRef]), |_env, values| -> Result, _> { + Ok(vec![values[0].clone()]) + }), + "extern_ref_identity_native" => Function::new_typed(&mut store, |er: Option| -> Option { + er + }), + "get_new_extern_ref" => Function::new_with_env(&mut store, &env, FunctionType::new([], [Type::ExternRef]), |mut env, _| -> Result, _> { + let inner = + [("hello".to_string(), "world".to_string()), + ("color".to_string(), "orange".to_string())] + .iter() + .cloned() + .collect::>(); + let new_extern_ref = ExternRef::new(&mut env, inner); + Ok(vec![Value::ExternRef(Some(new_extern_ref))]) + }), + "get_new_extern_ref_native" => Function::new_typed_with_env(&mut store, &env, |mut env: FunctionEnvMut<()>| -> Option { + let inner = + [("hello".to_string(), "world".to_string()), + ("color".to_string(), "orange".to_string())] + .iter() + .cloned() + .collect::>(); + Some(ExternRef::new(&mut env.as_store_mut(), inner)) + }) + }, + }; + + let instance = Instance::new(&mut store, &module, &imports)?; + for run in &["run", "run_native"] { + let f: &Function = instance.exports.get_function(run)?; + let results = f.call(&mut store, &[]).unwrap(); + if let Value::ExternRef(er) = &results[0] { + assert!(er.is_none()); + } else { + panic!("result is not an extern ref!"); + } + + let f: TypedFunction<(), Option> = + instance.exports.get_typed_function(&store, run)?; + let result: Option = f.call(&mut store)?; + assert!(result.is_none()); + } + + for get_hashmap in &["get_hashmap", "get_hashmap_native"] { + let f: &Function = instance.exports.get_function(get_hashmap)?; + let results = f.call(&mut store, &[]).unwrap(); + if let Value::ExternRef(er) = &results[0] { + let inner: &HashMap = + er.as_ref().unwrap().downcast(&mut store).unwrap(); + assert_eq!(inner["hello"], "world"); + assert_eq!(inner["color"], "orange"); + } else { + panic!("result is not an extern ref!"); + } + + let f: TypedFunction<(), Option> = + instance.exports.get_typed_function(&store, get_hashmap)?; + + let result: Option = f.call(&mut store)?; + let inner: &HashMap = result.unwrap().downcast(&mut store).unwrap(); + assert_eq!(inner["hello"], "world"); + assert_eq!(inner["color"], "orange"); + } + + Ok(()) +} + + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn extern_ref_ref_counting_basic_js() { + extern_ref_ref_counting_basic().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn extern_ref_ref_counting_basic() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module + (func (export "drop") (param $er externref) (result) + (drop (local.get $er))) +)"#; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&mut store, &module, &imports! {})?; + let f: TypedFunction, ()> = + instance.exports.get_typed_function(&store, "drop")?; + + let er = ExternRef::new(&mut store, 3u32); + f.call(&mut store, Some(er.clone()))?; + + let tmp: Option<&u32> = er.downcast(&mut store); + assert_eq!(tmp.unwrap(), &3); + + Ok(()) +} + + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn refs_in_globals_js() { + refs_in_globals().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn refs_in_globals() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module + (global $er_global (export "er_global") (mut externref) (ref.null extern)) + (global $fr_global (export "fr_global") (mut funcref) (ref.null func)) + (global $fr_immutable_global (export "fr_immutable_global") funcref (ref.func $hello)) + (func $hello (param) (result i32) + (i32.const 73)) +)"#; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&mut store, &module, &imports! {})?; + { + let er_global: &Global = instance.exports.get_global("er_global")?; + + if let Value::ExternRef(er) = er_global.get(&mut store) { + assert!(er.is_none()); + } else { + panic!("Did not find extern ref in the global"); + } + let extref = Some(ExternRef::new(&mut store, 3u32)); + er_global.set(&mut store, Value::ExternRef(extref))?; + + if let Value::ExternRef(er) = er_global.get(&mut store) { + let tmp: Option<&u32> = er.unwrap().downcast(&mut store); + assert_eq!(tmp.unwrap(), &3); + } else { + panic!("Did not find extern ref in the global"); + } + } + + { + let fr_global: &Global = instance.exports.get_global("fr_immutable_global")?; + + if let Value::FuncRef(Some(f)) = fr_global.get(&mut store) { + let native_func: TypedFunction<(), u32> = f.typed(&mut store)?; + assert_eq!(native_func.call(&mut store)?, 73); + } else { + panic!("Did not find non-null func ref in the global"); + } + } + + { + let fr_global: &Global = instance.exports.get_global("fr_global")?; + + if let Value::FuncRef(None) = fr_global.get(&mut store) { + } else { + panic!("Did not find a null func ref in the global"); + } + + let f = Function::new_typed(&mut store, |arg1: i32, arg2: i32| -> i32 { arg1 + arg2 }); + + fr_global.set(&mut store, Value::FuncRef(Some(f)))?; + + if let Value::FuncRef(Some(f)) = fr_global.get(&mut store) { + let native: TypedFunction<(i32, i32), i32> = f.typed(&mut store)?; + assert_eq!(native.call(&mut store, 5, 7)?, 12); + } else { + panic!("Did not find extern ref in the global"); + } + } + + Ok(()) +} + + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn extern_ref_ref_counting_table_basic_js() { + extern_ref_ref_counting_table_basic().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn extern_ref_ref_counting_table_basic() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module + (global $global (export "global") (mut externref) (ref.null extern)) + (table $table (export "table") 4 4 externref) + (func $insert (param $er externref) (param $idx i32) + (table.set $table (local.get $idx) (local.get $er))) + (func $intermediate (param $er externref) (param $idx i32) + (call $insert (local.get $er) (local.get $idx))) + (func $insert_into_table (export "insert_into_table") (param $er externref) (param $idx i32) (result externref) + (call $intermediate (local.get $er) (local.get $idx)) + (local.get $er)) +)"#; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&mut store, &module, &imports! {})?; + + let f: TypedFunction<(Option, i32), Option> = instance + .exports + .get_typed_function(&mut store, "insert_into_table")?; + + let er = ExternRef::new(&mut store, 3usize); + + let er = f.call(&mut store, Some(er), 1)?; + assert!(er.is_some()); + + let table: &Table = instance.exports.get_table("table")?; + + { + let er2 = table.get(&mut store, 1).unwrap(); + let er2 = er2.externref().unwrap(); + assert!(er2.is_some()); + } + + assert!(er.is_some()); + table.set(&mut store, 1, Value::ExternRef(None))?; + + assert!(er.is_some()); + + Ok(()) +} + + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn extern_ref_ref_counting_global_basic_js() { + extern_ref_ref_counting_global_basic().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn extern_ref_ref_counting_global_basic() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module + (global $global (export "global") (mut externref) (ref.null extern)) + (func $get_from_global (export "get_from_global") (result externref) + (drop (global.get $global)) + (global.get $global)) +)"#; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&mut store, &module, &imports! {})?; + + let global: &Global = instance.exports.get_global("global")?; + { + let er = ExternRef::new(&mut store, 3usize); + global.set(&mut store, Value::ExternRef(Some(er.clone())))?; + } + let get_from_global: TypedFunction<(), Option> = instance + .exports + .get_typed_function(&mut store, "get_from_global")?; + + let er = get_from_global.call(&mut store)?; + assert!(er.is_some()); + global.set(&mut store, Value::ExternRef(None))?; + assert!(er.is_some()); + + Ok(()) +} + + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn extern_ref_ref_counting_traps_js() { + extern_ref_ref_counting_traps().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn extern_ref_ref_counting_traps() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module + (func $pass_er (export "pass_extern_ref") (param externref) + (local.get 0) + (unreachable)) +)"#; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&mut store, &module, &imports! {})?; + + let pass_extern_ref: TypedFunction, ()> = instance + .exports + .get_typed_function(&mut store, "pass_extern_ref")?; + + let er = ExternRef::new(&mut store, 3usize); + + let result = pass_extern_ref.call(&mut store, Some(er.clone())); + assert!(result.is_err()); + + Ok(()) +} + + +#[cfg(feature = "js")] +#[cfg_attr(feature = "js", wasm_bindgen_test)] +fn extern_ref_ref_counting_table_instructions_js() { + extern_ref_ref_counting_table_instructions().unwrap(); +} + +#[cfg_attr(feature = "sys", test)] +fn extern_ref_ref_counting_table_instructions() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module + (table $table1 (export "table1") 2 12 externref) + (table $table2 (export "table2") 6 12 externref) + (func $grow_table_with_ref (export "grow_table_with_ref") (param $er externref) (param $size i32) (result i32) + (table.grow $table1 (local.get $er) (local.get $size))) + (func $fill_table_with_ref (export "fill_table_with_ref") (param $er externref) (param $start i32) (param $end i32) + (table.fill $table1 (local.get $start) (local.get $er) (local.get $end))) + (func $copy_into_table2 (export "copy_into_table2") + (table.copy $table2 $table1 (i32.const 0) (i32.const 0) (i32.const 4))) +)"#; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&mut store, &module, &imports! {})?; + + let grow_table_with_ref: TypedFunction<(Option, i32), i32> = instance + .exports + .get_typed_function(&mut store, "grow_table_with_ref")?; + let fill_table_with_ref: TypedFunction<(Option, i32, i32), ()> = instance + .exports + .get_typed_function(&mut store, "fill_table_with_ref")?; + let copy_into_table2: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "copy_into_table2")?; + let table1: &Table = instance.exports.get_table("table1")?; + let table2: &Table = instance.exports.get_table("table2")?; + + let er1 = ExternRef::new(&mut store, 3usize); + let er2 = ExternRef::new(&mut store, 5usize); + let er3 = ExternRef::new(&mut store, 7usize); + { + let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 0)?; + assert_eq!(result, 2); + + let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 10_000)?; + assert_eq!(result, -1); + + let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 8)?; + assert_eq!(result, 2); + + for i in 2..10 { + let v = table1.get(&mut store, i); + let e = v.as_ref().unwrap().unwrap_externref(); + let e_val: Option<&usize> = e.as_ref().unwrap().downcast(&mut store); + assert_eq!(*e_val.unwrap(), 3); + } + } + + { + fill_table_with_ref.call(&mut store, Some(er2.clone()), 0, 2)?; + } + + { + table2.set(&mut store, 0, Value::ExternRef(Some(er3.clone())))?; + table2.set(&mut store, 1, Value::ExternRef(Some(er3.clone())))?; + table2.set(&mut store, 2, Value::ExternRef(Some(er3.clone())))?; + table2.set(&mut store, 3, Value::ExternRef(Some(er3.clone())))?; + table2.set(&mut store, 4, Value::ExternRef(Some(er3.clone())))?; + } + + { + copy_into_table2.call(&mut store)?; + for i in 1..5 { + let v = table2.get(&mut store, i); + let e = v.as_ref().unwrap().unwrap_externref(); + let value: &usize = e.as_ref().unwrap().downcast(&mut store).unwrap(); + match i { + 0 | 1 => assert_eq!(*value, 5), + 4 => assert_eq!(*value, 7), + _ => assert_eq!(*value, 3), + } + } + } + + { + for i in 0..table1.size(&mut store) { + table1.set(&mut store, i, Value::ExternRef(None))?; + } + for i in 0..table2.size(&mut store) { + table2.set(&mut store, i, Value::ExternRef(None))?; + } + } + + Ok(()) +} \ No newline at end of file diff --git a/lib/api/tests/sys_externals.rs b/lib/api/tests/sys_externals.rs deleted file mode 100644 index 5899ee3ab26..00000000000 --- a/lib/api/tests/sys_externals.rs +++ /dev/null @@ -1,519 +0,0 @@ -#[cfg(feature = "sys")] -mod sys { - use anyhow::Result; - use wasmer::FunctionEnv; - use wasmer::*; - - #[test] - fn global_new() -> Result<()> { - let mut store = Store::default(); - let global = Global::new(&mut store, Value::I32(10)); - assert_eq!( - global.ty(&mut store), - GlobalType { - ty: Type::I32, - mutability: Mutability::Const - } - ); - - let global_mut = Global::new_mut(&mut store, Value::I32(10)); - assert_eq!( - global_mut.ty(&mut store), - GlobalType { - ty: Type::I32, - mutability: Mutability::Var - } - ); - - Ok(()) - } - - #[test] - fn global_get() -> Result<()> { - let mut store = Store::default(); - let global_i32 = Global::new(&mut store, Value::I32(10)); - assert_eq!(global_i32.get(&mut store), Value::I32(10)); - let global_i64 = Global::new(&mut store, Value::I64(20)); - assert_eq!(global_i64.get(&mut store), Value::I64(20)); - let global_f32 = Global::new(&mut store, Value::F32(10.0)); - assert_eq!(global_f32.get(&mut store), Value::F32(10.0)); - let global_f64 = Global::new(&mut store, Value::F64(20.0)); - assert_eq!(global_f64.get(&mut store), Value::F64(20.0)); - - Ok(()) - } - - #[test] - fn global_set() -> Result<()> { - let mut store = Store::default(); - let global_i32 = Global::new(&mut store, Value::I32(10)); - // Set on a constant should error - assert!(global_i32.set(&mut store, Value::I32(20)).is_err()); - - let global_i32_mut = Global::new_mut(&mut store, Value::I32(10)); - // Set on different type should error - assert!(global_i32_mut.set(&mut store, Value::I64(20)).is_err()); - - // Set on same type should succeed - global_i32_mut.set(&mut store, Value::I32(20))?; - assert_eq!(global_i32_mut.get(&mut store), Value::I32(20)); - - Ok(()) - } - - #[test] - fn table_new() -> Result<()> { - let mut store = Store::default(); - let table_type = TableType { - ty: Type::FuncRef, - minimum: 0, - maximum: None, - }; - let f = Function::new_typed(&mut store, || {}); - let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f)))?; - assert_eq!(table.ty(&mut store), table_type); - - // Anyrefs not yet supported - // let table_type = TableType { - // ty: Type::ExternRef, - // minimum: 0, - // maximum: None, - // }; - // let table = Table::new(&store, table_type, Value::ExternRef(ExternRef::Null))?; - // assert_eq!(*table.ty(), table_type); - - Ok(()) - } - - #[test] - #[ignore] - fn table_get() -> Result<()> { - let mut store = Store::default(); - let table_type = TableType { - ty: Type::FuncRef, - minimum: 0, - maximum: Some(1), - }; - let f = Function::new_typed(&mut store, |num: i32| num + 1); - let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f)))?; - assert_eq!(table.ty(&mut store), table_type); - let _elem = table.get(&mut store, 0).unwrap(); - // assert_eq!(elem.funcref().unwrap(), f); - Ok(()) - } - - #[test] - #[ignore] - fn table_set() -> Result<()> { - // Table set not yet tested - Ok(()) - } - - #[test] - fn table_grow() -> Result<()> { - let mut store = Store::default(); - let table_type = TableType { - ty: Type::FuncRef, - minimum: 0, - maximum: Some(10), - }; - let f = Function::new_typed(&mut store, |num: i32| num + 1); - let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f.clone())))?; - // Growing to a bigger maximum should return None - let old_len = table.grow(&mut store, 12, Value::FuncRef(Some(f.clone()))); - assert!(old_len.is_err()); - - // Growing to a bigger maximum should return None - let old_len = table.grow(&mut store, 5, Value::FuncRef(Some(f)))?; - assert_eq!(old_len, 0); - - Ok(()) - } - - #[test] - #[ignore] - fn table_copy() -> Result<()> { - // TODO: table copy test not yet implemented - Ok(()) - } - - #[test] - fn memory_new() -> Result<()> { - let mut store = Store::default(); - let memory_type = MemoryType { - shared: false, - minimum: Pages(0), - maximum: Some(Pages(10)), - }; - let memory = Memory::new(&mut store, memory_type)?; - assert_eq!(memory.view(&mut store).size(), Pages(0)); - assert_eq!(memory.ty(&mut store), memory_type); - Ok(()) - } - - #[test] - fn memory_grow() -> Result<()> { - let mut store = Store::default(); - let desc = MemoryType::new(Pages(10), Some(Pages(16)), false); - let memory = Memory::new(&mut store, desc)?; - assert_eq!(memory.view(&mut store).size(), Pages(10)); - - let result = memory.grow(&mut store, Pages(2)).unwrap(); - assert_eq!(result, Pages(10)); - assert_eq!(memory.view(&mut store).size(), Pages(12)); - - let result = memory.grow(&mut store, Pages(10)); - assert_eq!( - result, - Err(MemoryError::CouldNotGrow { - current: 12.into(), - attempted_delta: 10.into() - }) - ); - - let bad_desc = MemoryType::new(Pages(15), Some(Pages(10)), false); - let bad_result = Memory::new(&mut store, bad_desc); - - assert!(matches!(bad_result, Err(MemoryError::InvalidMemory { .. }))); - - Ok(()) - } - - #[test] - fn function_new() -> Result<()> { - let mut store = Store::default(); - let function = Function::new_typed(&mut store, || {}); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![], vec![]) - ); - let function = Function::new_typed(&mut store, |_a: i32| {}); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![Type::I32], vec![]) - ); - let function = Function::new_typed(&mut store, |_a: i32, _b: i64, _c: f32, _d: f64| {}); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) - ); - let function = Function::new_typed(&mut store, || -> i32 { 1 }); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![], vec![Type::I32]) - ); - let function = - Function::new_typed(&mut store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) - ); - Ok(()) - } - - #[test] - fn function_new_env() -> Result<()> { - let mut store = Store::default(); - #[derive(Clone)] - struct MyEnv {} - - let my_env = MyEnv {}; - let env = FunctionEnv::new(&mut store, my_env); - let function = - Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut| {}); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![], vec![]) - ); - let function = Function::new_typed_with_env( - &mut store, - &env, - |_env: FunctionEnvMut, _a: i32| {}, - ); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![Type::I32], vec![]) - ); - let function = Function::new_typed_with_env( - &mut store, - &env, - |_env: FunctionEnvMut, _a: i32, _b: i64, _c: f32, _d: f64| {}, - ); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) - ); - let function = - Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut| -> i32 { - 1 - }); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![], vec![Type::I32]) - ); - let function = Function::new_typed_with_env( - &mut store, - &env, - |_env: FunctionEnvMut| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, - ); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) - ); - Ok(()) - } - - #[test] - fn function_new_dynamic() -> Result<()> { - let mut store = Store::default(); - - // Using &FunctionType signature - let function_type = FunctionType::new(vec![], vec![]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = FunctionType::new(vec![Type::I32], vec![]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = FunctionType::new(vec![], vec![Type::I32]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - - // Using array signature - let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); - let function = Function::new( - &mut store, - function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).params(), [Type::V128]); - assert_eq!( - function.ty(&mut store).results(), - [Type::I32, Type::F32, Type::F64] - ); - - Ok(()) - } - - #[test] - fn function_new_dynamic_env() -> Result<()> { - let mut store = Store::default(); - #[derive(Clone)] - struct MyEnv {} - let my_env = MyEnv {}; - let env = FunctionEnv::new(&mut store, my_env); - - // Using &FunctionType signature - let function_type = FunctionType::new(vec![], vec![]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = FunctionType::new(vec![Type::I32], vec![]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = FunctionType::new(vec![], vec![Type::I32]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - - // Using array signature - let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); - let function = Function::new_with_env( - &mut store, - &env, - function_type, - |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).params(), [Type::V128]); - assert_eq!( - function.ty(&mut store).results(), - [Type::I32, Type::F32, Type::F64] - ); - - Ok(()) - } - - // #[test] - // fn native_function_works() -> Result<()> { - // let mut store = Store::default(); - // let function = Function::new_typed(&mut store, || {}); - // let typed_function: TypedFunction<(), ()> = function.typed(&mut store).unwrap(); - // let result = typed_function.call(&mut store); - // assert!(result.is_ok()); - - // let function = - // Function::new_typed(&mut store, |a: i32| -> i32 { a + 1 }); - // let typed_function: TypedFunction = function.typed(&mut store).unwrap(); - // assert_eq!(typed_function.call(&mut store, 3).unwrap(), 4); - - // fn rust_abi(a: i32, b: i64, c: f32, d: f64) -> u64 { - // (a as u64 * 1000) + (b as u64 * 100) + (c as u64 * 10) + (d as u64) - // } - // let function = Function::new_typed(&mut store, rust_abi); - // let typed_function: TypedFunction<(i32, i64, f32, f64), u64> = - // function.typed(&mut store).unwrap(); - // assert_eq!(typed_function.call(&mut store, 8, 4, 1.5, 5.).unwrap(), 8415); - - // let function = Function::new_typed(&mut store, || -> i32 { 1 }); - // let typed_function: TypedFunction<(), i32> = function.typed(&mut store).unwrap(); - // assert_eq!(typed_function.call(&mut store).unwrap(), 1); - - // let function = Function::new_typed(&mut store, |_a: i32| {}); - // let typed_function: TypedFunction = function.typed(&mut store).unwrap(); - // assert!(typed_function.call(&mut store, 4).is_ok()); - - // let function = - // Function::new_typed(&mut store, || -> (i32, i64, f32, f64) { - // (1, 2, 3.0, 4.0) - // }); - // let typed_function: TypedFunction<(), (i32, i64, f32, f64)> = - // function.typed(&mut store).unwrap(); - // assert_eq!(typed_function.call(&mut store).unwrap(), (1, 2, 3.0, 4.0)); - - // Ok(()) - // } - - // #[test] - // fn function_outlives_instance() -> Result<()> { - // let mut store = Store::default(); - // let wat = r#"(module - // (type $sum_t (func (param i32 i32) (result i32))) - // (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) - // local.get $x - // local.get $y - // i32.add) - // (export "sum" (func $sum_f))) - // "#; - - // let f = { - // let module = Module::new(&store, wat)?; - // let instance = Instance::new(&mut store, &module, &imports! {})?; - // let f: TypedFunction<(i32, i32), i32> = - // instance.exports.get_typed_function(&mut store, "sum")?; - - // assert_eq!(f.call(&mut store, 4, 5)?, 9); - // f - // }; - - // assert_eq!(f.call(&mut store, 4, 5)?, 9); - - // Ok(()) - // } - // /* - // #[test] - // fn weak_instance_ref_externs_after_instance() -> Result<()> { - // let mut store = Store::default(); - // let wat = r#"(module - // (memory (export "mem") 1) - // (type $sum_t (func (param i32 i32) (result i32))) - // (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) - // local.get $x - // local.get $y - // i32.add) - // (export "sum" (func $sum_f))) - // "#; - - // let f = { - // let module = Module::new(&store, wat)?; - // let instance = Instance::new(&mut store, &module, &imports! {})?; - // let f: TypedFunction<(i32, i32), i32> = - // instance.exports.get("sum")?; - - // assert_eq!(f.call(&mut store, 4, 5)?, 9); - // f - // }; - - // assert_eq!(f.call(&mut store, 4, 5)?, 9); - - // Ok(()) - // } - // */ - // #[test] - // fn manually_generate_wasmer_env() -> Result<()> { - // let mut store = Store::default(); - // #[derive(Clone)] - // struct MyEnv { - // val: u32, - // memory: Option, - // } - - // fn host_function(env: FunctionEnvMut, arg1: u32, arg2: u32) -> u32 { - // env.data().val + arg1 + arg2 - // } - - // let mut env = MyEnv { - // val: 5, - // memory: None, - // }; - // let env = FunctionEnv::new(&mut store, env); - - // let result = host_function(ctx.as_context_mut(), 7, 9); - // assert_eq!(result, 21); - - // let memory = Memory::new(&mut store, MemoryType::new(0, None, false))?; - // ctx.as_mut(&mut store).memory = Some(memory); - - // let result = host_function(ctx.as_context_mut(), 1, 2); - // assert_eq!(result, 8); - - // Ok(()) - // } -} diff --git a/lib/api/tests/sys_instance.rs b/lib/api/tests/sys_instance.rs deleted file mode 100644 index c1f51ed65b8..00000000000 --- a/lib/api/tests/sys_instance.rs +++ /dev/null @@ -1,76 +0,0 @@ -#[cfg(feature = "sys")] -mod sys { - use anyhow::Result; - use wasmer::FunctionEnv; - use wasmer::*; - - #[test] - fn exports_work_after_multiple_instances_have_been_freed() -> Result<()> { - let mut store = Store::default(); - let module = Module::new( - &store, - " - (module - (type $sum_t (func (param i32 i32) (result i32))) - (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) - local.get $x - local.get $y - i32.add) - (export \"sum\" (func $sum_f))) -", - )?; - - let imports = Imports::new(); - let instance = Instance::new(&mut store, &module, &imports)?; - let instance2 = instance.clone(); - let instance3 = instance.clone(); - - // The function is cloned to “break” the connection with `instance`. - let sum = instance.exports.get_function("sum")?.clone(); - - drop(instance); - drop(instance2); - drop(instance3); - - // All instances have been dropped, but `sum` continues to work! - assert_eq!( - sum.call(&mut store, &[Value::I32(1), Value::I32(2)])? - .into_vec(), - vec![Value::I32(3)], - ); - - Ok(()) - } - - #[test] - fn unit_native_function_env() -> Result<()> { - let mut store = Store::default(); - - #[derive(Clone)] - struct Env { - multiplier: u32, - } - - fn imported_fn( - env: FunctionEnvMut, - args: &[Value], - ) -> Result, RuntimeError> { - let value = env.data().multiplier * args[0].unwrap_i32() as u32; - Ok(vec![Value::I32(value as _)]) - } - - // We create the environment - let env = Env { multiplier: 3 }; - // We move the environment to the store, so it can be used by the `Function` - let env = FunctionEnv::new(&mut store, env); - - let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new_with_env(&mut store, &env, imported_signature, imported_fn); - - let expected = vec![Value::I32(12)].into_boxed_slice(); - let result = imported.call(&mut store, &[Value::I32(4)])?; - assert_eq!(result, expected); - - Ok(()) - } -} diff --git a/lib/api/tests/sys_module.rs b/lib/api/tests/sys_module.rs deleted file mode 100644 index 633fa7a477e..00000000000 --- a/lib/api/tests/sys_module.rs +++ /dev/null @@ -1,267 +0,0 @@ -#[cfg(feature = "sys")] -mod sys { - use anyhow::Result; - use wasmer::*; - - #[test] - fn module_get_name() -> Result<()> { - let store = Store::default(); - let wat = r#"(module)"#; - let module = Module::new(&store, wat)?; - assert_eq!(module.name(), None); - - Ok(()) - } - - #[test] - fn module_set_name() -> Result<()> { - let store = Store::default(); - let wat = r#"(module $name)"#; - let mut module = Module::new(&store, wat)?; - assert_eq!(module.name(), Some("name")); - - module.set_name("new_name"); - assert_eq!(module.name(), Some("new_name")); - - Ok(()) - } - - #[test] - fn imports() -> Result<()> { - let store = Store::default(); - let wat = r#"(module - (import "host" "func" (func)) - (import "host" "memory" (memory 1)) - (import "host" "table" (table 1 anyfunc)) - (import "host" "global" (global i32)) -)"#; - let module = Module::new(&store, wat)?; - assert_eq!( - module.imports().collect::>(), - vec![ - ImportType::new( - "host", - "func", - ExternType::Function(FunctionType::new(vec![], vec![])) - ), - ImportType::new( - "host", - "memory", - ExternType::Memory(MemoryType::new(Pages(1), None, false)) - ), - ImportType::new( - "host", - "table", - ExternType::Table(TableType::new(Type::FuncRef, 1, None)) - ), - ImportType::new( - "host", - "global", - ExternType::Global(GlobalType::new(Type::I32, Mutability::Const)) - ) - ] - ); - - // Now we test the iterators - assert_eq!( - module.imports().functions().collect::>(), - vec![ImportType::new( - "host", - "func", - FunctionType::new(vec![], vec![]) - ),] - ); - assert_eq!( - module.imports().memories().collect::>(), - vec![ImportType::new( - "host", - "memory", - MemoryType::new(Pages(1), None, false) - ),] - ); - assert_eq!( - module.imports().tables().collect::>(), - vec![ImportType::new( - "host", - "table", - TableType::new(Type::FuncRef, 1, None) - ),] - ); - assert_eq!( - module.imports().globals().collect::>(), - vec![ImportType::new( - "host", - "global", - GlobalType::new(Type::I32, Mutability::Const) - ),] - ); - Ok(()) - } - - #[test] - fn exports() -> Result<()> { - let store = Store::default(); - let wat = r#"(module - (func (export "func") nop) - (memory (export "memory") 1) - (table (export "table") 1 funcref) - (global (export "global") i32 (i32.const 0)) -)"#; - let module = Module::new(&store, wat)?; - assert_eq!( - module.exports().collect::>(), - vec![ - ExportType::new( - "func", - ExternType::Function(FunctionType::new(vec![], vec![])) - ), - ExportType::new( - "memory", - ExternType::Memory(MemoryType::new(Pages(1), None, false)) - ), - ExportType::new( - "table", - ExternType::Table(TableType::new(Type::FuncRef, 1, None)) - ), - ExportType::new( - "global", - ExternType::Global(GlobalType::new(Type::I32, Mutability::Const)) - ) - ] - ); - - // Now we test the iterators - assert_eq!( - module.exports().functions().collect::>(), - vec![ExportType::new("func", FunctionType::new(vec![], vec![])),] - ); - assert_eq!( - module.exports().memories().collect::>(), - vec![ExportType::new( - "memory", - MemoryType::new(Pages(1), None, false) - ),] - ); - assert_eq!( - module.exports().tables().collect::>(), - vec![ExportType::new( - "table", - TableType::new(Type::FuncRef, 1, None) - ),] - ); - assert_eq!( - module.exports().globals().collect::>(), - vec![ExportType::new( - "global", - GlobalType::new(Type::I32, Mutability::Const) - ),] - ); - Ok(()) - } - - #[test] - fn calling_host_functions_with_negative_values_works() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module - (import "host" "host_func1" (func (param i64))) - (import "host" "host_func2" (func (param i32))) - (import "host" "host_func3" (func (param i64))) - (import "host" "host_func4" (func (param i32))) - (import "host" "host_func5" (func (param i32))) - (import "host" "host_func6" (func (param i32))) - (import "host" "host_func7" (func (param i32))) - (import "host" "host_func8" (func (param i32))) - - (func (export "call_host_func1") - (call 0 (i64.const -1))) - (func (export "call_host_func2") - (call 1 (i32.const -1))) - (func (export "call_host_func3") - (call 2 (i64.const -1))) - (func (export "call_host_func4") - (call 3 (i32.const -1))) - (func (export "call_host_func5") - (call 4 (i32.const -1))) - (func (export "call_host_func6") - (call 5 (i32.const -1))) - (func (export "call_host_func7") - (call 6 (i32.const -1))) - (func (export "call_host_func8") - (call 7 (i32.const -1))) -)"#; - let module = Module::new(&store, wat)?; - let imports = imports! { - "host" => { - "host_func1" => Function::new_typed(&mut store, |p: u64| { - println!("host_func1: Found number {}", p); - assert_eq!(p, u64::max_value()); - }), - "host_func2" => Function::new_typed(&mut store, |p: u32| { - println!("host_func2: Found number {}", p); - assert_eq!(p, u32::max_value()); - }), - "host_func3" => Function::new_typed(&mut store, |p: i64| { - println!("host_func3: Found number {}", p); - assert_eq!(p, -1); - }), - "host_func4" => Function::new_typed(&mut store, |p: i32| { - println!("host_func4: Found number {}", p); - assert_eq!(p, -1); - }), - "host_func5" => Function::new_typed(&mut store, |p: i16| { - println!("host_func5: Found number {}", p); - assert_eq!(p, -1); - }), - "host_func6" => Function::new_typed(&mut store, |p: u16| { - println!("host_func6: Found number {}", p); - assert_eq!(p, u16::max_value()); - }), - "host_func7" => Function::new_typed(&mut store, |p: i8| { - println!("host_func7: Found number {}", p); - assert_eq!(p, -1); - }), - "host_func8" => Function::new_typed(&mut store, |p: u8| { - println!("host_func8: Found number {}", p); - assert_eq!(p, u8::max_value()); - }), - } - }; - let instance = Instance::new(&mut store, &module, &imports)?; - - let f1: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func1")?; - let f2: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func2")?; - let f3: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func3")?; - let f4: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func4")?; - let f5: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func5")?; - let f6: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func6")?; - let f7: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func7")?; - let f8: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func8")?; - - f1.call(&mut store)?; - f2.call(&mut store)?; - f3.call(&mut store)?; - f4.call(&mut store)?; - f5.call(&mut store)?; - f6.call(&mut store)?; - f7.call(&mut store)?; - f8.call(&mut store)?; - - Ok(()) - } -} diff --git a/lib/api/tests/sys_reference_types.rs b/lib/api/tests/sys_reference_types.rs deleted file mode 100644 index b481a07d8f9..00000000000 --- a/lib/api/tests/sys_reference_types.rs +++ /dev/null @@ -1,490 +0,0 @@ -#[cfg(feature = "sys")] -mod sys { - use anyhow::Result; - use std::sync::atomic::{AtomicBool, Ordering}; - use std::sync::Arc; - use wasmer::FunctionEnv; - use wasmer::*; - - #[test] - fn func_ref_passed_and_returned() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module - (import "env" "func_ref_identity" (func (param funcref) (result funcref))) - (type $ret_i32_ty (func (result i32))) - (table $table (export "table") 2 2 funcref) - - (func (export "run") (param) (result funcref) - (call 0 (ref.null func))) - (func (export "call_set_value") (param $fr funcref) (result i32) - (table.set $table (i32.const 0) (local.get $fr)) - (call_indirect $table (type $ret_i32_ty) (i32.const 0))) -)"#; - let module = Module::new(&store, wat)?; - #[derive(Clone, Debug)] - pub struct Env(Arc); - let env = Env(Arc::new(AtomicBool::new(false))); - let env = FunctionEnv::new(&mut store, env); - let imports = imports! { - "env" => { - "func_ref_identity" => Function::new_with_env(&mut store, &env, FunctionType::new([Type::FuncRef], [Type::FuncRef]), |_env: FunctionEnvMut, values: &[Value]| -> Result, _> { - Ok(vec![values[0].clone()]) - }) - }, - }; - - let instance = Instance::new(&mut store, &module, &imports)?; - - let f: &Function = instance.exports.get_function("run")?; - let results = f.call(&mut store, &[]).unwrap(); - if let Value::FuncRef(fr) = &results[0] { - assert!(fr.is_none()); - } else { - panic!("funcref not found!"); - } - - let func_to_call = - Function::new_typed_with_env(&mut store, &env, |mut env: FunctionEnvMut| -> i32 { - env.data_mut().0.store(true, Ordering::SeqCst); - 343 - }); - let call_set_value: &Function = instance.exports.get_function("call_set_value")?; - let results: Box<[Value]> = - call_set_value.call(&mut store, &[Value::FuncRef(Some(func_to_call))])?; - assert!(env - .as_mut(&mut store.as_store_mut()) - .0 - .load(Ordering::SeqCst)); - assert_eq!(&*results, &[Value::I32(343)]); - - Ok(()) - } - - #[test] - fn func_ref_passed_and_called() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module - (func $func_ref_call (import "env" "func_ref_call") (param funcref) (result i32)) - (type $ret_i32_ty (func (result i32))) - (table $table (export "table") 2 2 funcref) - - (func $product (param $x i32) (param $y i32) (result i32) - (i32.mul (local.get $x) (local.get $y))) - ;; TODO: figure out exactly why this statement is needed - (elem declare func $product) - (func (export "call_set_value") (param $fr funcref) (result i32) - (table.set $table (i32.const 0) (local.get $fr)) - (call_indirect $table (type $ret_i32_ty) (i32.const 0))) - (func (export "call_func") (param $fr funcref) (result i32) - (call $func_ref_call (local.get $fr))) - (func (export "call_host_func_with_wasm_func") (result i32) - (call $func_ref_call (ref.func $product))) -)"#; - let module = Module::new(&store, wat)?; - let env = FunctionEnv::new(&mut store, ()); - fn func_ref_call( - mut env: FunctionEnvMut<()>, - values: &[Value], - ) -> Result, RuntimeError> { - // TODO: look into `Box<[Value]>` being returned breakage - let f = values[0].unwrap_funcref().as_ref().unwrap(); - let f: TypedFunction<(i32, i32), i32> = f.typed(&mut env)?; - Ok(vec![Value::I32(f.call(&mut env, 7, 9)?)]) - } - - let imports = imports! { - "env" => { - "func_ref_call" => Function::new_with_env( - &mut store, - &env, - FunctionType::new([Type::FuncRef], [Type::I32]), - func_ref_call - ), - // "func_ref_call_native" => Function::new_native(&mut store, |f: Function| -> Result { - // let f: TypedFunction::<(i32, i32), i32> = f.typed(&mut store)?; - // f.call(&mut store, 7, 9) - // }) - }, - }; - - let instance = Instance::new(&mut store, &module, &imports)?; - { - fn sum(a: i32, b: i32) -> i32 { - a + b - } - let sum_func = Function::new_typed(&mut store, sum); - - let call_func: &Function = instance.exports.get_function("call_func")?; - let result = call_func.call(&mut store, &[Value::FuncRef(Some(sum_func))])?; - assert_eq!(result[0].unwrap_i32(), 16); - } - - { - let f: TypedFunction<(), i32> = instance - .exports - .get_typed_function(&mut store, "call_host_func_with_wasm_func")?; - let result = f.call(&mut store)?; - assert_eq!(result, 63); - } - - Ok(()) - } - - #[test] - fn extern_ref_passed_and_returned() -> Result<()> { - use std::collections::HashMap; - let mut store = Store::default(); - let wat = r#"(module - (func $extern_ref_identity (import "env" "extern_ref_identity") (param externref) (result externref)) - (func $extern_ref_identity_native (import "env" "extern_ref_identity_native") (param externref) (result externref)) - (func $get_new_extern_ref (import "env" "get_new_extern_ref") (result externref)) - (func $get_new_extern_ref_native (import "env" "get_new_extern_ref_native") (result externref)) - - (func (export "run") (param) (result externref) - (call $extern_ref_identity (ref.null extern))) - (func (export "run_native") (param) (result externref) - (call $extern_ref_identity_native (ref.null extern))) - (func (export "get_hashmap") (param) (result externref) - (call $get_new_extern_ref)) - (func (export "get_hashmap_native") (param) (result externref) - (call $get_new_extern_ref_native)) - )"#; - let module = Module::new(&store, wat)?; - let env = FunctionEnv::new(&mut store, ()); - let imports = imports! { - "env" => { - "extern_ref_identity" => Function::new_with_env(&mut store, &env, FunctionType::new([Type::ExternRef], [Type::ExternRef]), |_env, values| -> Result, _> { - Ok(vec![values[0].clone()]) - }), - "extern_ref_identity_native" => Function::new_typed(&mut store, |er: Option| -> Option { - er - }), - "get_new_extern_ref" => Function::new_with_env(&mut store, &env, FunctionType::new([], [Type::ExternRef]), |mut env, _| -> Result, _> { - let inner = - [("hello".to_string(), "world".to_string()), - ("color".to_string(), "orange".to_string())] - .iter() - .cloned() - .collect::>(); - let new_extern_ref = ExternRef::new(&mut env, inner); - Ok(vec![Value::ExternRef(Some(new_extern_ref))]) - }), - "get_new_extern_ref_native" => Function::new_typed_with_env(&mut store, &env, |mut env: FunctionEnvMut<()>| -> Option { - let inner = - [("hello".to_string(), "world".to_string()), - ("color".to_string(), "orange".to_string())] - .iter() - .cloned() - .collect::>(); - Some(ExternRef::new(&mut env.as_store_mut(), inner)) - }) - }, - }; - - let instance = Instance::new(&mut store, &module, &imports)?; - for run in &["run", "run_native"] { - let f: &Function = instance.exports.get_function(run)?; - let results = f.call(&mut store, &[]).unwrap(); - if let Value::ExternRef(er) = &results[0] { - assert!(er.is_none()); - } else { - panic!("result is not an extern ref!"); - } - - let f: TypedFunction<(), Option> = - instance.exports.get_typed_function(&store, run)?; - let result: Option = f.call(&mut store)?; - assert!(result.is_none()); - } - - for get_hashmap in &["get_hashmap", "get_hashmap_native"] { - let f: &Function = instance.exports.get_function(get_hashmap)?; - let results = f.call(&mut store, &[]).unwrap(); - if let Value::ExternRef(er) = &results[0] { - let inner: &HashMap = - er.as_ref().unwrap().downcast(&mut store).unwrap(); - assert_eq!(inner["hello"], "world"); - assert_eq!(inner["color"], "orange"); - } else { - panic!("result is not an extern ref!"); - } - - let f: TypedFunction<(), Option> = - instance.exports.get_typed_function(&store, get_hashmap)?; - - let result: Option = f.call(&mut store)?; - let inner: &HashMap = result.unwrap().downcast(&mut store).unwrap(); - assert_eq!(inner["hello"], "world"); - assert_eq!(inner["color"], "orange"); - } - - Ok(()) - } - - #[test] - fn extern_ref_ref_counting_basic() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module - (func (export "drop") (param $er externref) (result) - (drop (local.get $er))) - )"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut store, &module, &imports! {})?; - let f: TypedFunction, ()> = - instance.exports.get_typed_function(&store, "drop")?; - - let er = ExternRef::new(&mut store, 3u32); - f.call(&mut store, Some(er.clone()))?; - - let tmp: Option<&u32> = er.downcast(&mut store); - assert_eq!(tmp.unwrap(), &3); - - Ok(()) - } - - #[test] - fn refs_in_globals() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module - (global $er_global (export "er_global") (mut externref) (ref.null extern)) - (global $fr_global (export "fr_global") (mut funcref) (ref.null func)) - (global $fr_immutable_global (export "fr_immutable_global") funcref (ref.func $hello)) - (func $hello (param) (result i32) - (i32.const 73)) - )"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut store, &module, &imports! {})?; - { - let er_global: &Global = instance.exports.get_global("er_global")?; - - if let Value::ExternRef(er) = er_global.get(&mut store) { - assert!(er.is_none()); - } else { - panic!("Did not find extern ref in the global"); - } - let extref = Some(ExternRef::new(&mut store, 3u32)); - er_global.set(&mut store, Value::ExternRef(extref))?; - - if let Value::ExternRef(er) = er_global.get(&mut store) { - let tmp: Option<&u32> = er.unwrap().downcast(&mut store); - assert_eq!(tmp.unwrap(), &3); - } else { - panic!("Did not find extern ref in the global"); - } - } - - { - let fr_global: &Global = instance.exports.get_global("fr_immutable_global")?; - - if let Value::FuncRef(Some(f)) = fr_global.get(&mut store) { - let native_func: TypedFunction<(), u32> = f.typed(&mut store)?; - assert_eq!(native_func.call(&mut store)?, 73); - } else { - panic!("Did not find non-null func ref in the global"); - } - } - - { - let fr_global: &Global = instance.exports.get_global("fr_global")?; - - if let Value::FuncRef(None) = fr_global.get(&mut store) { - } else { - panic!("Did not find a null func ref in the global"); - } - - let f = Function::new_typed(&mut store, |arg1: i32, arg2: i32| -> i32 { arg1 + arg2 }); - - fr_global.set(&mut store, Value::FuncRef(Some(f)))?; - - if let Value::FuncRef(Some(f)) = fr_global.get(&mut store) { - let native: TypedFunction<(i32, i32), i32> = f.typed(&mut store)?; - assert_eq!(native.call(&mut store, 5, 7)?, 12); - } else { - panic!("Did not find extern ref in the global"); - } - } - - Ok(()) - } - - #[test] - fn extern_ref_ref_counting_table_basic() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module - (global $global (export "global") (mut externref) (ref.null extern)) - (table $table (export "table") 4 4 externref) - (func $insert (param $er externref) (param $idx i32) - (table.set $table (local.get $idx) (local.get $er))) - (func $intermediate (param $er externref) (param $idx i32) - (call $insert (local.get $er) (local.get $idx))) - (func $insert_into_table (export "insert_into_table") (param $er externref) (param $idx i32) (result externref) - (call $intermediate (local.get $er) (local.get $idx)) - (local.get $er)) - )"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut store, &module, &imports! {})?; - - let f: TypedFunction<(Option, i32), Option> = instance - .exports - .get_typed_function(&mut store, "insert_into_table")?; - - let er = ExternRef::new(&mut store, 3usize); - - let er = f.call(&mut store, Some(er), 1)?; - assert!(er.is_some()); - - let table: &Table = instance.exports.get_table("table")?; - - { - let er2 = table.get(&mut store, 1).unwrap(); - let er2 = er2.externref().unwrap(); - assert!(er2.is_some()); - } - - assert!(er.is_some()); - table.set(&mut store, 1, Value::ExternRef(None))?; - - assert!(er.is_some()); - - Ok(()) - } - - #[test] - fn extern_ref_ref_counting_global_basic() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module - (global $global (export "global") (mut externref) (ref.null extern)) - (func $get_from_global (export "get_from_global") (result externref) - (drop (global.get $global)) - (global.get $global)) - )"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut store, &module, &imports! {})?; - - let global: &Global = instance.exports.get_global("global")?; - { - let er = ExternRef::new(&mut store, 3usize); - global.set(&mut store, Value::ExternRef(Some(er.clone())))?; - } - let get_from_global: TypedFunction<(), Option> = instance - .exports - .get_typed_function(&mut store, "get_from_global")?; - - let er = get_from_global.call(&mut store)?; - assert!(er.is_some()); - global.set(&mut store, Value::ExternRef(None))?; - assert!(er.is_some()); - - Ok(()) - } - - #[test] - fn extern_ref_ref_counting_traps() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module - (func $pass_er (export "pass_extern_ref") (param externref) - (local.get 0) - (unreachable)) - )"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut store, &module, &imports! {})?; - - let pass_extern_ref: TypedFunction, ()> = instance - .exports - .get_typed_function(&mut store, "pass_extern_ref")?; - - let er = ExternRef::new(&mut store, 3usize); - - let result = pass_extern_ref.call(&mut store, Some(er.clone())); - assert!(result.is_err()); - - Ok(()) - } - - #[test] - fn extern_ref_ref_counting_table_instructions() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module - (table $table1 (export "table1") 2 12 externref) - (table $table2 (export "table2") 6 12 externref) - (func $grow_table_with_ref (export "grow_table_with_ref") (param $er externref) (param $size i32) (result i32) - (table.grow $table1 (local.get $er) (local.get $size))) - (func $fill_table_with_ref (export "fill_table_with_ref") (param $er externref) (param $start i32) (param $end i32) - (table.fill $table1 (local.get $start) (local.get $er) (local.get $end))) - (func $copy_into_table2 (export "copy_into_table2") - (table.copy $table2 $table1 (i32.const 0) (i32.const 0) (i32.const 4))) - )"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut store, &module, &imports! {})?; - - let grow_table_with_ref: TypedFunction<(Option, i32), i32> = instance - .exports - .get_typed_function(&mut store, "grow_table_with_ref")?; - let fill_table_with_ref: TypedFunction<(Option, i32, i32), ()> = instance - .exports - .get_typed_function(&mut store, "fill_table_with_ref")?; - let copy_into_table2: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "copy_into_table2")?; - let table1: &Table = instance.exports.get_table("table1")?; - let table2: &Table = instance.exports.get_table("table2")?; - - let er1 = ExternRef::new(&mut store, 3usize); - let er2 = ExternRef::new(&mut store, 5usize); - let er3 = ExternRef::new(&mut store, 7usize); - { - let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 0)?; - assert_eq!(result, 2); - - let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 10_000)?; - assert_eq!(result, -1); - - let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 8)?; - assert_eq!(result, 2); - - for i in 2..10 { - let v = table1.get(&mut store, i); - let e = v.as_ref().unwrap().unwrap_externref(); - let e_val: Option<&usize> = e.as_ref().unwrap().downcast(&mut store); - assert_eq!(*e_val.unwrap(), 3); - } - } - - { - fill_table_with_ref.call(&mut store, Some(er2.clone()), 0, 2)?; - } - - { - table2.set(&mut store, 0, Value::ExternRef(Some(er3.clone())))?; - table2.set(&mut store, 1, Value::ExternRef(Some(er3.clone())))?; - table2.set(&mut store, 2, Value::ExternRef(Some(er3.clone())))?; - table2.set(&mut store, 3, Value::ExternRef(Some(er3.clone())))?; - table2.set(&mut store, 4, Value::ExternRef(Some(er3.clone())))?; - } - - { - copy_into_table2.call(&mut store)?; - for i in 1..5 { - let v = table2.get(&mut store, i); - let e = v.as_ref().unwrap().unwrap_externref(); - let value: &usize = e.as_ref().unwrap().downcast(&mut store).unwrap(); - match i { - 0 | 1 => assert_eq!(*value, 5), - 4 => assert_eq!(*value, 7), - _ => assert_eq!(*value, 3), - } - } - } - - { - for i in 0..table1.size(&mut store) { - table1.set(&mut store, i, Value::ExternRef(None))?; - } - for i in 0..table2.size(&mut store) { - table2.set(&mut store, i, Value::ExternRef(None))?; - } - } - - Ok(()) - } -} From a16215337edcff9ff90f6129d22101ad7bf30650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Sch=C3=BCtt?= Date: Fri, 2 Sep 2022 12:10:27 +0200 Subject: [PATCH 02/14] Add initial proc-macro crate --- Cargo.lock | 121 +++++++++++++----- lib/api/Cargo.toml | 2 + .../macro-wasmer-universal-test/Cargo.toml | 12 ++ .../macro-wasmer-universal-test/src/lib.rs | 39 ++++++ lib/api/tests/reference_types.rs | 10 +- 5 files changed, 142 insertions(+), 42 deletions(-) create mode 100644 lib/api/macro-wasmer-universal-test/Cargo.toml create mode 100644 lib/api/macro-wasmer-universal-test/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 73327c3d2b2..e9834248aaa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "android_system_properties" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ed72e1635e121ca3e79420540282af22da58be50de153d36f81ddc6b83aa9e" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] @@ -57,15 +57,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1485d4d2cc45e7b201ee3767015c96faa5904387c9d87c6efdd0fb511f12d305" +checksum = "a26fa4d7e3f2eebadf743988fc8aec9fa9a9e82611acafd77c1462ed6262440a" [[package]] name = "arbitrary" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a7924531f38b1970ff630f03eb20a2fde69db5c590c93b0f3482e95dcc5fd60" +checksum = "8931eb436ab9bf1980c6cb2b9d1ba5390cd6793b2c6e2d2ea8147da3570c2a2e" dependencies = [ "derive_arbitrary", ] @@ -279,7 +279,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6358dedf60f4d9b8db43ad187391afe959746101346fe51bb978126bec61dfb" dependencies = [ - "clap 3.2.17", + "clap 3.2.20", "heck", "indexmap", "log", @@ -297,6 +297,9 @@ name = "cc" version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +dependencies = [ + "jobserver", +] [[package]] name = "cexpr" @@ -361,9 +364,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.17" +version = "3.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e724a68d9319343bb3328c9cc2dfde263f4b3142ee1059a9980580171c954b" +checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd" dependencies = [ "atty", "bitflags", @@ -378,9 +381,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.2.17" +version = "3.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13547f7012c01ab4a0e8f8967730ada8f9fdf419e8b6c792788f39cf4e46eefa" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ "heck", "proc-macro-error", @@ -756,9 +759,9 @@ dependencies = [ [[package]] name = "derive_arbitrary" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a577516173adb681466d517d39bd468293bc2c2a16439375ef0f35bba45f3d" +checksum = "d749b611838b7e92cba33b8552187059f2dc32f91d4d66bdc4fe5da9526b4e07" dependencies = [ "proc-macro2", "quote", @@ -941,9 +944,9 @@ dependencies = [ [[package]] name = "erased-serde" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003000e712ad0f95857bd4d2ef8d1890069e06554101697d12050668b2f6f020" +checksum = "54558e0ba96fbe24280072642eceb9d7d442e32c7ec0ea9e7ecd7b4ea2cf4e11" dependencies = [ "serde", ] @@ -1174,13 +1177,14 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "iana-time-zone" -version = "0.1.46" +version = "0.1.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad2bfd338099682614d3ee3fe0cd72e0b6a41ca6a87f6a74a3bd593c91650501" +checksum = "4c495f162af0bf17656d0014a0eded5f3cd2f365fdd204548c2869db89359dc7" dependencies = [ "android_system_properties", "core-foundation-sys", "js-sys", + "once_cell", "wasm-bindgen", "winapi", ] @@ -1296,6 +1300,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +[[package]] +name = "jobserver" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.59" @@ -1331,9 +1344,9 @@ checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" [[package]] name = "libfuzzer-sys" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "336244aaeab6a12df46480dc585802aa743a72d66b11937844c61bbca84c991d" +checksum = "ae185684fe19814afd066da15a7cc41e126886c21282934225d9fc847582da58" dependencies = [ "arbitrary", "cc", @@ -1365,9 +1378,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" dependencies = [ "autocfg", "scopeguard", @@ -1391,6 +1404,15 @@ dependencies = [ "libc", ] +[[package]] +name = "macro-wasmer-universal-test" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "proc-quote", + "syn", +] + [[package]] name = "matchers" version = "0.1.0" @@ -1631,9 +1653,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "peeking_take_while" @@ -1729,14 +1751,14 @@ dependencies = [ [[package]] name = "pretty_assertions" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89f989ac94207d048d92db058e4f6ec7342b0971fc58d1271ca148b799b3563" +checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" dependencies = [ - "ansi_term", "ctor", "diff", "output_vt100", + "yansi", ] [[package]] @@ -1778,6 +1800,30 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-quote" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e84ab161de78c915302ca325a19bee6df272800e2ae1a43fe3ef430bab2a100" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "proc-quote-impl", + "quote", + "syn", +] + +[[package]] +name = "proc-quote-impl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb3ec628b063cdbcf316e06a8b8c1a541d28fa6c0a8eacd2bfb2b7f49e88aa0" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", +] + [[package]] name = "ptr_meta" version = "0.1.4" @@ -2233,9 +2279,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa 1.0.3", "ryu", @@ -2515,18 +2561,18 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thiserror" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" +checksum = "3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" +checksum = "c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09" dependencies = [ "proc-macro2", "quote", @@ -2928,6 +2974,7 @@ dependencies = [ "hashbrown 0.11.2", "indexmap", "js-sys", + "macro-wasmer-universal-test", "more-asserts", "target-lexicon 0.12.4", "tempfile", @@ -3010,7 +3057,7 @@ dependencies = [ "atty", "bytesize", "cfg-if 1.0.0", - "clap 3.2.17", + "clap 3.2.20", "colored 2.0.0", "dirs", "distance", @@ -3071,7 +3118,7 @@ dependencies = [ "atty", "bytesize", "cfg-if 1.0.0", - "clap 3.2.17", + "clap 3.2.20", "colored 2.0.0", "distance", "fern", @@ -3713,3 +3760,9 @@ name = "xml-rs" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" + +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" diff --git a/lib/api/Cargo.toml b/lib/api/Cargo.toml index 9bcb2c9b0a1..d3373036c2a 100644 --- a/lib/api/Cargo.toml +++ b/lib/api/Cargo.toml @@ -55,6 +55,7 @@ winapi = "0.3" wat = "1.0" tempfile = "3.1" anyhow = "1.0" +macro-wasmer-universal-test = { version = "0.1.0", path = "./macro-wasmer-universal-test" } # Dependencies and Develoment Dependencies for `js`. [target.'cfg(target_arch = "wasm32")'.dependencies] @@ -72,6 +73,7 @@ hashbrown = { version = "0.11", optional = true } wat = "1.0" anyhow = "1.0" wasm-bindgen-test = "0.3.0" +macro-wasmer-universal-test = { version = "0.1.0", path = "./macro-wasmer-universal-test" } # Specific to `js`. # diff --git a/lib/api/macro-wasmer-universal-test/Cargo.toml b/lib/api/macro-wasmer-universal-test/Cargo.toml new file mode 100644 index 00000000000..ee00fd4ced2 --- /dev/null +++ b/lib/api/macro-wasmer-universal-test/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "macro-wasmer-universal-test" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +proc-quote = "0.4.0" +proc-macro2 = "1.0.43" +syn = "1.0.99" \ No newline at end of file diff --git a/lib/api/macro-wasmer-universal-test/src/lib.rs b/lib/api/macro-wasmer-universal-test/src/lib.rs new file mode 100644 index 00000000000..13fa4472a7d --- /dev/null +++ b/lib/api/macro-wasmer-universal-test/src/lib.rs @@ -0,0 +1,39 @@ +extern crate proc_macro; +use proc_macro::TokenStream; +use syn::{parse_macro_input, Result}; +use syn::parse::{Parse, ParseStream}; +use proc_macro2::{Ident, Span}; + +struct MyMacroInput { + function_name: String +} + +impl Parse for MyMacroInput { + fn parse(input: ParseStream) -> Result { + Ok(MyMacroInput { function_name: format!("hello") }) + } +} + +#[proc_macro_attribute] +pub fn universal_test(_: TokenStream, item: TokenStream) -> TokenStream { + + let item_clone = item.clone(); + let input = parse_macro_input!(item_clone as MyMacroInput); + let function_name_normal = Ident::new(&input.function_name, Span::call_site()); + let function_name_js = Ident::new(&format!("{}_js", input.function_name), Span::call_site()); + let item = proc_macro2::TokenStream::from(item); + + let tokens = proc_quote::quote! { + #[cfg(feature = "js")] + #[cfg_attr(feature = "js", wasm_bindgen_test)] + fn #function_name_js() { + let e: Result<()> = #function_name_normal(); + e.unwrap(); + } + + #[cfg_attr(feature = "sys", test)] + #item + }; + + proc_macro::TokenStream::from(tokens) +} \ No newline at end of file diff --git a/lib/api/tests/reference_types.rs b/lib/api/tests/reference_types.rs index 9acf9f3be0e..9671b223ce6 100644 --- a/lib/api/tests/reference_types.rs +++ b/lib/api/tests/reference_types.rs @@ -1,7 +1,7 @@ use anyhow::Result; #[cfg(feature = "js")] use wasm_bindgen_test::*; - +use macro_wasmer_universal_test::universal_test; use wasmer::*; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; @@ -144,13 +144,7 @@ fn func_ref_passed_and_called() -> Result<()> { } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn extern_ref_passed_and_returned_js() { - extern_ref_passed_and_returned().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[macro_wasmer_universal_test::universal_test] fn extern_ref_passed_and_returned() -> Result<()> { use std::collections::HashMap; let mut store = Store::default(); From 7d482d7e736f3bf07327ced38d2e66ebf3e6468b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Sch=C3=BCtt?= Date: Fri, 2 Sep 2022 15:47:25 +0200 Subject: [PATCH 03/14] Fix proc-macro for wasmer-universal-test to work correctly --- Cargo.lock | 8 ++++ Cargo.toml | 1 + lib/api/macro-wasmer-test/Cargo.toml | 7 +++ lib/api/macro-wasmer-test/src/main.rs | 9 ++++ .../macro-wasmer-universal-test/Cargo.toml | 3 +- .../macro-wasmer-universal-test/src/lib.rs | 44 +++++++++---------- 6 files changed, 48 insertions(+), 24 deletions(-) create mode 100644 lib/api/macro-wasmer-test/Cargo.toml create mode 100644 lib/api/macro-wasmer-test/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index e9834248aaa..71961907556 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1404,12 +1404,20 @@ dependencies = [ "libc", ] +[[package]] +name = "macro-wasmer-test" +version = "0.1.0" +dependencies = [ + "macro-wasmer-universal-test", +] + [[package]] name = "macro-wasmer-universal-test" version = "0.1.0" dependencies = [ "proc-macro2", "proc-quote", + "quote", "syn", ] diff --git a/Cargo.toml b/Cargo.toml index 6ee42dd2c37..1b2890aeee4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,6 +52,7 @@ members = [ "tests/lib/compiler-test-derive", "tests/integration/cli", "tests/integration/ios", + "lib/api/macro-wasmer-test", "fuzz", ] resolver = "2" diff --git a/lib/api/macro-wasmer-test/Cargo.toml b/lib/api/macro-wasmer-test/Cargo.toml new file mode 100644 index 00000000000..44f5230d0e3 --- /dev/null +++ b/lib/api/macro-wasmer-test/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "macro-wasmer-test" +version = "0.1.0" +edition = "2021" + +[dependencies] +macro-wasmer-universal-test = { version = "0.1.0", path = "../macro-wasmer-universal-test" } diff --git a/lib/api/macro-wasmer-test/src/main.rs b/lib/api/macro-wasmer-test/src/main.rs new file mode 100644 index 00000000000..50cbbac1a2e --- /dev/null +++ b/lib/api/macro-wasmer-test/src/main.rs @@ -0,0 +1,9 @@ +#[macro_wasmer_universal_test::universal_test] +fn extern_ref_passed_and_returned() -> Result<(), ()> { + Ok(()) +} + +fn main() { + extern_ref_passed_and_returned_js(); + extern_ref_passed_and_returned().unwrap(); +} diff --git a/lib/api/macro-wasmer-universal-test/Cargo.toml b/lib/api/macro-wasmer-universal-test/Cargo.toml index ee00fd4ced2..8132ddf4854 100644 --- a/lib/api/macro-wasmer-universal-test/Cargo.toml +++ b/lib/api/macro-wasmer-universal-test/Cargo.toml @@ -9,4 +9,5 @@ proc-macro = true [dependencies] proc-quote = "0.4.0" proc-macro2 = "1.0.43" -syn = "1.0.99" \ No newline at end of file +syn = { version = "1.0.99", features = ["full"] } +quote = "*" \ No newline at end of file diff --git a/lib/api/macro-wasmer-universal-test/src/lib.rs b/lib/api/macro-wasmer-universal-test/src/lib.rs index 13fa4472a7d..94b3de41dc3 100644 --- a/lib/api/macro-wasmer-universal-test/src/lib.rs +++ b/lib/api/macro-wasmer-universal-test/src/lib.rs @@ -1,38 +1,36 @@ extern crate proc_macro; + use proc_macro::TokenStream; -use syn::{parse_macro_input, Result}; -use syn::parse::{Parse, ParseStream}; use proc_macro2::{Ident, Span}; -struct MyMacroInput { - function_name: String -} - -impl Parse for MyMacroInput { - fn parse(input: ParseStream) -> Result { - Ok(MyMacroInput { function_name: format!("hello") }) - } -} - #[proc_macro_attribute] -pub fn universal_test(_: TokenStream, item: TokenStream) -> TokenStream { +pub fn universal_test(_attr: TokenStream, item: TokenStream) -> TokenStream { let item_clone = item.clone(); - let input = parse_macro_input!(item_clone as MyMacroInput); - let function_name_normal = Ident::new(&input.function_name, Span::call_site()); - let function_name_js = Ident::new(&format!("{}_js", input.function_name), Span::call_site()); - let item = proc_macro2::TokenStream::from(item); + let mut iter = item_clone.into_iter(); + let _ = iter.next().unwrap(); // fn + let item_tree: proc_macro::TokenTree = iter.next().unwrap(); // fn ... + let n = match &item_tree { + proc_macro::TokenTree::Ident(i) => i.to_string(), + _ => panic!("expected fn ...() -> Result<(), String>"), + }; + + let function_name_normal = Ident::new(&n, Span::call_site()); + let function_name_js = Ident::new(&format!("{}_js", n), Span::call_site()); + let parsed = match syn::parse::(item) { + Ok(o) => o, + Err(e) => { + return proc_macro::TokenStream::from(e.to_compile_error()); + }, + }; - let tokens = proc_quote::quote! { + let tokens = quote::quote! { #[cfg(feature = "js")] #[cfg_attr(feature = "js", wasm_bindgen_test)] - fn #function_name_js() { - let e: Result<()> = #function_name_normal(); - e.unwrap(); - } + fn #function_name_js() { #function_name_normal().unwrap(); } #[cfg_attr(feature = "sys", test)] - #item + #parsed }; proc_macro::TokenStream::from(tokens) From 670df982120959ae79a06ac7be3174033e297d6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Sch=C3=BCtt?= Date: Fri, 2 Sep 2022 15:56:30 +0200 Subject: [PATCH 04/14] Remove macro-test crate, verify that the proc-macro works --- lib/api/macro-wasmer-test/Cargo.toml | 7 ------- lib/api/macro-wasmer-test/src/main.rs | 9 --------- 2 files changed, 16 deletions(-) delete mode 100644 lib/api/macro-wasmer-test/Cargo.toml delete mode 100644 lib/api/macro-wasmer-test/src/main.rs diff --git a/lib/api/macro-wasmer-test/Cargo.toml b/lib/api/macro-wasmer-test/Cargo.toml deleted file mode 100644 index 44f5230d0e3..00000000000 --- a/lib/api/macro-wasmer-test/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "macro-wasmer-test" -version = "0.1.0" -edition = "2021" - -[dependencies] -macro-wasmer-universal-test = { version = "0.1.0", path = "../macro-wasmer-universal-test" } diff --git a/lib/api/macro-wasmer-test/src/main.rs b/lib/api/macro-wasmer-test/src/main.rs deleted file mode 100644 index 50cbbac1a2e..00000000000 --- a/lib/api/macro-wasmer-test/src/main.rs +++ /dev/null @@ -1,9 +0,0 @@ -#[macro_wasmer_universal_test::universal_test] -fn extern_ref_passed_and_returned() -> Result<(), ()> { - Ok(()) -} - -fn main() { - extern_ref_passed_and_returned_js(); - extern_ref_passed_and_returned().unwrap(); -} From 3a247319856785a685bb1196381861c9ab4d45b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Sch=C3=BCtt?= Date: Fri, 2 Sep 2022 16:25:38 +0200 Subject: [PATCH 05/14] Use #[universal_test] (PR review) --- Cargo.lock | 7 -- Cargo.toml | 1 - lib/api/tests/externals.rs | 118 +++++-------------------------- lib/api/tests/instance.rs | 17 +---- lib/api/tests/module.rs | 41 ++--------- lib/api/tests/reference_types.rs | 64 +++-------------- 6 files changed, 33 insertions(+), 215 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 71961907556..b8703ce5106 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1404,13 +1404,6 @@ dependencies = [ "libc", ] -[[package]] -name = "macro-wasmer-test" -version = "0.1.0" -dependencies = [ - "macro-wasmer-universal-test", -] - [[package]] name = "macro-wasmer-universal-test" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 1b2890aeee4..6ee42dd2c37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,6 @@ members = [ "tests/lib/compiler-test-derive", "tests/integration/cli", "tests/integration/ios", - "lib/api/macro-wasmer-test", "fuzz", ] resolver = "2" diff --git a/lib/api/tests/externals.rs b/lib/api/tests/externals.rs index eb23b5e7aa4..06ad7bf232b 100644 --- a/lib/api/tests/externals.rs +++ b/lib/api/tests/externals.rs @@ -1,16 +1,11 @@ use anyhow::Result; #[cfg(feature = "js")] use wasm_bindgen_test::*; +use macro_wasmer_universal_test::universal_test; use wasmer::*; -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn global_new_js() { - global_new().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn global_new() -> Result<()> { let mut store = Store::default(); let global = Global::new(&mut store, Value::I32(10)); @@ -35,13 +30,7 @@ fn global_new() -> Result<()> { } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn global_get_js() { - global_get().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn global_get() -> Result<()> { let mut store = Store::default(); let global_i32 = Global::new(&mut store, Value::I32(10)); @@ -56,13 +45,7 @@ fn global_get() -> Result<()> { Ok(()) } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn global_set_js() { - global_set().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn global_set() -> Result<()> { let mut store = Store::default(); let global_i32 = Global::new(&mut store, Value::I32(10)); @@ -80,13 +63,7 @@ fn global_set() -> Result<()> { Ok(()) } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn table_new_js() { - table_new().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn table_new() -> Result<()> { let mut store = Store::default(); let table_type = TableType { @@ -110,14 +87,7 @@ fn table_new() -> Result<()> { Ok(()) } -#[cfg_attr(feature = "sys", test)] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -#[ignore] -fn table_get_js() { - table_get().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn table_get() -> Result<()> { let mut store = Store::default(); let table_type = TableType { @@ -133,26 +103,13 @@ fn table_get() -> Result<()> { Ok(()) } -#[cfg_attr(feature = "sys", test)] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -#[ignore] -fn table_set_js() { - table_set().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn table_set() -> Result<()> { // Table set not yet tested Ok(()) } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn table_grow_js() { - table_grow().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn table_grow() -> Result<()> { let mut store = Store::default(); let table_type = TableType { @@ -173,26 +130,13 @@ fn table_grow() -> Result<()> { Ok(()) } -#[cfg_attr(feature = "sys", test)] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -#[ignore] -fn table_copy_js() { - table_copy().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn table_copy() -> Result<()> { // TODO: table copy test not yet implemented Ok(()) } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn memory_new_js() { - memory_new().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn memory_new() -> Result<()> { let mut store = Store::default(); let memory_type = MemoryType { @@ -206,13 +150,7 @@ fn memory_new() -> Result<()> { Ok(()) } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn memory_grow_js() { - memory_grow().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn memory_grow() -> Result<()> { let mut store = Store::default(); let desc = MemoryType::new(Pages(10), Some(Pages(16)), false); @@ -240,13 +178,7 @@ fn memory_grow() -> Result<()> { Ok(()) } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn function_new_js() { - function_new().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn function_new() -> Result<()> { let mut store = Store::default(); let function = Function::new_typed(&mut store, || {}); @@ -278,13 +210,7 @@ fn function_new() -> Result<()> { Ok(()) } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn function_new_env_js() { - function_new_env().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn function_new_env() -> Result<()> { let mut store = Store::default(); #[derive(Clone)] @@ -336,13 +262,7 @@ fn function_new_env() -> Result<()> { Ok(()) } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn function_new_dynamic_js() { - function_new_dynamic().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn function_new_dynamic() -> Result<()> { let mut store = Store::default(); @@ -401,13 +321,7 @@ fn function_new_dynamic() -> Result<()> { Ok(()) } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn function_new_dynamic_env_js() { - function_new_dynamic_env().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn function_new_dynamic_env() -> Result<()> { let mut store = Store::default(); #[derive(Clone)] @@ -474,4 +388,4 @@ fn function_new_dynamic_env() -> Result<()> { ); Ok(()) -} \ No newline at end of file +} diff --git a/lib/api/tests/instance.rs b/lib/api/tests/instance.rs index c3268d8cc46..4fbb5cdff2d 100644 --- a/lib/api/tests/instance.rs +++ b/lib/api/tests/instance.rs @@ -1,17 +1,12 @@ use anyhow::Result; #[cfg(feature = "js")] use wasm_bindgen_test::*; +use macro_wasmer_universal_test::universal_test; use wasmer::*; -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn exports_work_after_multiple_instances_have_been_freed_js() { - exports_work_after_multiple_instances_have_been_freed().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn exports_work_after_multiple_instances_have_been_freed() -> Result<()> { let mut store = Store::default(); let module = Module::new( @@ -50,13 +45,7 @@ fn exports_work_after_multiple_instances_have_been_freed() -> Result<()> { } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn unit_native_function_env_js() { - unit_native_function_env().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn unit_native_function_env() -> Result<()> { let mut store = Store::default(); diff --git a/lib/api/tests/module.rs b/lib/api/tests/module.rs index 4eb779cc735..150ed824da8 100644 --- a/lib/api/tests/module.rs +++ b/lib/api/tests/module.rs @@ -1,16 +1,11 @@ use anyhow::Result; #[cfg(feature = "js")] use wasm_bindgen_test::*; +use macro_wasmer_universal_test::universal_test; use wasmer::*; -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn module_get_name_js() { - module_get_name().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn module_get_name() -> Result<()> { let store = Store::default(); let wat = r#"(module)"#; @@ -20,13 +15,7 @@ fn module_get_name() -> Result<()> { Ok(()) } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn module_set_name_js() { - module_set_name().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn module_set_name() -> Result<()> { let store = Store::default(); let wat = r#"(module $name)"#; @@ -39,13 +28,7 @@ fn module_set_name() -> Result<()> { Ok(()) } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn imports_js() { - imports().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn imports() -> Result<()> { let store = Store::default(); let wat = r#"(module @@ -117,13 +100,7 @@ fn imports() -> Result<()> { Ok(()) } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn exports_js() { - exports().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn exports() -> Result<()> { let store = Store::default(); let wat = r#"(module @@ -184,13 +161,7 @@ fn exports() -> Result<()> { Ok(()) } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn calling_host_functions_with_negative_values_works_js() { - calling_host_functions_with_negative_values_works().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn calling_host_functions_with_negative_values_works() -> Result<()> { let mut store = Store::default(); let wat = r#"(module diff --git a/lib/api/tests/reference_types.rs b/lib/api/tests/reference_types.rs index 9671b223ce6..a5a343d5282 100644 --- a/lib/api/tests/reference_types.rs +++ b/lib/api/tests/reference_types.rs @@ -6,13 +6,7 @@ use wasmer::*; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn func_ref_passed_and_returned_js() { - func_ref_passed_and_returned().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn func_ref_passed_and_returned() -> Result<()> { let mut store = Store::default(); let wat = r#"(module @@ -67,13 +61,7 @@ fn func_ref_passed_and_returned() -> Result<()> { } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn func_ref_passed_and_called_js() { - func_ref_passed_and_called().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn func_ref_passed_and_called() -> Result<()> { let mut store = Store::default(); let wat = r#"(module @@ -236,13 +224,7 @@ fn extern_ref_passed_and_returned() -> Result<()> { } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn extern_ref_ref_counting_basic_js() { - extern_ref_ref_counting_basic().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn extern_ref_ref_counting_basic() -> Result<()> { let mut store = Store::default(); let wat = r#"(module @@ -264,13 +246,7 @@ fn extern_ref_ref_counting_basic() -> Result<()> { } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn refs_in_globals_js() { - refs_in_globals().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn refs_in_globals() -> Result<()> { let mut store = Store::default(); let wat = r#"(module @@ -336,13 +312,7 @@ fn refs_in_globals() -> Result<()> { } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn extern_ref_ref_counting_table_basic_js() { - extern_ref_ref_counting_table_basic().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn extern_ref_ref_counting_table_basic() -> Result<()> { let mut store = Store::default(); let wat = r#"(module @@ -385,13 +355,7 @@ fn extern_ref_ref_counting_table_basic() -> Result<()> { } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn extern_ref_ref_counting_global_basic_js() { - extern_ref_ref_counting_global_basic().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn extern_ref_ref_counting_global_basic() -> Result<()> { let mut store = Store::default(); let wat = r#"(module @@ -421,13 +385,7 @@ fn extern_ref_ref_counting_global_basic() -> Result<()> { } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn extern_ref_ref_counting_traps_js() { - extern_ref_ref_counting_traps().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn extern_ref_ref_counting_traps() -> Result<()> { let mut store = Store::default(); let wat = r#"(module @@ -451,13 +409,7 @@ fn extern_ref_ref_counting_traps() -> Result<()> { } -#[cfg(feature = "js")] -#[cfg_attr(feature = "js", wasm_bindgen_test)] -fn extern_ref_ref_counting_table_instructions_js() { - extern_ref_ref_counting_table_instructions().unwrap(); -} - -#[cfg_attr(feature = "sys", test)] +#[universal_test] fn extern_ref_ref_counting_table_instructions() -> Result<()> { let mut store = Store::default(); let wat = r#"(module From 416dbfa2b820cf1be72f7e875a747d39776daacf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Sch=C3=BCtt?= Date: Fri, 2 Sep 2022 16:27:56 +0200 Subject: [PATCH 06/14] Remove ExternRef tests on -js target --- .../macro-wasmer-universal-test/src/lib.rs | 13 +- lib/api/tests/externals.rs | 32 +- lib/api/tests/instance.rs | 11 +- lib/api/tests/module.rs | 4 +- lib/api/tests/reference_types.rs | 706 +++++++++--------- 5 files changed, 372 insertions(+), 394 deletions(-) diff --git a/lib/api/macro-wasmer-universal-test/src/lib.rs b/lib/api/macro-wasmer-universal-test/src/lib.rs index 94b3de41dc3..48838c0e7f8 100644 --- a/lib/api/macro-wasmer-universal-test/src/lib.rs +++ b/lib/api/macro-wasmer-universal-test/src/lib.rs @@ -5,7 +5,6 @@ use proc_macro2::{Ident, Span}; #[proc_macro_attribute] pub fn universal_test(_attr: TokenStream, item: TokenStream) -> TokenStream { - let item_clone = item.clone(); let mut iter = item_clone.into_iter(); let _ = iter.next().unwrap(); // fn @@ -14,24 +13,24 @@ pub fn universal_test(_attr: TokenStream, item: TokenStream) -> TokenStream { proc_macro::TokenTree::Ident(i) => i.to_string(), _ => panic!("expected fn ...() -> Result<(), String>"), }; - + let function_name_normal = Ident::new(&n, Span::call_site()); let function_name_js = Ident::new(&format!("{}_js", n), Span::call_site()); let parsed = match syn::parse::(item) { Ok(o) => o, - Err(e) => { - return proc_macro::TokenStream::from(e.to_compile_error()); - }, + Err(e) => { + return proc_macro::TokenStream::from(e.to_compile_error()); + } }; let tokens = quote::quote! { #[cfg(feature = "js")] #[cfg_attr(feature = "js", wasm_bindgen_test)] fn #function_name_js() { #function_name_normal().unwrap(); } - + #[cfg_attr(feature = "sys", test)] #parsed }; proc_macro::TokenStream::from(tokens) -} \ No newline at end of file +} diff --git a/lib/api/tests/externals.rs b/lib/api/tests/externals.rs index 06ad7bf232b..66bf54dcb7e 100644 --- a/lib/api/tests/externals.rs +++ b/lib/api/tests/externals.rs @@ -1,7 +1,7 @@ use anyhow::Result; +use macro_wasmer_universal_test::universal_test; #[cfg(feature = "js")] use wasm_bindgen_test::*; -use macro_wasmer_universal_test::universal_test; use wasmer::*; @@ -29,7 +29,6 @@ fn global_new() -> Result<()> { Ok(()) } - #[universal_test] fn global_get() -> Result<()> { let mut store = Store::default(); @@ -201,8 +200,7 @@ fn function_new() -> Result<()> { function.ty(&mut store).clone(), FunctionType::new(vec![], vec![Type::I32]) ); - let function = - Function::new_typed(&mut store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); + let function = Function::new_typed(&mut store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); assert_eq!( function.ty(&mut store).clone(), FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) @@ -218,17 +216,13 @@ fn function_new_env() -> Result<()> { let my_env = MyEnv {}; let env = FunctionEnv::new(&mut store, my_env); - let function = - Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut| {}); + let function = Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut| {}); assert_eq!( function.ty(&mut store).clone(), FunctionType::new(vec![], vec![]) ); - let function = Function::new_typed_with_env( - &mut store, - &env, - |_env: FunctionEnvMut, _a: i32| {}, - ); + let function = + Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut, _a: i32| {}); assert_eq!( function.ty(&mut store).clone(), FunctionType::new(vec![Type::I32], vec![]) @@ -243,9 +237,7 @@ fn function_new_env() -> Result<()> { FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) ); let function = - Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut| -> i32 { - 1 - }); + Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut| -> i32 { 1 }); assert_eq!( function.ty(&mut store).clone(), FunctionType::new(vec![], vec![Type::I32]) @@ -281,8 +273,7 @@ fn function_new_dynamic() -> Result<()> { |_values: &[Value]| unimplemented!(), ); assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); + let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); let function = Function::new( &mut store, &function_type, @@ -296,8 +287,7 @@ fn function_new_dynamic() -> Result<()> { |_values: &[Value]| unimplemented!(), ); assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); + let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); let function = Function::new( &mut store, &function_type, @@ -346,8 +336,7 @@ fn function_new_dynamic_env() -> Result<()> { |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), ); assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); + let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); let function = Function::new_with_env( &mut store, &env, @@ -363,8 +352,7 @@ fn function_new_dynamic_env() -> Result<()> { |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), ); assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); + let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); let function = Function::new_with_env( &mut store, &env, diff --git a/lib/api/tests/instance.rs b/lib/api/tests/instance.rs index 4fbb5cdff2d..2f9ca45d1e1 100644 --- a/lib/api/tests/instance.rs +++ b/lib/api/tests/instance.rs @@ -1,11 +1,10 @@ use anyhow::Result; +use macro_wasmer_universal_test::universal_test; #[cfg(feature = "js")] use wasm_bindgen_test::*; -use macro_wasmer_universal_test::universal_test; use wasmer::*; - #[universal_test] fn exports_work_after_multiple_instances_have_been_freed() -> Result<()> { let mut store = Store::default(); @@ -44,7 +43,6 @@ fn exports_work_after_multiple_instances_have_been_freed() -> Result<()> { Ok(()) } - #[universal_test] fn unit_native_function_env() -> Result<()> { let mut store = Store::default(); @@ -54,10 +52,7 @@ fn unit_native_function_env() -> Result<()> { multiplier: u32, } - fn imported_fn( - env: FunctionEnvMut, - args: &[Value], - ) -> Result, RuntimeError> { + fn imported_fn(env: FunctionEnvMut, args: &[Value]) -> Result, RuntimeError> { let value = env.data().multiplier * args[0].unwrap_i32() as u32; Ok(vec![Value::I32(value as _)]) } @@ -75,4 +70,4 @@ fn unit_native_function_env() -> Result<()> { assert_eq!(result, expected); Ok(()) -} \ No newline at end of file +} diff --git a/lib/api/tests/module.rs b/lib/api/tests/module.rs index 150ed824da8..f174c200433 100644 --- a/lib/api/tests/module.rs +++ b/lib/api/tests/module.rs @@ -1,7 +1,7 @@ use anyhow::Result; +use macro_wasmer_universal_test::universal_test; #[cfg(feature = "js")] use wasm_bindgen_test::*; -use macro_wasmer_universal_test::universal_test; use wasmer::*; @@ -265,4 +265,4 @@ fn calling_host_functions_with_negative_values_works() -> Result<()> { f8.call(&mut store)?; Ok(()) -} \ No newline at end of file +} diff --git a/lib/api/tests/reference_types.rs b/lib/api/tests/reference_types.rs index a5a343d5282..36c47ae884f 100644 --- a/lib/api/tests/reference_types.rs +++ b/lib/api/tests/reference_types.rs @@ -1,15 +1,18 @@ use anyhow::Result; -#[cfg(feature = "js")] -use wasm_bindgen_test::*; use macro_wasmer_universal_test::universal_test; -use wasmer::*; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; +#[cfg(feature = "js")] +use wasm_bindgen_test::*; +use wasmer::*; -#[universal_test] -fn func_ref_passed_and_returned() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module +#[cfg(feature = "sys")] +pub mod reference_types { + + #[universal_test] + fn func_ref_passed_and_returned() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module (import "env" "func_ref_identity" (func (param funcref) (result funcref))) (type $ret_i32_ty (func (result i32))) (table $table (export "table") 2 2 funcref) @@ -20,51 +23,50 @@ fn func_ref_passed_and_returned() -> Result<()> { (table.set $table (i32.const 0) (local.get $fr)) (call_indirect $table (type $ret_i32_ty) (i32.const 0))) )"#; - let module = Module::new(&store, wat)?; - #[derive(Clone, Debug)] - pub struct Env(Arc); - let env = Env(Arc::new(AtomicBool::new(false))); - let env = FunctionEnv::new(&mut store, env); - let imports = imports! { - "env" => { - "func_ref_identity" => Function::new_with_env(&mut store, &env, FunctionType::new([Type::FuncRef], [Type::FuncRef]), |_env: FunctionEnvMut, values: &[Value]| -> Result, _> { - Ok(vec![values[0].clone()]) - }) - }, - }; - - let instance = Instance::new(&mut store, &module, &imports)?; - - let f: &Function = instance.exports.get_function("run")?; - let results = f.call(&mut store, &[]).unwrap(); - if let Value::FuncRef(fr) = &results[0] { - assert!(fr.is_none()); - } else { - panic!("funcref not found!"); - } - - let func_to_call = - Function::new_typed_with_env(&mut store, &env, |mut env: FunctionEnvMut| -> i32 { - env.data_mut().0.store(true, Ordering::SeqCst); - 343 - }); - let call_set_value: &Function = instance.exports.get_function("call_set_value")?; - let results: Box<[Value]> = - call_set_value.call(&mut store, &[Value::FuncRef(Some(func_to_call))])?; - assert!(env - .as_mut(&mut store.as_store_mut()) - .0 - .load(Ordering::SeqCst)); - assert_eq!(&*results, &[Value::I32(343)]); - - Ok(()) -} + let module = Module::new(&store, wat)?; + #[derive(Clone, Debug)] + pub struct Env(Arc); + let env = Env(Arc::new(AtomicBool::new(false))); + let env = FunctionEnv::new(&mut store, env); + let imports = imports! { + "env" => { + "func_ref_identity" => Function::new_with_env(&mut store, &env, FunctionType::new([Type::FuncRef], [Type::FuncRef]), |_env: FunctionEnvMut, values: &[Value]| -> Result, _> { + Ok(vec![values[0].clone()]) + }) + }, + }; + + let instance = Instance::new(&mut store, &module, &imports)?; + + let f: &Function = instance.exports.get_function("run")?; + let results = f.call(&mut store, &[]).unwrap(); + if let Value::FuncRef(fr) = &results[0] { + assert!(fr.is_none()); + } else { + panic!("funcref not found!"); + } + let func_to_call = + Function::new_typed_with_env(&mut store, &env, |mut env: FunctionEnvMut| -> i32 { + env.data_mut().0.store(true, Ordering::SeqCst); + 343 + }); + let call_set_value: &Function = instance.exports.get_function("call_set_value")?; + let results: Box<[Value]> = + call_set_value.call(&mut store, &[Value::FuncRef(Some(func_to_call))])?; + assert!(env + .as_mut(&mut store.as_store_mut()) + .0 + .load(Ordering::SeqCst)); + assert_eq!(&*results, &[Value::I32(343)]); + + Ok(()) + } -#[universal_test] -fn func_ref_passed_and_called() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module + #[universal_test] + fn func_ref_passed_and_called() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module (func $func_ref_call (import "env" "func_ref_call") (param funcref) (result i32)) (type $ret_i32_ty (func (result i32))) (table $table (export "table") 2 2 funcref) @@ -81,62 +83,61 @@ fn func_ref_passed_and_called() -> Result<()> { (func (export "call_host_func_with_wasm_func") (result i32) (call $func_ref_call (ref.func $product))) )"#; - let module = Module::new(&store, wat)?; - let env = FunctionEnv::new(&mut store, ()); - fn func_ref_call( - mut env: FunctionEnvMut<()>, - values: &[Value], - ) -> Result, RuntimeError> { - // TODO: look into `Box<[Value]>` being returned breakage - let f = values[0].unwrap_funcref().as_ref().unwrap(); - let f: TypedFunction<(i32, i32), i32> = f.typed(&mut env)?; - Ok(vec![Value::I32(f.call(&mut env, 7, 9)?)]) - } - - let imports = imports! { - "env" => { - "func_ref_call" => Function::new_with_env( - &mut store, - &env, - FunctionType::new([Type::FuncRef], [Type::I32]), - func_ref_call - ), - // "func_ref_call_native" => Function::new_native(&mut store, |f: Function| -> Result { - // let f: TypedFunction::<(i32, i32), i32> = f.typed(&mut store)?; - // f.call(&mut store, 7, 9) - // }) - }, - }; - - let instance = Instance::new(&mut store, &module, &imports)?; - { - fn sum(a: i32, b: i32) -> i32 { - a + b + let module = Module::new(&store, wat)?; + let env = FunctionEnv::new(&mut store, ()); + fn func_ref_call( + mut env: FunctionEnvMut<()>, + values: &[Value], + ) -> Result, RuntimeError> { + // TODO: look into `Box<[Value]>` being returned breakage + let f = values[0].unwrap_funcref().as_ref().unwrap(); + let f: TypedFunction<(i32, i32), i32> = f.typed(&mut env)?; + Ok(vec![Value::I32(f.call(&mut env, 7, 9)?)]) } - let sum_func = Function::new_typed(&mut store, sum); - let call_func: &Function = instance.exports.get_function("call_func")?; - let result = call_func.call(&mut store, &[Value::FuncRef(Some(sum_func))])?; - assert_eq!(result[0].unwrap_i32(), 16); - } + let imports = imports! { + "env" => { + "func_ref_call" => Function::new_with_env( + &mut store, + &env, + FunctionType::new([Type::FuncRef], [Type::I32]), + func_ref_call + ), + // "func_ref_call_native" => Function::new_native(&mut store, |f: Function| -> Result { + // let f: TypedFunction::<(i32, i32), i32> = f.typed(&mut store)?; + // f.call(&mut store, 7, 9) + // }) + }, + }; + + let instance = Instance::new(&mut store, &module, &imports)?; + { + fn sum(a: i32, b: i32) -> i32 { + a + b + } + let sum_func = Function::new_typed(&mut store, sum); - { - let f: TypedFunction<(), i32> = instance - .exports - .get_typed_function(&mut store, "call_host_func_with_wasm_func")?; - let result = f.call(&mut store)?; - assert_eq!(result, 63); - } + let call_func: &Function = instance.exports.get_function("call_func")?; + let result = call_func.call(&mut store, &[Value::FuncRef(Some(sum_func))])?; + assert_eq!(result[0].unwrap_i32(), 16); + } - Ok(()) -} + { + let f: TypedFunction<(), i32> = instance + .exports + .get_typed_function(&mut store, "call_host_func_with_wasm_func")?; + let result = f.call(&mut store)?; + assert_eq!(result, 63); + } + Ok(()) + } -#[macro_wasmer_universal_test::universal_test] -fn extern_ref_passed_and_returned() -> Result<()> { - use std::collections::HashMap; - let mut store = Store::default(); - let wat = r#"(module + #[macro_wasmer_universal_test::universal_test] + fn extern_ref_passed_and_returned() -> Result<()> { + use std::collections::HashMap; + let mut store = Store::default(); + let wat = r#"(module (func $extern_ref_identity (import "env" "extern_ref_identity") (param externref) (result externref)) (func $extern_ref_identity_native (import "env" "extern_ref_identity_native") (param externref) (result externref)) (func $get_new_extern_ref (import "env" "get_new_extern_ref") (result externref)) @@ -151,171 +152,168 @@ fn extern_ref_passed_and_returned() -> Result<()> { (func (export "get_hashmap_native") (param) (result externref) (call $get_new_extern_ref_native)) )"#; - let module = Module::new(&store, wat)?; - let env = FunctionEnv::new(&mut store, ()); - let imports = imports! { - "env" => { - "extern_ref_identity" => Function::new_with_env(&mut store, &env, FunctionType::new([Type::ExternRef], [Type::ExternRef]), |_env, values| -> Result, _> { - Ok(vec![values[0].clone()]) - }), - "extern_ref_identity_native" => Function::new_typed(&mut store, |er: Option| -> Option { - er - }), - "get_new_extern_ref" => Function::new_with_env(&mut store, &env, FunctionType::new([], [Type::ExternRef]), |mut env, _| -> Result, _> { - let inner = - [("hello".to_string(), "world".to_string()), - ("color".to_string(), "orange".to_string())] - .iter() - .cloned() - .collect::>(); - let new_extern_ref = ExternRef::new(&mut env, inner); - Ok(vec![Value::ExternRef(Some(new_extern_ref))]) - }), - "get_new_extern_ref_native" => Function::new_typed_with_env(&mut store, &env, |mut env: FunctionEnvMut<()>| -> Option { - let inner = - [("hello".to_string(), "world".to_string()), - ("color".to_string(), "orange".to_string())] - .iter() - .cloned() - .collect::>(); - Some(ExternRef::new(&mut env.as_store_mut(), inner)) - }) - }, - }; - - let instance = Instance::new(&mut store, &module, &imports)?; - for run in &["run", "run_native"] { - let f: &Function = instance.exports.get_function(run)?; - let results = f.call(&mut store, &[]).unwrap(); - if let Value::ExternRef(er) = &results[0] { - assert!(er.is_none()); - } else { - panic!("result is not an extern ref!"); + let module = Module::new(&store, wat)?; + let env = FunctionEnv::new(&mut store, ()); + let imports = imports! { + "env" => { + "extern_ref_identity" => Function::new_with_env(&mut store, &env, FunctionType::new([Type::ExternRef], [Type::ExternRef]), |_env, values| -> Result, _> { + Ok(vec![values[0].clone()]) + }), + "extern_ref_identity_native" => Function::new_typed(&mut store, |er: Option| -> Option { + er + }), + "get_new_extern_ref" => Function::new_with_env(&mut store, &env, FunctionType::new([], [Type::ExternRef]), |mut env, _| -> Result, _> { + let inner = + [("hello".to_string(), "world".to_string()), + ("color".to_string(), "orange".to_string())] + .iter() + .cloned() + .collect::>(); + let new_extern_ref = ExternRef::new(&mut env, inner); + Ok(vec![Value::ExternRef(Some(new_extern_ref))]) + }), + "get_new_extern_ref_native" => Function::new_typed_with_env(&mut store, &env, |mut env: FunctionEnvMut<()>| -> Option { + let inner = + [("hello".to_string(), "world".to_string()), + ("color".to_string(), "orange".to_string())] + .iter() + .cloned() + .collect::>(); + Some(ExternRef::new(&mut env.as_store_mut(), inner)) + }) + }, + }; + + let instance = Instance::new(&mut store, &module, &imports)?; + for run in &["run", "run_native"] { + let f: &Function = instance.exports.get_function(run)?; + let results = f.call(&mut store, &[]).unwrap(); + if let Value::ExternRef(er) = &results[0] { + assert!(er.is_none()); + } else { + panic!("result is not an extern ref!"); + } + + let f: TypedFunction<(), Option> = + instance.exports.get_typed_function(&store, run)?; + let result: Option = f.call(&mut store)?; + assert!(result.is_none()); } - let f: TypedFunction<(), Option> = - instance.exports.get_typed_function(&store, run)?; - let result: Option = f.call(&mut store)?; - assert!(result.is_none()); - } + for get_hashmap in &["get_hashmap", "get_hashmap_native"] { + let f: &Function = instance.exports.get_function(get_hashmap)?; + let results = f.call(&mut store, &[]).unwrap(); + if let Value::ExternRef(er) = &results[0] { + let inner: &HashMap = + er.as_ref().unwrap().downcast(&mut store).unwrap(); + assert_eq!(inner["hello"], "world"); + assert_eq!(inner["color"], "orange"); + } else { + panic!("result is not an extern ref!"); + } - for get_hashmap in &["get_hashmap", "get_hashmap_native"] { - let f: &Function = instance.exports.get_function(get_hashmap)?; - let results = f.call(&mut store, &[]).unwrap(); - if let Value::ExternRef(er) = &results[0] { - let inner: &HashMap = - er.as_ref().unwrap().downcast(&mut store).unwrap(); + let f: TypedFunction<(), Option> = + instance.exports.get_typed_function(&store, get_hashmap)?; + + let result: Option = f.call(&mut store)?; + let inner: &HashMap = result.unwrap().downcast(&mut store).unwrap(); assert_eq!(inner["hello"], "world"); assert_eq!(inner["color"], "orange"); - } else { - panic!("result is not an extern ref!"); } - let f: TypedFunction<(), Option> = - instance.exports.get_typed_function(&store, get_hashmap)?; - - let result: Option = f.call(&mut store)?; - let inner: &HashMap = result.unwrap().downcast(&mut store).unwrap(); - assert_eq!(inner["hello"], "world"); - assert_eq!(inner["color"], "orange"); + Ok(()) } - Ok(()) -} - - -#[universal_test] -fn extern_ref_ref_counting_basic() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module + #[universal_test] + fn extern_ref_ref_counting_basic() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module (func (export "drop") (param $er externref) (result) (drop (local.get $er))) )"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut store, &module, &imports! {})?; - let f: TypedFunction, ()> = - instance.exports.get_typed_function(&store, "drop")?; - - let er = ExternRef::new(&mut store, 3u32); - f.call(&mut store, Some(er.clone()))?; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&mut store, &module, &imports! {})?; + let f: TypedFunction, ()> = + instance.exports.get_typed_function(&store, "drop")?; - let tmp: Option<&u32> = er.downcast(&mut store); - assert_eq!(tmp.unwrap(), &3); + let er = ExternRef::new(&mut store, 3u32); + f.call(&mut store, Some(er.clone()))?; - Ok(()) -} + let tmp: Option<&u32> = er.downcast(&mut store); + assert_eq!(tmp.unwrap(), &3); + Ok(()) + } -#[universal_test] -fn refs_in_globals() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module + #[universal_test] + fn refs_in_globals() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module (global $er_global (export "er_global") (mut externref) (ref.null extern)) (global $fr_global (export "fr_global") (mut funcref) (ref.null func)) (global $fr_immutable_global (export "fr_immutable_global") funcref (ref.func $hello)) (func $hello (param) (result i32) (i32.const 73)) )"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut store, &module, &imports! {})?; - { - let er_global: &Global = instance.exports.get_global("er_global")?; - - if let Value::ExternRef(er) = er_global.get(&mut store) { - assert!(er.is_none()); - } else { - panic!("Did not find extern ref in the global"); - } - let extref = Some(ExternRef::new(&mut store, 3u32)); - er_global.set(&mut store, Value::ExternRef(extref))?; - - if let Value::ExternRef(er) = er_global.get(&mut store) { - let tmp: Option<&u32> = er.unwrap().downcast(&mut store); - assert_eq!(tmp.unwrap(), &3); - } else { - panic!("Did not find extern ref in the global"); + let module = Module::new(&store, wat)?; + let instance = Instance::new(&mut store, &module, &imports! {})?; + { + let er_global: &Global = instance.exports.get_global("er_global")?; + + if let Value::ExternRef(er) = er_global.get(&mut store) { + assert!(er.is_none()); + } else { + panic!("Did not find extern ref in the global"); + } + let extref = Some(ExternRef::new(&mut store, 3u32)); + er_global.set(&mut store, Value::ExternRef(extref))?; + + if let Value::ExternRef(er) = er_global.get(&mut store) { + let tmp: Option<&u32> = er.unwrap().downcast(&mut store); + assert_eq!(tmp.unwrap(), &3); + } else { + panic!("Did not find extern ref in the global"); + } } - } - { - let fr_global: &Global = instance.exports.get_global("fr_immutable_global")?; + { + let fr_global: &Global = instance.exports.get_global("fr_immutable_global")?; - if let Value::FuncRef(Some(f)) = fr_global.get(&mut store) { - let native_func: TypedFunction<(), u32> = f.typed(&mut store)?; - assert_eq!(native_func.call(&mut store)?, 73); - } else { - panic!("Did not find non-null func ref in the global"); + if let Value::FuncRef(Some(f)) = fr_global.get(&mut store) { + let native_func: TypedFunction<(), u32> = f.typed(&mut store)?; + assert_eq!(native_func.call(&mut store)?, 73); + } else { + panic!("Did not find non-null func ref in the global"); + } } - } - { - let fr_global: &Global = instance.exports.get_global("fr_global")?; + { + let fr_global: &Global = instance.exports.get_global("fr_global")?; - if let Value::FuncRef(None) = fr_global.get(&mut store) { - } else { - panic!("Did not find a null func ref in the global"); - } + if let Value::FuncRef(None) = fr_global.get(&mut store) { + } else { + panic!("Did not find a null func ref in the global"); + } - let f = Function::new_typed(&mut store, |arg1: i32, arg2: i32| -> i32 { arg1 + arg2 }); + let f = Function::new_typed(&mut store, |arg1: i32, arg2: i32| -> i32 { arg1 + arg2 }); - fr_global.set(&mut store, Value::FuncRef(Some(f)))?; + fr_global.set(&mut store, Value::FuncRef(Some(f)))?; - if let Value::FuncRef(Some(f)) = fr_global.get(&mut store) { - let native: TypedFunction<(i32, i32), i32> = f.typed(&mut store)?; - assert_eq!(native.call(&mut store, 5, 7)?, 12); - } else { - panic!("Did not find extern ref in the global"); + if let Value::FuncRef(Some(f)) = fr_global.get(&mut store) { + let native: TypedFunction<(i32, i32), i32> = f.typed(&mut store)?; + assert_eq!(native.call(&mut store, 5, 7)?, 12); + } else { + panic!("Did not find extern ref in the global"); + } } - } - - Ok(()) -} + Ok(()) + } -#[universal_test] -fn extern_ref_ref_counting_table_basic() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module + #[universal_test] + fn extern_ref_ref_counting_table_basic() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module (global $global (export "global") (mut externref) (ref.null extern)) (table $table (export "table") 4 4 externref) (func $insert (param $er externref) (param $idx i32) @@ -326,93 +324,90 @@ fn extern_ref_ref_counting_table_basic() -> Result<()> { (call $intermediate (local.get $er) (local.get $idx)) (local.get $er)) )"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut store, &module, &imports! {})?; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&mut store, &module, &imports! {})?; - let f: TypedFunction<(Option, i32), Option> = instance - .exports - .get_typed_function(&mut store, "insert_into_table")?; - - let er = ExternRef::new(&mut store, 3usize); + let f: TypedFunction<(Option, i32), Option> = instance + .exports + .get_typed_function(&mut store, "insert_into_table")?; - let er = f.call(&mut store, Some(er), 1)?; - assert!(er.is_some()); + let er = ExternRef::new(&mut store, 3usize); - let table: &Table = instance.exports.get_table("table")?; + let er = f.call(&mut store, Some(er), 1)?; + assert!(er.is_some()); - { - let er2 = table.get(&mut store, 1).unwrap(); - let er2 = er2.externref().unwrap(); - assert!(er2.is_some()); - } + let table: &Table = instance.exports.get_table("table")?; - assert!(er.is_some()); - table.set(&mut store, 1, Value::ExternRef(None))?; + { + let er2 = table.get(&mut store, 1).unwrap(); + let er2 = er2.externref().unwrap(); + assert!(er2.is_some()); + } - assert!(er.is_some()); + assert!(er.is_some()); + table.set(&mut store, 1, Value::ExternRef(None))?; - Ok(()) -} + assert!(er.is_some()); + Ok(()) + } -#[universal_test] -fn extern_ref_ref_counting_global_basic() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module + #[universal_test] + fn extern_ref_ref_counting_global_basic() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module (global $global (export "global") (mut externref) (ref.null extern)) (func $get_from_global (export "get_from_global") (result externref) (drop (global.get $global)) (global.get $global)) )"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut store, &module, &imports! {})?; - - let global: &Global = instance.exports.get_global("global")?; - { - let er = ExternRef::new(&mut store, 3usize); - global.set(&mut store, Value::ExternRef(Some(er.clone())))?; - } - let get_from_global: TypedFunction<(), Option> = instance - .exports - .get_typed_function(&mut store, "get_from_global")?; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&mut store, &module, &imports! {})?; - let er = get_from_global.call(&mut store)?; - assert!(er.is_some()); - global.set(&mut store, Value::ExternRef(None))?; - assert!(er.is_some()); + let global: &Global = instance.exports.get_global("global")?; + { + let er = ExternRef::new(&mut store, 3usize); + global.set(&mut store, Value::ExternRef(Some(er.clone())))?; + } + let get_from_global: TypedFunction<(), Option> = instance + .exports + .get_typed_function(&mut store, "get_from_global")?; - Ok(()) -} + let er = get_from_global.call(&mut store)?; + assert!(er.is_some()); + global.set(&mut store, Value::ExternRef(None))?; + assert!(er.is_some()); + Ok(()) + } -#[universal_test] -fn extern_ref_ref_counting_traps() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module + #[universal_test] + fn extern_ref_ref_counting_traps() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module (func $pass_er (export "pass_extern_ref") (param externref) (local.get 0) (unreachable)) )"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut store, &module, &imports! {})?; - - let pass_extern_ref: TypedFunction, ()> = instance - .exports - .get_typed_function(&mut store, "pass_extern_ref")?; + let module = Module::new(&store, wat)?; + let instance = Instance::new(&mut store, &module, &imports! {})?; - let er = ExternRef::new(&mut store, 3usize); + let pass_extern_ref: TypedFunction, ()> = instance + .exports + .get_typed_function(&mut store, "pass_extern_ref")?; - let result = pass_extern_ref.call(&mut store, Some(er.clone())); - assert!(result.is_err()); + let er = ExternRef::new(&mut store, 3usize); - Ok(()) -} + let result = pass_extern_ref.call(&mut store, Some(er.clone())); + assert!(result.is_err()); + Ok(()) + } -#[universal_test] -fn extern_ref_ref_counting_table_instructions() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module + #[universal_test] + fn extern_ref_ref_counting_table_instructions() -> Result<()> { + let mut store = Store::default(); + let wat = r#"(module (table $table1 (export "table1") 2 12 externref) (table $table2 (export "table2") 6 12 externref) (func $grow_table_with_ref (export "grow_table_with_ref") (param $er externref) (param $size i32) (result i32) @@ -422,76 +417,77 @@ fn extern_ref_ref_counting_table_instructions() -> Result<()> { (func $copy_into_table2 (export "copy_into_table2") (table.copy $table2 $table1 (i32.const 0) (i32.const 0) (i32.const 4))) )"#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&mut store, &module, &imports! {})?; - - let grow_table_with_ref: TypedFunction<(Option, i32), i32> = instance - .exports - .get_typed_function(&mut store, "grow_table_with_ref")?; - let fill_table_with_ref: TypedFunction<(Option, i32, i32), ()> = instance - .exports - .get_typed_function(&mut store, "fill_table_with_ref")?; - let copy_into_table2: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "copy_into_table2")?; - let table1: &Table = instance.exports.get_table("table1")?; - let table2: &Table = instance.exports.get_table("table2")?; - - let er1 = ExternRef::new(&mut store, 3usize); - let er2 = ExternRef::new(&mut store, 5usize); - let er3 = ExternRef::new(&mut store, 7usize); - { - let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 0)?; - assert_eq!(result, 2); - - let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 10_000)?; - assert_eq!(result, -1); - - let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 8)?; - assert_eq!(result, 2); - - for i in 2..10 { - let v = table1.get(&mut store, i); - let e = v.as_ref().unwrap().unwrap_externref(); - let e_val: Option<&usize> = e.as_ref().unwrap().downcast(&mut store); - assert_eq!(*e_val.unwrap(), 3); + let module = Module::new(&store, wat)?; + let instance = Instance::new(&mut store, &module, &imports! {})?; + + let grow_table_with_ref: TypedFunction<(Option, i32), i32> = instance + .exports + .get_typed_function(&mut store, "grow_table_with_ref")?; + let fill_table_with_ref: TypedFunction<(Option, i32, i32), ()> = instance + .exports + .get_typed_function(&mut store, "fill_table_with_ref")?; + let copy_into_table2: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "copy_into_table2")?; + let table1: &Table = instance.exports.get_table("table1")?; + let table2: &Table = instance.exports.get_table("table2")?; + + let er1 = ExternRef::new(&mut store, 3usize); + let er2 = ExternRef::new(&mut store, 5usize); + let er3 = ExternRef::new(&mut store, 7usize); + { + let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 0)?; + assert_eq!(result, 2); + + let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 10_000)?; + assert_eq!(result, -1); + + let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 8)?; + assert_eq!(result, 2); + + for i in 2..10 { + let v = table1.get(&mut store, i); + let e = v.as_ref().unwrap().unwrap_externref(); + let e_val: Option<&usize> = e.as_ref().unwrap().downcast(&mut store); + assert_eq!(*e_val.unwrap(), 3); + } } - } - { - fill_table_with_ref.call(&mut store, Some(er2.clone()), 0, 2)?; - } + { + fill_table_with_ref.call(&mut store, Some(er2.clone()), 0, 2)?; + } - { - table2.set(&mut store, 0, Value::ExternRef(Some(er3.clone())))?; - table2.set(&mut store, 1, Value::ExternRef(Some(er3.clone())))?; - table2.set(&mut store, 2, Value::ExternRef(Some(er3.clone())))?; - table2.set(&mut store, 3, Value::ExternRef(Some(er3.clone())))?; - table2.set(&mut store, 4, Value::ExternRef(Some(er3.clone())))?; - } + { + table2.set(&mut store, 0, Value::ExternRef(Some(er3.clone())))?; + table2.set(&mut store, 1, Value::ExternRef(Some(er3.clone())))?; + table2.set(&mut store, 2, Value::ExternRef(Some(er3.clone())))?; + table2.set(&mut store, 3, Value::ExternRef(Some(er3.clone())))?; + table2.set(&mut store, 4, Value::ExternRef(Some(er3.clone())))?; + } - { - copy_into_table2.call(&mut store)?; - for i in 1..5 { - let v = table2.get(&mut store, i); - let e = v.as_ref().unwrap().unwrap_externref(); - let value: &usize = e.as_ref().unwrap().downcast(&mut store).unwrap(); - match i { - 0 | 1 => assert_eq!(*value, 5), - 4 => assert_eq!(*value, 7), - _ => assert_eq!(*value, 3), + { + copy_into_table2.call(&mut store)?; + for i in 1..5 { + let v = table2.get(&mut store, i); + let e = v.as_ref().unwrap().unwrap_externref(); + let value: &usize = e.as_ref().unwrap().downcast(&mut store).unwrap(); + match i { + 0 | 1 => assert_eq!(*value, 5), + 4 => assert_eq!(*value, 7), + _ => assert_eq!(*value, 3), + } } } - } - { - for i in 0..table1.size(&mut store) { - table1.set(&mut store, i, Value::ExternRef(None))?; - } - for i in 0..table2.size(&mut store) { - table2.set(&mut store, i, Value::ExternRef(None))?; + { + for i in 0..table1.size(&mut store) { + table1.set(&mut store, i, Value::ExternRef(None))?; + } + for i in 0..table2.size(&mut store) { + table2.set(&mut store, i, Value::ExternRef(None))?; + } } - } - Ok(()) -} \ No newline at end of file + Ok(()) + } +} From d4419020b94da2d5ff21a10e0e5b5388a31a74ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Sch=C3=BCtt?= Date: Fri, 2 Sep 2022 16:32:09 +0200 Subject: [PATCH 07/14] Fix "make lint" --- lib/api/tests/reference_types.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/api/tests/reference_types.rs b/lib/api/tests/reference_types.rs index 36c47ae884f..aecd46d48ec 100644 --- a/lib/api/tests/reference_types.rs +++ b/lib/api/tests/reference_types.rs @@ -1,14 +1,14 @@ -use anyhow::Result; -use macro_wasmer_universal_test::universal_test; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Arc; -#[cfg(feature = "js")] -use wasm_bindgen_test::*; -use wasmer::*; - #[cfg(feature = "sys")] pub mod reference_types { + use anyhow::Result; + use macro_wasmer_universal_test::universal_test; + use std::sync::atomic::{AtomicBool, Ordering}; + use std::sync::Arc; + #[cfg(feature = "js")] + use wasm_bindgen_test::*; + use wasmer::*; + #[universal_test] fn func_ref_passed_and_returned() -> Result<()> { let mut store = Store::default(); From f6c58990d3fd4c680bae34c636010ff2c9b1ec31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Sch=C3=BCtt?= Date: Mon, 5 Sep 2022 12:15:39 +0200 Subject: [PATCH 08/14] Comment out tests that weren't run on JS before --- lib/api/tests/externals.rs | 92 ++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 34 deletions(-) diff --git a/lib/api/tests/externals.rs b/lib/api/tests/externals.rs index 66bf54dcb7e..4e507967365 100644 --- a/lib/api/tests/externals.rs +++ b/lib/api/tests/externals.rs @@ -32,14 +32,26 @@ fn global_new() -> Result<()> { #[universal_test] fn global_get() -> Result<()> { let mut store = Store::default(); + let global_i32 = Global::new(&mut store, Value::I32(10)); assert_eq!(global_i32.get(&mut store), Value::I32(10)); - let global_i64 = Global::new(&mut store, Value::I64(20)); - assert_eq!(global_i64.get(&mut store), Value::I64(20)); + + // 64-bit values are not yet fully supported in some versions of Node + #[cfg(feature = "sys")] + { + let global_i64 = Global::new(&mut store, Value::I64(20)); + assert_eq!(global_i64.get(&mut store), Value::I64(20)); + } + let global_f32 = Global::new(&mut store, Value::F32(10.0)); assert_eq!(global_f32.get(&mut store), Value::F32(10.0)); - let global_f64 = Global::new(&mut store, Value::F64(20.0)); - assert_eq!(global_f64.get(&mut store), Value::F64(20.0)); + + // 64-bit values are not yet fully supported in some versions of Node + #[cfg(feature = "sys")] + { + let global_f64 = Global::new(&mut store, Value::F64(20.0)); + assert_eq!(global_f64.get(&mut store), Value::F64(20.0)); + } Ok(()) } @@ -88,17 +100,22 @@ fn table_new() -> Result<()> { #[universal_test] fn table_get() -> Result<()> { - let mut store = Store::default(); - let table_type = TableType { - ty: Type::FuncRef, - minimum: 0, - maximum: Some(1), - }; - let f = Function::new_typed(&mut store, |num: i32| num + 1); - let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f)))?; - assert_eq!(table.ty(&mut store), table_type); - let _elem = table.get(&mut store, 0).unwrap(); - // assert_eq!(elem.funcref().unwrap(), f); + // Tables are not yet fully supported in Wasm + #[cfg(feature = "sys")] + { + let mut store = Store::default(); + let table_type = TableType { + ty: Type::FuncRef, + minimum: 0, + maximum: Some(1), + }; + let f = Function::new_typed(&mut store, |num: i32| num + 1); + let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f)))?; + assert_eq!(table.ty(&mut store), table_type); + let _elem = table.get(&mut store, 0).unwrap(); + // assert_eq!(elem.funcref().unwrap(), f); + } + Ok(()) } @@ -110,21 +127,25 @@ fn table_set() -> Result<()> { #[universal_test] fn table_grow() -> Result<()> { - let mut store = Store::default(); - let table_type = TableType { - ty: Type::FuncRef, - minimum: 0, - maximum: Some(10), - }; - let f = Function::new_typed(&mut store, |num: i32| num + 1); - let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f.clone())))?; - // Growing to a bigger maximum should return None - let old_len = table.grow(&mut store, 12, Value::FuncRef(Some(f.clone()))); - assert!(old_len.is_err()); - - // Growing to a bigger maximum should return None - let old_len = table.grow(&mut store, 5, Value::FuncRef(Some(f)))?; - assert_eq!(old_len, 0); + // Tables are not yet fully supported in Wasm + #[cfg(feature = "sys")] + { + let mut store = Store::default(); + let table_type = TableType { + ty: Type::FuncRef, + minimum: 0, + maximum: Some(10), + }; + let f = Function::new_typed(&mut store, |num: i32| num + 1); + let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f.clone())))?; + // Growing to a bigger maximum should return None + let old_len = table.grow(&mut store, 12, Value::FuncRef(Some(f.clone()))); + assert!(old_len.is_err()); + + // Growing to a bigger maximum should return None + let old_len = table.grow(&mut store, 5, Value::FuncRef(Some(f)))?; + assert_eq!(old_len, 0); + } Ok(()) } @@ -169,10 +190,13 @@ fn memory_grow() -> Result<()> { }) ); - let bad_desc = MemoryType::new(Pages(15), Some(Pages(10)), false); - let bad_result = Memory::new(&mut store, bad_desc); - - assert!(matches!(bad_result, Err(MemoryError::InvalidMemory { .. }))); + // JS will never give BadMemory unless V8 is broken somehow + #[cfg(feature = "sys")] + { + let bad_desc = MemoryType::new(Pages(15), Some(Pages(10)), false); + let bad_result = Memory::new(&mut store, bad_desc); + assert!(matches!(bad_result, Err(MemoryError::InvalidMemory { .. }))); + } Ok(()) } From 0f1db67115434c06840bef8b6a492bcace252652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Sch=C3=BCtt?= Date: Mon, 5 Sep 2022 12:19:51 +0200 Subject: [PATCH 09/14] Disable table_get test (was not enabled previously) --- lib/api/tests/externals.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/api/tests/externals.rs b/lib/api/tests/externals.rs index 4e507967365..6f507ff84a1 100644 --- a/lib/api/tests/externals.rs +++ b/lib/api/tests/externals.rs @@ -99,6 +99,7 @@ fn table_new() -> Result<()> { } #[universal_test] +#[cfg_attr(feature = "sys", ignore)] fn table_get() -> Result<()> { // Tables are not yet fully supported in Wasm #[cfg(feature = "sys")] From 8eba3c3245ea84140769ad6a4c1569ce3b5e8acd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Sch=C3=BCtt?= Date: Mon, 5 Sep 2022 13:24:49 +0200 Subject: [PATCH 10/14] Fix universal_test panicking --- lib/api/tests/externals.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/api/tests/externals.rs b/lib/api/tests/externals.rs index 6f507ff84a1..432d1e0698e 100644 --- a/lib/api/tests/externals.rs +++ b/lib/api/tests/externals.rs @@ -98,8 +98,8 @@ fn table_new() -> Result<()> { Ok(()) } -#[universal_test] #[cfg_attr(feature = "sys", ignore)] +#[universal_test] fn table_get() -> Result<()> { // Tables are not yet fully supported in Wasm #[cfg(feature = "sys")] From d7fc2899b33341bc8b3c81f7ba14656d7b0b3b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Sch=C3=BCtt?= Date: Mon, 5 Sep 2022 13:41:36 +0200 Subject: [PATCH 11/14] Switch Result<(), anyhow::Error> to Result<(), String> This will make the tests pass on no-std JS --- lib/api/tests/externals.rs | 52 ++++++++++++++++-------------- lib/api/tests/instance.rs | 23 +++++++++----- lib/api/tests/module.rs | 65 ++++++++++++++++++++++---------------- 3 files changed, 81 insertions(+), 59 deletions(-) diff --git a/lib/api/tests/externals.rs b/lib/api/tests/externals.rs index 432d1e0698e..f5f7ac0c9e0 100644 --- a/lib/api/tests/externals.rs +++ b/lib/api/tests/externals.rs @@ -1,4 +1,3 @@ -use anyhow::Result; use macro_wasmer_universal_test::universal_test; #[cfg(feature = "js")] use wasm_bindgen_test::*; @@ -6,7 +5,7 @@ use wasm_bindgen_test::*; use wasmer::*; #[universal_test] -fn global_new() -> Result<()> { +fn global_new() -> Result<(), String> { let mut store = Store::default(); let global = Global::new(&mut store, Value::I32(10)); assert_eq!( @@ -30,7 +29,7 @@ fn global_new() -> Result<()> { } #[universal_test] -fn global_get() -> Result<()> { +fn global_get() -> Result<(), String> { let mut store = Store::default(); let global_i32 = Global::new(&mut store, Value::I32(10)); @@ -57,7 +56,7 @@ fn global_get() -> Result<()> { } #[universal_test] -fn global_set() -> Result<()> { +fn global_set() -> Result<(), String> { let mut store = Store::default(); let global_i32 = Global::new(&mut store, Value::I32(10)); // Set on a constant should error @@ -68,14 +67,16 @@ fn global_set() -> Result<()> { assert!(global_i32_mut.set(&mut store, Value::I64(20)).is_err()); // Set on same type should succeed - global_i32_mut.set(&mut store, Value::I32(20))?; + global_i32_mut + .set(&mut store, Value::I32(20)) + .map_err(|e| format!("{e:?}"))?; assert_eq!(global_i32_mut.get(&mut store), Value::I32(20)); Ok(()) } #[universal_test] -fn table_new() -> Result<()> { +fn table_new() -> Result<(), String> { let mut store = Store::default(); let table_type = TableType { ty: Type::FuncRef, @@ -83,7 +84,8 @@ fn table_new() -> Result<()> { maximum: None, }; let f = Function::new_typed(&mut store, || {}); - let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f)))?; + let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f))) + .map_err(|e| format!("{e:?}"))?; assert_eq!(table.ty(&mut store), table_type); // Anyrefs not yet supported @@ -92,7 +94,7 @@ fn table_new() -> Result<()> { // minimum: 0, // maximum: None, // }; - // let table = Table::new(&store, table_type, Value::ExternRef(ExternRef::Null))?; + // let table = Table::new(&store, table_type, Value::ExternRef(ExternRef::Null)).map_err(|e| format!("{e:?}"))?; // assert_eq!(*table.ty(), table_type); Ok(()) @@ -100,7 +102,7 @@ fn table_new() -> Result<()> { #[cfg_attr(feature = "sys", ignore)] #[universal_test] -fn table_get() -> Result<()> { +fn table_get() -> Result<(), String> { // Tables are not yet fully supported in Wasm #[cfg(feature = "sys")] { @@ -111,7 +113,8 @@ fn table_get() -> Result<()> { maximum: Some(1), }; let f = Function::new_typed(&mut store, |num: i32| num + 1); - let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f)))?; + let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f))) + .map_err(|e| format!("{e:?}"))?; assert_eq!(table.ty(&mut store), table_type); let _elem = table.get(&mut store, 0).unwrap(); // assert_eq!(elem.funcref().unwrap(), f); @@ -121,13 +124,13 @@ fn table_get() -> Result<()> { } #[universal_test] -fn table_set() -> Result<()> { +fn table_set() -> Result<(), String> { // Table set not yet tested Ok(()) } #[universal_test] -fn table_grow() -> Result<()> { +fn table_grow() -> Result<(), String> { // Tables are not yet fully supported in Wasm #[cfg(feature = "sys")] { @@ -138,13 +141,16 @@ fn table_grow() -> Result<()> { maximum: Some(10), }; let f = Function::new_typed(&mut store, |num: i32| num + 1); - let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f.clone())))?; + let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f.clone()))) + .map_err(|e| format!("{e:?}"))?; // Growing to a bigger maximum should return None let old_len = table.grow(&mut store, 12, Value::FuncRef(Some(f.clone()))); assert!(old_len.is_err()); // Growing to a bigger maximum should return None - let old_len = table.grow(&mut store, 5, Value::FuncRef(Some(f)))?; + let old_len = table + .grow(&mut store, 5, Value::FuncRef(Some(f))) + .map_err(|e| format!("{e:?}"))?; assert_eq!(old_len, 0); } @@ -152,30 +158,30 @@ fn table_grow() -> Result<()> { } #[universal_test] -fn table_copy() -> Result<()> { +fn table_copy() -> Result<(), String> { // TODO: table copy test not yet implemented Ok(()) } #[universal_test] -fn memory_new() -> Result<()> { +fn memory_new() -> Result<(), String> { let mut store = Store::default(); let memory_type = MemoryType { shared: false, minimum: Pages(0), maximum: Some(Pages(10)), }; - let memory = Memory::new(&mut store, memory_type)?; + let memory = Memory::new(&mut store, memory_type).map_err(|e| format!("{e:?}"))?; assert_eq!(memory.view(&mut store).size(), Pages(0)); assert_eq!(memory.ty(&mut store), memory_type); Ok(()) } #[universal_test] -fn memory_grow() -> Result<()> { +fn memory_grow() -> Result<(), String> { let mut store = Store::default(); let desc = MemoryType::new(Pages(10), Some(Pages(16)), false); - let memory = Memory::new(&mut store, desc)?; + let memory = Memory::new(&mut store, desc).map_err(|e| format!("{e:?}"))?; assert_eq!(memory.view(&mut store).size(), Pages(10)); let result = memory.grow(&mut store, Pages(2)).unwrap(); @@ -203,7 +209,7 @@ fn memory_grow() -> Result<()> { } #[universal_test] -fn function_new() -> Result<()> { +fn function_new() -> Result<(), String> { let mut store = Store::default(); let function = Function::new_typed(&mut store, || {}); assert_eq!( @@ -234,7 +240,7 @@ fn function_new() -> Result<()> { } #[universal_test] -fn function_new_env() -> Result<()> { +fn function_new_env() -> Result<(), String> { let mut store = Store::default(); #[derive(Clone)] struct MyEnv {} @@ -280,7 +286,7 @@ fn function_new_env() -> Result<()> { } #[universal_test] -fn function_new_dynamic() -> Result<()> { +fn function_new_dynamic() -> Result<(), String> { let mut store = Store::default(); // Using &FunctionType signature @@ -337,7 +343,7 @@ fn function_new_dynamic() -> Result<()> { } #[universal_test] -fn function_new_dynamic_env() -> Result<()> { +fn function_new_dynamic_env() -> Result<(), String> { let mut store = Store::default(); #[derive(Clone)] struct MyEnv {} diff --git a/lib/api/tests/instance.rs b/lib/api/tests/instance.rs index 2f9ca45d1e1..bffdfd81250 100644 --- a/lib/api/tests/instance.rs +++ b/lib/api/tests/instance.rs @@ -1,4 +1,3 @@ -use anyhow::Result; use macro_wasmer_universal_test::universal_test; #[cfg(feature = "js")] use wasm_bindgen_test::*; @@ -6,7 +5,7 @@ use wasm_bindgen_test::*; use wasmer::*; #[universal_test] -fn exports_work_after_multiple_instances_have_been_freed() -> Result<()> { +fn exports_work_after_multiple_instances_have_been_freed() -> Result<(), String> { let mut store = Store::default(); let module = Module::new( &store, @@ -19,15 +18,20 @@ fn exports_work_after_multiple_instances_have_been_freed() -> Result<()> { i32.add) (export \"sum\" (func $sum_f))) ", - )?; + ) + .map_err(|e| format!("{e:?}"))?; let imports = Imports::new(); - let instance = Instance::new(&mut store, &module, &imports)?; + let instance = Instance::new(&mut store, &module, &imports).map_err(|e| format!("{e:?}"))?; let instance2 = instance.clone(); let instance3 = instance.clone(); // The function is cloned to “break” the connection with `instance`. - let sum = instance.exports.get_function("sum")?.clone(); + let sum = instance + .exports + .get_function("sum") + .map_err(|e| format!("{e:?}"))? + .clone(); drop(instance); drop(instance2); @@ -35,7 +39,8 @@ fn exports_work_after_multiple_instances_have_been_freed() -> Result<()> { // All instances have been dropped, but `sum` continues to work! assert_eq!( - sum.call(&mut store, &[Value::I32(1), Value::I32(2)])? + sum.call(&mut store, &[Value::I32(1), Value::I32(2)]) + .map_err(|e| format!("{e:?}"))? .into_vec(), vec![Value::I32(3)], ); @@ -44,7 +49,7 @@ fn exports_work_after_multiple_instances_have_been_freed() -> Result<()> { } #[universal_test] -fn unit_native_function_env() -> Result<()> { +fn unit_native_function_env() -> Result<(), String> { let mut store = Store::default(); #[derive(Clone)] @@ -66,7 +71,9 @@ fn unit_native_function_env() -> Result<()> { let imported = Function::new_with_env(&mut store, &env, imported_signature, imported_fn); let expected = vec![Value::I32(12)].into_boxed_slice(); - let result = imported.call(&mut store, &[Value::I32(4)])?; + let result = imported + .call(&mut store, &[Value::I32(4)]) + .map_err(|e| format!("{e:?}"))?; assert_eq!(result, expected); Ok(()) diff --git a/lib/api/tests/module.rs b/lib/api/tests/module.rs index f174c200433..13ccad34cbb 100644 --- a/lib/api/tests/module.rs +++ b/lib/api/tests/module.rs @@ -1,4 +1,3 @@ -use anyhow::Result; use macro_wasmer_universal_test::universal_test; #[cfg(feature = "js")] use wasm_bindgen_test::*; @@ -6,20 +5,22 @@ use wasm_bindgen_test::*; use wasmer::*; #[universal_test] -fn module_get_name() -> Result<()> { +fn module_get_name() -> Result<(), String> { let store = Store::default(); let wat = r#"(module)"#; - let module = Module::new(&store, wat)?; + let module = Module::new(&store, wat) + .map_err(|e| format!("{e:?}")) + .map_err(|e| format!("{e:?}"))?; assert_eq!(module.name(), None); Ok(()) } #[universal_test] -fn module_set_name() -> Result<()> { +fn module_set_name() -> Result<(), String> { let store = Store::default(); let wat = r#"(module $name)"#; - let mut module = Module::new(&store, wat)?; + let mut module = Module::new(&store, wat).map_err(|e| format!("{e:?}"))?; assert_eq!(module.name(), Some("name")); module.set_name("new_name"); @@ -29,7 +30,7 @@ fn module_set_name() -> Result<()> { } #[universal_test] -fn imports() -> Result<()> { +fn imports() -> Result<(), String> { let store = Store::default(); let wat = r#"(module (import "host" "func" (func)) @@ -37,7 +38,7 @@ fn imports() -> Result<()> { (import "host" "table" (table 1 anyfunc)) (import "host" "global" (global i32)) )"#; - let module = Module::new(&store, wat)?; + let module = Module::new(&store, wat).map_err(|e| format!("{e:?}"))?; assert_eq!( module.imports().collect::>(), vec![ @@ -101,7 +102,7 @@ fn imports() -> Result<()> { } #[universal_test] -fn exports() -> Result<()> { +fn exports() -> Result<(), String> { let store = Store::default(); let wat = r#"(module (func (export "func") nop) @@ -109,7 +110,7 @@ fn exports() -> Result<()> { (table (export "table") 1 funcref) (global (export "global") i32 (i32.const 0)) )"#; - let module = Module::new(&store, wat)?; + let module = Module::new(&store, wat).map_err(|e| format!("{e:?}"))?; assert_eq!( module.exports().collect::>(), vec![ @@ -162,7 +163,7 @@ fn exports() -> Result<()> { } #[universal_test] -fn calling_host_functions_with_negative_values_works() -> Result<()> { +fn calling_host_functions_with_negative_values_works() -> Result<(), String> { let mut store = Store::default(); let wat = r#"(module (import "host" "host_func1" (func (param i64))) @@ -191,7 +192,7 @@ fn calling_host_functions_with_negative_values_works() -> Result<()> { (func (export "call_host_func8") (call 7 (i32.const -1))) )"#; - let module = Module::new(&store, wat)?; + let module = Module::new(&store, wat).map_err(|e| format!("{e:?}"))?; let imports = imports! { "host" => { "host_func1" => Function::new_typed(&mut store, |p: u64| { @@ -228,41 +229,49 @@ fn calling_host_functions_with_negative_values_works() -> Result<()> { }), } }; - let instance = Instance::new(&mut store, &module, &imports)?; + let instance = Instance::new(&mut store, &module, &imports).map_err(|e| format!("{e:?}"))?; let f1: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut store, "call_host_func1")?; + .get_typed_function(&mut store, "call_host_func1") + .map_err(|e| format!("{e:?}"))?; let f2: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut store, "call_host_func2")?; + .get_typed_function(&mut store, "call_host_func2") + .map_err(|e| format!("{e:?}"))?; let f3: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut store, "call_host_func3")?; + .get_typed_function(&mut store, "call_host_func3") + .map_err(|e| format!("{e:?}"))?; let f4: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut store, "call_host_func4")?; + .get_typed_function(&mut store, "call_host_func4") + .map_err(|e| format!("{e:?}"))?; let f5: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut store, "call_host_func5")?; + .get_typed_function(&mut store, "call_host_func5") + .map_err(|e| format!("{e:?}"))?; let f6: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut store, "call_host_func6")?; + .get_typed_function(&mut store, "call_host_func6") + .map_err(|e| format!("{e:?}"))?; let f7: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut store, "call_host_func7")?; + .get_typed_function(&mut store, "call_host_func7") + .map_err(|e| format!("{e:?}"))?; let f8: TypedFunction<(), ()> = instance .exports - .get_typed_function(&mut store, "call_host_func8")?; + .get_typed_function(&mut store, "call_host_func8") + .map_err(|e| format!("{e:?}"))?; - f1.call(&mut store)?; - f2.call(&mut store)?; - f3.call(&mut store)?; - f4.call(&mut store)?; - f5.call(&mut store)?; - f6.call(&mut store)?; - f7.call(&mut store)?; - f8.call(&mut store)?; + f1.call(&mut store).map_err(|e| format!("{e:?}"))?; + f2.call(&mut store).map_err(|e| format!("{e:?}"))?; + f3.call(&mut store).map_err(|e| format!("{e:?}"))?; + f4.call(&mut store).map_err(|e| format!("{e:?}"))?; + f5.call(&mut store).map_err(|e| format!("{e:?}"))?; + f6.call(&mut store).map_err(|e| format!("{e:?}"))?; + f7.call(&mut store).map_err(|e| format!("{e:?}"))?; + f8.call(&mut store).map_err(|e| format!("{e:?}"))?; Ok(()) } From 8f702d2bc4b7d2cc4a76bb5e33625e792764b401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Sch=C3=BCtt?= Date: Mon, 5 Sep 2022 13:58:24 +0200 Subject: [PATCH 12/14] Fix "cargo deny" --- lib/api/macro-wasmer-universal-test/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/api/macro-wasmer-universal-test/Cargo.toml b/lib/api/macro-wasmer-universal-test/Cargo.toml index 8132ddf4854..f6f401ad4b1 100644 --- a/lib/api/macro-wasmer-universal-test/Cargo.toml +++ b/lib/api/macro-wasmer-universal-test/Cargo.toml @@ -2,6 +2,8 @@ name = "macro-wasmer-universal-test" version = "0.1.0" edition = "2021" +license = "MIT" +description = "Universal test macro for wasmer-test" [lib] proc-macro = true From d1062ae851a8dfde0021b2d590d95f9e61357340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Sch=C3=BCtt?= Date: Mon, 5 Sep 2022 14:49:02 +0200 Subject: [PATCH 13/14] Fix "table_get" test again --- lib/api/tests/externals.rs | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/lib/api/tests/externals.rs b/lib/api/tests/externals.rs index f5f7ac0c9e0..e8149b74c5a 100644 --- a/lib/api/tests/externals.rs +++ b/lib/api/tests/externals.rs @@ -100,25 +100,24 @@ fn table_new() -> Result<(), String> { Ok(()) } -#[cfg_attr(feature = "sys", ignore)] #[universal_test] fn table_get() -> Result<(), String> { + // Tables are not yet fully supported in Wasm - #[cfg(feature = "sys")] - { - let mut store = Store::default(); - let table_type = TableType { - ty: Type::FuncRef, - minimum: 0, - maximum: Some(1), - }; - let f = Function::new_typed(&mut store, |num: i32| num + 1); - let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f))) - .map_err(|e| format!("{e:?}"))?; - assert_eq!(table.ty(&mut store), table_type); - let _elem = table.get(&mut store, 0).unwrap(); - // assert_eq!(elem.funcref().unwrap(), f); - } + // This test was marked as #[ignore] on -sys, which is why it is commented out. + + // let mut store = Store::default(); + // let table_type = TableType { + // ty: Type::FuncRef, + // minimum: 0, + // maximum: Some(1), + // }; + // let f = Function::new_typed(&mut store, |num: i32| num + 1); + // let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f))) + // .map_err(|e| format!("{e:?}"))?; + // assert_eq!(table.ty(&mut store), table_type); + // let _elem = table.get(&mut store, 0).unwrap(); + // assert_eq!(elem.funcref().unwrap(), f); Ok(()) } From 2552aec8b7ce8482a9c9c6c556762b607b3dadd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Sch=C3=BCtt?= Date: Mon, 5 Sep 2022 15:27:39 +0200 Subject: [PATCH 14/14] Fix "make lint" --- lib/api/tests/externals.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/api/tests/externals.rs b/lib/api/tests/externals.rs index e8149b74c5a..5c17579a4ab 100644 --- a/lib/api/tests/externals.rs +++ b/lib/api/tests/externals.rs @@ -102,7 +102,6 @@ fn table_new() -> Result<(), String> { #[universal_test] fn table_get() -> Result<(), String> { - // Tables are not yet fully supported in Wasm // This test was marked as #[ignore] on -sys, which is why it is commented out.