mirror of
https://github.com/mii443/wasmer.git
synced 2025-08-23 00:45:32 +00:00
499 lines
16 KiB
Rust
499 lines
16 KiB
Rust
use macro_wasmer_universal_test::universal_test;
|
|
#[cfg(feature = "js")]
|
|
use wasm_bindgen_test::*;
|
|
|
|
use wasmer::*;
|
|
|
|
#[universal_test]
|
|
fn global_new() -> Result<(), String> {
|
|
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
|
|
}
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[universal_test]
|
|
#[cfg_attr(
|
|
feature = "wamr",
|
|
ignore = "wamr does not support globals unattached to instances"
|
|
)]
|
|
fn global_get() -> Result<(), String> {
|
|
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
|
|
#[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));
|
|
|
|
// 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(())
|
|
}
|
|
|
|
#[universal_test]
|
|
#[cfg_attr(
|
|
feature = "wamr",
|
|
ignore = "wamr does not support globals unattached to instances"
|
|
)]
|
|
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
|
|
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))
|
|
.map_err(|e| format!("{e:?}"))?;
|
|
assert_eq!(global_i32_mut.get(&mut store), Value::I32(20));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[universal_test]
|
|
#[cfg_attr(feature = "wasmi", ignore = "wasmi does not support funcrefs")]
|
|
fn table_new() -> Result<(), String> {
|
|
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)))
|
|
.map_err(|e| format!("{e:?}"))?;
|
|
assert_eq!(table.ty(&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)).map_err(|e| format!("{e:?}"))?;
|
|
// assert_eq!(*table.ty(), table_type);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[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.
|
|
|
|
// 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(())
|
|
}
|
|
|
|
#[universal_test]
|
|
fn table_set() -> Result<(), String> {
|
|
// Table set not yet tested
|
|
#[cfg(feature = "sys")]
|
|
{
|
|
let mut store = Store::default();
|
|
|
|
let table_type = TableType {
|
|
ty: Type::ExternRef,
|
|
minimum: 1,
|
|
maximum: None,
|
|
};
|
|
let extern_ref = ExternRef::new(&mut store, 0u32);
|
|
let table = Table::new(
|
|
&mut store,
|
|
table_type,
|
|
Value::ExternRef(Some(extern_ref.clone())),
|
|
)
|
|
.map_err(|e| format!("{e:?}"))?;
|
|
assert_eq!(table.ty(&store), table_type);
|
|
|
|
let v = table.get(&mut store, 0);
|
|
assert!(v.is_some());
|
|
|
|
let v = v.unwrap();
|
|
|
|
let v = if let Value::ExternRef(Some(ext)) = v {
|
|
ext.downcast::<u32>(&mut store)
|
|
} else {
|
|
return Err("table.get does not match `ExternRef(Some(..))`!".into());
|
|
};
|
|
|
|
let v = v.unwrap();
|
|
assert_eq!(*v, 0u32);
|
|
|
|
let extern_ref = ExternRef::new(&mut store, 1u32);
|
|
table
|
|
.set(&mut store, 0, Value::ExternRef(Some(extern_ref)))
|
|
.map_err(|e| e.to_string())?;
|
|
|
|
let v = table.get(&mut store, 0);
|
|
assert!(v.is_some());
|
|
let v = v.unwrap();
|
|
|
|
let v = if let Value::ExternRef(Some(ext)) = v {
|
|
ext.downcast::<u32>(&mut store)
|
|
} else {
|
|
return Err("table.get does not match `ExternRef(Some(..))`!".into());
|
|
};
|
|
|
|
assert!(v.is_some());
|
|
let v = v.unwrap();
|
|
assert_eq!(*v, 1u32);
|
|
|
|
let extern_ref = ExternRef::new(&mut store, 2u32);
|
|
table
|
|
.set(&mut store, 0, Value::ExternRef(Some(extern_ref)))
|
|
.map_err(|e| e.to_string())?;
|
|
|
|
let v = table.get(&mut store, 0);
|
|
assert!(v.is_some());
|
|
let v = v.unwrap();
|
|
|
|
let v = if let Value::ExternRef(Some(ext)) = v {
|
|
ext.downcast::<u32>(&mut store)
|
|
} else {
|
|
return Err("table.get does not match `ExternRef(Some(..))`!".into());
|
|
};
|
|
|
|
assert!(v.is_some());
|
|
let v = v.unwrap();
|
|
assert_eq!(*v, 2u32);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[universal_test]
|
|
fn table_grow() -> 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(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())))
|
|
.map_err(|e| format!("{e:?}"))?;
|
|
|
|
let old_len = table.grow(&mut store, 1, Value::FuncRef(Some(f.clone())));
|
|
assert_eq!(0, old_len.unwrap());
|
|
let old_len = table.grow(&mut store, 1, Value::FuncRef(Some(f.clone())));
|
|
assert_eq!(1, old_len.unwrap());
|
|
|
|
// 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());
|
|
|
|
let old_len = table
|
|
.grow(&mut store, 5, Value::FuncRef(Some(f)))
|
|
.map_err(|e| format!("{e:?}"))?;
|
|
assert_eq!(old_len, 2);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[universal_test]
|
|
fn table_copy() -> Result<(), String> {
|
|
// TODO: table copy test not yet implemented
|
|
Ok(())
|
|
}
|
|
|
|
#[universal_test]
|
|
fn memory_new() -> Result<(), String> {
|
|
let mut store = Store::default();
|
|
let memory_type = MemoryType {
|
|
shared: if cfg!(feature = "wamr") { true } else { false },
|
|
minimum: Pages(0),
|
|
maximum: Some(Pages(10)),
|
|
};
|
|
let memory = Memory::new(&mut store, memory_type).map_err(|e| format!("{e:?}"))?;
|
|
assert_eq!(memory.view(&store).size(), Pages(0));
|
|
assert_eq!(memory.ty(&store), memory_type);
|
|
Ok(())
|
|
}
|
|
|
|
#[universal_test]
|
|
#[cfg_attr(
|
|
feature = "wamr",
|
|
ignore = "wamr does not support direct calls to grow memory"
|
|
)]
|
|
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).map_err(|e| format!("{e:?}"))?;
|
|
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_eq!(
|
|
result,
|
|
Err(MemoryError::CouldNotGrow {
|
|
current: 12.into(),
|
|
attempted_delta: 10.into()
|
|
})
|
|
);
|
|
|
|
// 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(())
|
|
}
|
|
|
|
#[universal_test]
|
|
fn function_new() -> Result<(), String> {
|
|
let mut store = Store::default();
|
|
let function = Function::new_typed(&mut store, || {});
|
|
assert_eq!(function.ty(&store), FunctionType::new(vec![], vec![]));
|
|
let function = Function::new_typed(&mut store, |_a: i32| {});
|
|
assert_eq!(
|
|
function.ty(&store),
|
|
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),
|
|
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),
|
|
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),
|
|
FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64])
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[universal_test]
|
|
fn function_new_env() -> Result<(), String> {
|
|
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<MyEnv>| {});
|
|
assert_eq!(function.ty(&store), FunctionType::new(vec![], vec![]));
|
|
let function =
|
|
Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut<MyEnv>, _a: i32| {});
|
|
assert_eq!(
|
|
function.ty(&store),
|
|
FunctionType::new(vec![Type::I32], vec![])
|
|
);
|
|
let function = Function::new_typed_with_env(
|
|
&mut store,
|
|
&env,
|
|
|_env: FunctionEnvMut<MyEnv>, _a: i32, _b: i64, _c: f32, _d: f64| {},
|
|
);
|
|
assert_eq!(
|
|
function.ty(&store),
|
|
FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![])
|
|
);
|
|
let function =
|
|
Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut<MyEnv>| -> i32 { 1 });
|
|
assert_eq!(
|
|
function.ty(&store),
|
|
FunctionType::new(vec![], vec![Type::I32])
|
|
);
|
|
let function = Function::new_typed_with_env(
|
|
&mut store,
|
|
&env,
|
|
|_env: FunctionEnvMut<MyEnv>| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) },
|
|
);
|
|
assert_eq!(
|
|
function.ty(&store),
|
|
FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64])
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[universal_test]
|
|
fn function_new_dynamic() -> Result<(), String> {
|
|
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), 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), 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), 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), 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), function_type);
|
|
|
|
// wasmi does not support V128 through its wasm_c_api bindings.
|
|
#[cfg(not(any(feature = "wasmi", feature = "v8")))]
|
|
{
|
|
// 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]
|
|
);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[universal_test]
|
|
fn function_new_dynamic_env() -> Result<(), String> {
|
|
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), 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), 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), 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), 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), function_type);
|
|
|
|
// wasmi does not support V128 through its wasm_c_api bindings.
|
|
#[cfg(not(any(feature = "wasmi", feature = "v8")))]
|
|
{
|
|
// 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]
|
|
);
|
|
}
|
|
Ok(())
|
|
}
|