mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-09 22:28:21 +00:00
Separate testing per compiler
This commit is contained in:
@@ -2,196 +2,194 @@
|
||||
//! This tests checks that the provided functions (both native and
|
||||
//! dynamic ones) work properly.
|
||||
|
||||
wasmer_compilers! {
|
||||
use wasmer::*;
|
||||
use anyhow::Result;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
|
||||
use crate::utils::get_store;
|
||||
use anyhow::Result;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
|
||||
use wasmer::*;
|
||||
|
||||
fn get_module(store: &Store) -> Result<Module> {
|
||||
let wat = r#"
|
||||
(import "host" "0" (func))
|
||||
(import "host" "1" (func (param i32) (result i32)))
|
||||
(import "host" "2" (func (param i32) (param i64)))
|
||||
(import "host" "3" (func (param i32 i64 i32 f32 f64)))
|
||||
fn get_module(store: &Store) -> Result<Module> {
|
||||
let wat = r#"
|
||||
(import "host" "0" (func))
|
||||
(import "host" "1" (func (param i32) (result i32)))
|
||||
(import "host" "2" (func (param i32) (param i64)))
|
||||
(import "host" "3" (func (param i32 i64 i32 f32 f64)))
|
||||
|
||||
(func $foo
|
||||
call 0
|
||||
i32.const 0
|
||||
call 1
|
||||
i32.const 1
|
||||
i32.add
|
||||
i64.const 3
|
||||
call 2
|
||||
(func $foo
|
||||
call 0
|
||||
i32.const 0
|
||||
call 1
|
||||
i32.const 1
|
||||
i32.add
|
||||
i64.const 3
|
||||
call 2
|
||||
|
||||
i32.const 100
|
||||
i64.const 200
|
||||
i32.const 300
|
||||
f32.const 400
|
||||
f64.const 500
|
||||
call 3
|
||||
)
|
||||
(start $foo)
|
||||
"#;
|
||||
i32.const 100
|
||||
i64.const 200
|
||||
i32.const 300
|
||||
f32.const 400
|
||||
f64.const 500
|
||||
call 3
|
||||
)
|
||||
(start $foo)
|
||||
"#;
|
||||
|
||||
let module = Module::new(&store, &wat)?;
|
||||
Ok(module)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dynamic_function() -> Result<()> {
|
||||
let store = get_store();
|
||||
let module = get_module(&store)?;
|
||||
static HITS: AtomicUsize = AtomicUsize::new(0);
|
||||
Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"host" => {
|
||||
"0" => Function::new_dynamic(&store, &FunctionType::new(vec![], vec![]), |_values| {
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 0);
|
||||
Ok(vec![])
|
||||
}),
|
||||
"1" => Function::new_dynamic(&store, &FunctionType::new(vec![ValType::I32], vec![ValType::I32]), |values| {
|
||||
assert_eq!(values[0], Value::I32(0));
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 1);
|
||||
Ok(vec![Value::I32(1)])
|
||||
}),
|
||||
"2" => Function::new_dynamic(&store, &FunctionType::new(vec![ValType::I32, ValType::I64], vec![]), |values| {
|
||||
assert_eq!(values[0], Value::I32(2));
|
||||
assert_eq!(values[1], Value::I64(3));
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 2);
|
||||
Ok(vec![])
|
||||
}),
|
||||
"3" => Function::new_dynamic(&store, &FunctionType::new(vec![ValType::I32, ValType::I64, ValType::I32, ValType::F32, ValType::F64], vec![]), |values| {
|
||||
assert_eq!(values[0], Value::I32(100));
|
||||
assert_eq!(values[1], Value::I64(200));
|
||||
assert_eq!(values[2], Value::I32(300));
|
||||
assert_eq!(values[3], Value::F32(400.0));
|
||||
assert_eq!(values[4], Value::F64(500.0));
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 3);
|
||||
Ok(vec![])
|
||||
}),
|
||||
},
|
||||
},
|
||||
)?;
|
||||
assert_eq!(HITS.load(SeqCst), 4);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn dynamic_function_with_env() -> Result<()> {
|
||||
let store = get_store();
|
||||
let module = get_module(&store)?;
|
||||
|
||||
let mut env: AtomicUsize = AtomicUsize::new(0);
|
||||
Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"host" => {
|
||||
"0" => Function::new_dynamic_env(&store, &FunctionType::new(vec![], vec![]), &mut env, |env, _values| {
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 0);
|
||||
Ok(vec![])
|
||||
}),
|
||||
"1" => Function::new_dynamic_env(&store, &FunctionType::new(vec![ValType::I32], vec![ValType::I32]), &mut env, |env, values| {
|
||||
assert_eq!(values[0], Value::I32(0));
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 1);
|
||||
Ok(vec![Value::I32(1)])
|
||||
}),
|
||||
"2" => Function::new_dynamic_env(&store, &FunctionType::new(vec![ValType::I32, ValType::I64], vec![]), &mut env, |env, values| {
|
||||
assert_eq!(values[0], Value::I32(2));
|
||||
assert_eq!(values[1], Value::I64(3));
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 2);
|
||||
Ok(vec![])
|
||||
}),
|
||||
"3" => Function::new_dynamic_env(&store, &FunctionType::new(vec![ValType::I32, ValType::I64, ValType::I32, ValType::F32, ValType::F64], vec![]), &mut env, |env, values| {
|
||||
assert_eq!(values[0], Value::I32(100));
|
||||
assert_eq!(values[1], Value::I64(200));
|
||||
assert_eq!(values[2], Value::I32(300));
|
||||
assert_eq!(values[3], Value::F32(400.0));
|
||||
assert_eq!(values[4], Value::F64(500.0));
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 3);
|
||||
Ok(vec![])
|
||||
}),
|
||||
},
|
||||
},
|
||||
)?;
|
||||
assert_eq!(env.load(SeqCst), 4);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn native_function() -> Result<()> {
|
||||
let store = get_store();
|
||||
let module = get_module(&store)?;
|
||||
|
||||
static HITS: AtomicUsize = AtomicUsize::new(0);
|
||||
Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"host" => {
|
||||
"0" => Function::new(&store, || {
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 0);
|
||||
}),
|
||||
"1" => Function::new(&store, |x: i32| -> i32 {
|
||||
assert_eq!(x, 0);
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 1);
|
||||
1
|
||||
}),
|
||||
"2" => Function::new(&store, |x: i32, y: i64| {
|
||||
assert_eq!(x, 2);
|
||||
assert_eq!(y, 3);
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 2);
|
||||
}),
|
||||
"3" => Function::new(&store, |a: i32, b: i64, c: i32, d: f32, e: f64| {
|
||||
assert_eq!(a, 100);
|
||||
assert_eq!(b, 200);
|
||||
assert_eq!(c, 300);
|
||||
assert_eq!(d, 400.0);
|
||||
assert_eq!(e, 500.0);
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 3);
|
||||
}),
|
||||
},
|
||||
},
|
||||
)?;
|
||||
assert_eq!(HITS.load(SeqCst), 4);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn native_function_with_env() -> Result<()> {
|
||||
let store = get_store();
|
||||
let module = get_module(&store)?;
|
||||
|
||||
let mut env: AtomicUsize = AtomicUsize::new(0);
|
||||
Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"host" => {
|
||||
"0" => Function::new_env(&store, &mut env, |env: &mut AtomicUsize| {
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 0);
|
||||
}),
|
||||
"1" => Function::new_env(&store, &mut env, |env: &mut AtomicUsize, x: i32| -> i32 {
|
||||
assert_eq!(x, 0);
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 1);
|
||||
1
|
||||
}),
|
||||
"2" => Function::new_env(&store, &mut env, |env: &mut AtomicUsize, x: i32, y: i64| {
|
||||
assert_eq!(x, 2);
|
||||
assert_eq!(y, 3);
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 2);
|
||||
}),
|
||||
"3" => Function::new_env(&store, &mut env, |env: &mut AtomicUsize, a: i32, b: i64, c: i32, d: f32, e: f64| {
|
||||
assert_eq!(a, 100);
|
||||
assert_eq!(b, 200);
|
||||
assert_eq!(c, 300);
|
||||
assert_eq!(d, 400.0);
|
||||
assert_eq!(e, 500.0);
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 3);
|
||||
}),
|
||||
},
|
||||
},
|
||||
)?;
|
||||
assert_eq!(env.load(SeqCst), 4);
|
||||
Ok(())
|
||||
}
|
||||
let module = Module::new(&store, &wat)?;
|
||||
Ok(module)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dynamic_function() -> Result<()> {
|
||||
let store = get_store();
|
||||
let module = get_module(&store)?;
|
||||
static HITS: AtomicUsize = AtomicUsize::new(0);
|
||||
Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"host" => {
|
||||
"0" => Function::new_dynamic(&store, &FunctionType::new(vec![], vec![]), |_values| {
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 0);
|
||||
Ok(vec![])
|
||||
}),
|
||||
"1" => Function::new_dynamic(&store, &FunctionType::new(vec![ValType::I32], vec![ValType::I32]), |values| {
|
||||
assert_eq!(values[0], Value::I32(0));
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 1);
|
||||
Ok(vec![Value::I32(1)])
|
||||
}),
|
||||
"2" => Function::new_dynamic(&store, &FunctionType::new(vec![ValType::I32, ValType::I64], vec![]), |values| {
|
||||
assert_eq!(values[0], Value::I32(2));
|
||||
assert_eq!(values[1], Value::I64(3));
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 2);
|
||||
Ok(vec![])
|
||||
}),
|
||||
"3" => Function::new_dynamic(&store, &FunctionType::new(vec![ValType::I32, ValType::I64, ValType::I32, ValType::F32, ValType::F64], vec![]), |values| {
|
||||
assert_eq!(values[0], Value::I32(100));
|
||||
assert_eq!(values[1], Value::I64(200));
|
||||
assert_eq!(values[2], Value::I32(300));
|
||||
assert_eq!(values[3], Value::F32(400.0));
|
||||
assert_eq!(values[4], Value::F64(500.0));
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 3);
|
||||
Ok(vec![])
|
||||
}),
|
||||
},
|
||||
},
|
||||
)?;
|
||||
assert_eq!(HITS.load(SeqCst), 4);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dynamic_function_with_env() -> Result<()> {
|
||||
let store = get_store();
|
||||
let module = get_module(&store)?;
|
||||
|
||||
let mut env: AtomicUsize = AtomicUsize::new(0);
|
||||
Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"host" => {
|
||||
"0" => Function::new_dynamic_env(&store, &FunctionType::new(vec![], vec![]), &mut env, |env, _values| {
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 0);
|
||||
Ok(vec![])
|
||||
}),
|
||||
"1" => Function::new_dynamic_env(&store, &FunctionType::new(vec![ValType::I32], vec![ValType::I32]), &mut env, |env, values| {
|
||||
assert_eq!(values[0], Value::I32(0));
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 1);
|
||||
Ok(vec![Value::I32(1)])
|
||||
}),
|
||||
"2" => Function::new_dynamic_env(&store, &FunctionType::new(vec![ValType::I32, ValType::I64], vec![]), &mut env, |env, values| {
|
||||
assert_eq!(values[0], Value::I32(2));
|
||||
assert_eq!(values[1], Value::I64(3));
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 2);
|
||||
Ok(vec![])
|
||||
}),
|
||||
"3" => Function::new_dynamic_env(&store, &FunctionType::new(vec![ValType::I32, ValType::I64, ValType::I32, ValType::F32, ValType::F64], vec![]), &mut env, |env, values| {
|
||||
assert_eq!(values[0], Value::I32(100));
|
||||
assert_eq!(values[1], Value::I64(200));
|
||||
assert_eq!(values[2], Value::I32(300));
|
||||
assert_eq!(values[3], Value::F32(400.0));
|
||||
assert_eq!(values[4], Value::F64(500.0));
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 3);
|
||||
Ok(vec![])
|
||||
}),
|
||||
},
|
||||
},
|
||||
)?;
|
||||
assert_eq!(env.load(SeqCst), 4);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn native_function() -> Result<()> {
|
||||
let store = get_store();
|
||||
let module = get_module(&store)?;
|
||||
|
||||
static HITS: AtomicUsize = AtomicUsize::new(0);
|
||||
Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"host" => {
|
||||
"0" => Function::new(&store, || {
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 0);
|
||||
}),
|
||||
"1" => Function::new(&store, |x: i32| -> i32 {
|
||||
assert_eq!(x, 0);
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 1);
|
||||
1
|
||||
}),
|
||||
"2" => Function::new(&store, |x: i32, y: i64| {
|
||||
assert_eq!(x, 2);
|
||||
assert_eq!(y, 3);
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 2);
|
||||
}),
|
||||
"3" => Function::new(&store, |a: i32, b: i64, c: i32, d: f32, e: f64| {
|
||||
assert_eq!(a, 100);
|
||||
assert_eq!(b, 200);
|
||||
assert_eq!(c, 300);
|
||||
assert_eq!(d, 400.0);
|
||||
assert_eq!(e, 500.0);
|
||||
assert_eq!(HITS.fetch_add(1, SeqCst), 3);
|
||||
}),
|
||||
},
|
||||
},
|
||||
)?;
|
||||
assert_eq!(HITS.load(SeqCst), 4);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn native_function_with_env() -> Result<()> {
|
||||
let store = get_store();
|
||||
let module = get_module(&store)?;
|
||||
|
||||
let mut env: AtomicUsize = AtomicUsize::new(0);
|
||||
Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"host" => {
|
||||
"0" => Function::new_env(&store, &mut env, |env: &mut AtomicUsize| {
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 0);
|
||||
}),
|
||||
"1" => Function::new_env(&store, &mut env, |env: &mut AtomicUsize, x: i32| -> i32 {
|
||||
assert_eq!(x, 0);
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 1);
|
||||
1
|
||||
}),
|
||||
"2" => Function::new_env(&store, &mut env, |env: &mut AtomicUsize, x: i32, y: i64| {
|
||||
assert_eq!(x, 2);
|
||||
assert_eq!(y, 3);
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 2);
|
||||
}),
|
||||
"3" => Function::new_env(&store, &mut env, |env: &mut AtomicUsize, a: i32, b: i64, c: i32, d: f32, e: f64| {
|
||||
assert_eq!(a, 100);
|
||||
assert_eq!(b, 200);
|
||||
assert_eq!(c, 300);
|
||||
assert_eq!(d, 400.0);
|
||||
assert_eq!(e, 500.0);
|
||||
assert_eq!(env.fetch_add(1, SeqCst), 3);
|
||||
}),
|
||||
},
|
||||
},
|
||||
)?;
|
||||
assert_eq!(env.load(SeqCst), 4);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
#[macro_export]
|
||||
macro_rules! wasmer_compilers {
|
||||
{ $($code:item)* } => {
|
||||
#[cfg(feature = "singlepass")]
|
||||
#[cfg(test)]
|
||||
mod singlepass {
|
||||
use std::sync::Arc;
|
||||
use wasmer::{Features, Store, Tunables};
|
||||
use wasmer_engine_jit::JITEngine;
|
||||
use test_utils::get_compiler_config_from_str;
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn get_store() -> Store {
|
||||
let features = Features::default();
|
||||
let try_nan_canonicalization = false;
|
||||
let compiler_config =
|
||||
get_compiler_config_from_str("singlepass", try_nan_canonicalization, features);
|
||||
let tunables = Tunables::for_target(compiler_config.target().triple());
|
||||
let store = Store::new(Arc::new(JITEngine::new(compiler_config, tunables)));
|
||||
store
|
||||
}
|
||||
$($code)*
|
||||
}
|
||||
|
||||
#[cfg(feature = "cranelift")]
|
||||
#[cfg(test)]
|
||||
mod cranelift {
|
||||
use std::sync::Arc;
|
||||
use wasmer::{Features, Store, Tunables};
|
||||
use wasmer_engine_jit::JITEngine;
|
||||
use test_utils::get_compiler_config_from_str;
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn get_store() -> Store {
|
||||
let features = Features::default();
|
||||
let try_nan_canonicalization = false;
|
||||
let compiler_config =
|
||||
get_compiler_config_from_str("cranelift", try_nan_canonicalization, features);
|
||||
let tunables = Tunables::for_target(compiler_config.target().triple());
|
||||
let store = Store::new(Arc::new(JITEngine::new(compiler_config, tunables)));
|
||||
store
|
||||
}
|
||||
$($code)*
|
||||
}
|
||||
#[cfg(feature = "llvm")]
|
||||
#[cfg(test)]
|
||||
mod llvm {
|
||||
use std::sync::Arc;
|
||||
use wasmer::{Features, Store, Tunables};
|
||||
use wasmer_engine_jit::JITEngine;
|
||||
use test_utils::get_compiler_config_from_str;
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn get_store() -> Store {
|
||||
let features = Features::default();
|
||||
let try_nan_canonicalization = false;
|
||||
let compiler_config =
|
||||
get_compiler_config_from_str("llvm", try_nan_canonicalization, features);
|
||||
let tunables = Tunables::for_target(compiler_config.target().triple());
|
||||
let store = Store::new(Arc::new(JITEngine::new(compiler_config, tunables)));
|
||||
store
|
||||
}
|
||||
$($code)*
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -2,11 +2,7 @@
|
||||
//! implementation, such as: singlepass, cranelift or llvm depending
|
||||
//! on what's available on the target.
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
mod imports;
|
||||
mod multi_value_imports;
|
||||
mod traps;
|
||||
mod wast;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
mod utils;
|
||||
|
||||
@@ -2,185 +2,8 @@
|
||||
//! This tests checks that the provided functions (both native and
|
||||
//! dynamic ones) work properly.
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
// These tests are skipped because they are known failing.
|
||||
lazy_static! {
|
||||
static ref SKIP_TESTS: HashSet<&'static str> = [
|
||||
// https://github.com/bytecodealliance/wasmtime/issues/1178
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_f32_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_f32_f32_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_f32_f32_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_f32_f64::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_f32_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_f32_i32_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_f32_i32_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_f32_i64::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_f64_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_i32_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_i32_f32_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_i32_f32_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_i32_f64::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_i32_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_i32_i32_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_i32_i32_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_i32_i64::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_i64_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f32_i64_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f64_f32_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f64_f32_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f64_i32_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_f64_i32_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_f32_f32_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_f32_f32_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_f32_f64::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_f64_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_f64_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_i32_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_i32_f32_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_i32_f32_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_i32_f64::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_i32_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_i32_i32_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_i32_i32_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_i32_i64::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_i64_f32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i32_i64_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i64_f32_i32::native")),
|
||||
(concat!(module_path!(), "::cranelift::test_mvr_i64_i32_i32::native")),
|
||||
|
||||
// Multi-value is not implemented in singlepass yet.
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f64::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_f64::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i64::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f32_i64::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f64::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f64::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f64_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f64_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f64_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_f64_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f64::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_f64::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i64::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i32_i64::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i64::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i64::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i64_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i64_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i64_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f32_i64_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f64_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f64_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f64_f32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f64_f32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f64_f32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f64_f32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f64_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f64_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f64_i32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f64_i32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f64_i32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_f64_i32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f64::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_f64::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i64::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f32_i64::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f64::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f64::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f64_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f64_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f64_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_f64_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f64::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_f64::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32_i32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i32_i32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i64::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i32_i64::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i64::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i64::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i64_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i64_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i64_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i32_i64_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i64_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i64_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i64_f32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i64_f32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i64_f32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i64_f32_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i64_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i64_i32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i64_i32_f32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i64_i32_f32::native")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i64_i32_i32::dynamic")),
|
||||
(concat!(module_path!(), "::singlepass::test_mvr_i64_i32_i32::native")),
|
||||
]
|
||||
.iter()
|
||||
.copied()
|
||||
.collect();
|
||||
}
|
||||
use crate::utils::get_store;
|
||||
use wasmer::*;
|
||||
|
||||
macro_rules! mvr_test {
|
||||
($test_name:ident, $( $result_type:ty ),* ) => {
|
||||
@@ -214,13 +37,8 @@ macro_rules! mvr_test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(any(feature = "test-cranelift", feature="test-singlepass"), ignore)]
|
||||
fn native() -> anyhow::Result<()> {
|
||||
dbg!(concat!(module_path!(), "::native"));
|
||||
if crate::multi_value_imports::SKIP_TESTS.contains(concat!(module_path!(), "::native")) {
|
||||
println!("skipped");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let store = get_store();
|
||||
let module = get_module(&store)?;
|
||||
let instance = wasmer::Instance::new(
|
||||
@@ -245,12 +63,8 @@ macro_rules! mvr_test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(feature="test-singlepass", ignore)]
|
||||
fn dynamic() -> anyhow::Result<()> {
|
||||
if crate::multi_value_imports::SKIP_TESTS.contains(concat!(module_path!(), "::dynamic")) {
|
||||
println!("skipped");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let store = get_store();
|
||||
let module = get_module(&store)?;
|
||||
let instance = wasmer::Instance::new(
|
||||
@@ -272,124 +86,122 @@ macro_rules! mvr_test {
|
||||
}
|
||||
}
|
||||
|
||||
wasmer_compilers! {
|
||||
trait ExpectedExpr {
|
||||
fn expected_value(n: i32) -> Self;
|
||||
fn expected_val(n: i32) -> wasmer::Val;
|
||||
fn expected_valtype() -> wasmer::ValType;
|
||||
}
|
||||
impl ExpectedExpr for i32 {
|
||||
fn expected_value(n: i32) -> i32 {
|
||||
n + 1
|
||||
}
|
||||
fn expected_val(n: i32) -> wasmer::Val {
|
||||
wasmer::Val::I32(Self::expected_value(n))
|
||||
}
|
||||
fn expected_valtype() -> wasmer::ValType {
|
||||
wasmer::ValType::I32
|
||||
}
|
||||
}
|
||||
impl ExpectedExpr for i64 {
|
||||
fn expected_value(n: i32) -> i64 {
|
||||
n as i64 + 2i64
|
||||
}
|
||||
fn expected_val(n: i32) -> wasmer::Val {
|
||||
wasmer::Val::I64(Self::expected_value(n))
|
||||
}
|
||||
fn expected_valtype() -> wasmer::ValType {
|
||||
wasmer::ValType::I64
|
||||
}
|
||||
}
|
||||
impl ExpectedExpr for f32 {
|
||||
fn expected_value(n: i32) -> f32 {
|
||||
n as f32 * 0.1
|
||||
}
|
||||
fn expected_val(n: i32) -> wasmer::Val {
|
||||
wasmer::Val::F32(Self::expected_value(n))
|
||||
}
|
||||
fn expected_valtype() -> wasmer::ValType {
|
||||
wasmer::ValType::F32
|
||||
}
|
||||
}
|
||||
impl ExpectedExpr for f64 {
|
||||
fn expected_value(n: i32) -> f64 {
|
||||
n as f64 * 0.12
|
||||
}
|
||||
fn expected_val(n: i32) -> wasmer::Val {
|
||||
wasmer::Val::F64(Self::expected_value(n))
|
||||
}
|
||||
fn expected_valtype() -> wasmer::ValType {
|
||||
wasmer::ValType::F64
|
||||
}
|
||||
}
|
||||
|
||||
mvr_test!(test_mvr_i32_i32, i32, i32);
|
||||
mvr_test!(test_mvr_i32_f32, i32, f32);
|
||||
mvr_test!(test_mvr_f32_i32, f32, i32);
|
||||
mvr_test!(test_mvr_f32_f32, f32, f32);
|
||||
|
||||
mvr_test!(test_mvr_i64_i32, i64, i32);
|
||||
mvr_test!(test_mvr_i64_f32, i64, f32);
|
||||
mvr_test!(test_mvr_f64_i32, f64, i32);
|
||||
mvr_test!(test_mvr_f64_f32, f64, f32);
|
||||
|
||||
mvr_test!(test_mvr_i32_i64, i32, i64);
|
||||
mvr_test!(test_mvr_f32_i64, f32, i64);
|
||||
mvr_test!(test_mvr_i32_f64, i32, f64);
|
||||
mvr_test!(test_mvr_f32_f64, f32, f64);
|
||||
|
||||
mvr_test!(test_mvr_i32_i32_i32, i32, i32, i32);
|
||||
mvr_test!(test_mvr_i32_i32_f32, i32, i32, f32);
|
||||
mvr_test!(test_mvr_i32_f32_i32, i32, f32, i32);
|
||||
mvr_test!(test_mvr_i32_f32_f32, i32, f32, f32);
|
||||
mvr_test!(test_mvr_f32_i32_i32, f32, i32, i32);
|
||||
mvr_test!(test_mvr_f32_i32_f32, f32, i32, f32);
|
||||
mvr_test!(test_mvr_f32_f32_i32, f32, f32, i32);
|
||||
mvr_test!(test_mvr_f32_f32_f32, f32, f32, f32);
|
||||
|
||||
mvr_test!(test_mvr_i32_i32_i64, i32, i32, i64);
|
||||
mvr_test!(test_mvr_i32_f32_i64, i32, f32, i64);
|
||||
mvr_test!(test_mvr_f32_i32_i64, f32, i32, i64);
|
||||
mvr_test!(test_mvr_f32_f32_i64, f32, f32, i64);
|
||||
mvr_test!(test_mvr_i32_i32_f64, i32, i32, f64);
|
||||
mvr_test!(test_mvr_i32_f32_f64, i32, f32, f64);
|
||||
mvr_test!(test_mvr_f32_i32_f64, f32, i32, f64);
|
||||
mvr_test!(test_mvr_f32_f32_f64, f32, f32, f64);
|
||||
|
||||
mvr_test!(test_mvr_i32_i64_i32, i32, i64, i32);
|
||||
mvr_test!(test_mvr_i32_i64_f32, i32, i64, f32);
|
||||
mvr_test!(test_mvr_f32_i64_i32, f32, i64, i32);
|
||||
mvr_test!(test_mvr_f32_i64_f32, f32, i64, f32);
|
||||
mvr_test!(test_mvr_i32_f64_i32, i32, f64, i32);
|
||||
mvr_test!(test_mvr_i32_f64_f32, i32, f64, f32);
|
||||
mvr_test!(test_mvr_f32_f64_i32, f32, f64, i32);
|
||||
mvr_test!(test_mvr_f32_f64_f32, f32, f64, f32);
|
||||
|
||||
mvr_test!(test_mvr_i64_i32_i32, i64, i32, i32);
|
||||
mvr_test!(test_mvr_i64_i32_f32, i64, i32, f32);
|
||||
mvr_test!(test_mvr_i64_f32_i32, i64, f32, i32);
|
||||
mvr_test!(test_mvr_i64_f32_f32, i64, f32, f32);
|
||||
mvr_test!(test_mvr_f64_i32_i32, f64, i32, i32);
|
||||
mvr_test!(test_mvr_f64_i32_f32, f64, i32, f32);
|
||||
mvr_test!(test_mvr_f64_f32_i32, f64, f32, i32);
|
||||
mvr_test!(test_mvr_f64_f32_f32, f64, f32, f32);
|
||||
|
||||
mvr_test!(test_mvr_i32_i32_i32_i32, i32, i32, i32, i32);
|
||||
mvr_test!(test_mvr_i32_i32_i32_f32, i32, i32, i32, f32);
|
||||
mvr_test!(test_mvr_i32_i32_f32_i32, i32, i32, f32, i32);
|
||||
mvr_test!(test_mvr_i32_i32_f32_f32, i32, i32, f32, f32);
|
||||
mvr_test!(test_mvr_i32_f32_i32_i32, i32, f32, i32, i32);
|
||||
mvr_test!(test_mvr_i32_f32_i32_f32, i32, f32, i32, f32);
|
||||
mvr_test!(test_mvr_i32_f32_f32_i32, i32, f32, f32, i32);
|
||||
mvr_test!(test_mvr_i32_f32_f32_f32, i32, f32, f32, f32);
|
||||
mvr_test!(test_mvr_f32_i32_i32_i32, f32, i32, i32, i32);
|
||||
mvr_test!(test_mvr_f32_i32_i32_f32, f32, i32, i32, f32);
|
||||
mvr_test!(test_mvr_f32_i32_f32_i32, f32, i32, f32, i32);
|
||||
mvr_test!(test_mvr_f32_i32_f32_f32, f32, i32, f32, f32);
|
||||
mvr_test!(test_mvr_f32_f32_i32_i32, f32, f32, i32, i32);
|
||||
mvr_test!(test_mvr_f32_f32_i32_f32, f32, f32, i32, f32);
|
||||
mvr_test!(test_mvr_f32_f32_f32_i32, f32, f32, f32, i32);
|
||||
mvr_test!(test_mvr_f32_f32_f32_f32, f32, f32, f32, f32);
|
||||
|
||||
mvr_test!(test_mvr_i32_i32_i32_i32_i32, i32, i32, i32, i32, i32);
|
||||
trait ExpectedExpr {
|
||||
fn expected_value(n: i32) -> Self;
|
||||
fn expected_val(n: i32) -> wasmer::Val;
|
||||
fn expected_valtype() -> wasmer::ValType;
|
||||
}
|
||||
impl ExpectedExpr for i32 {
|
||||
fn expected_value(n: i32) -> i32 {
|
||||
n + 1
|
||||
}
|
||||
fn expected_val(n: i32) -> wasmer::Val {
|
||||
wasmer::Val::I32(Self::expected_value(n))
|
||||
}
|
||||
fn expected_valtype() -> wasmer::ValType {
|
||||
wasmer::ValType::I32
|
||||
}
|
||||
}
|
||||
impl ExpectedExpr for i64 {
|
||||
fn expected_value(n: i32) -> i64 {
|
||||
n as i64 + 2i64
|
||||
}
|
||||
fn expected_val(n: i32) -> wasmer::Val {
|
||||
wasmer::Val::I64(Self::expected_value(n))
|
||||
}
|
||||
fn expected_valtype() -> wasmer::ValType {
|
||||
wasmer::ValType::I64
|
||||
}
|
||||
}
|
||||
impl ExpectedExpr for f32 {
|
||||
fn expected_value(n: i32) -> f32 {
|
||||
n as f32 * 0.1
|
||||
}
|
||||
fn expected_val(n: i32) -> wasmer::Val {
|
||||
wasmer::Val::F32(Self::expected_value(n))
|
||||
}
|
||||
fn expected_valtype() -> wasmer::ValType {
|
||||
wasmer::ValType::F32
|
||||
}
|
||||
}
|
||||
impl ExpectedExpr for f64 {
|
||||
fn expected_value(n: i32) -> f64 {
|
||||
n as f64 * 0.12
|
||||
}
|
||||
fn expected_val(n: i32) -> wasmer::Val {
|
||||
wasmer::Val::F64(Self::expected_value(n))
|
||||
}
|
||||
fn expected_valtype() -> wasmer::ValType {
|
||||
wasmer::ValType::F64
|
||||
}
|
||||
}
|
||||
|
||||
mvr_test!(test_mvr_i32_i32, i32, i32);
|
||||
mvr_test!(test_mvr_i32_f32, i32, f32);
|
||||
mvr_test!(test_mvr_f32_i32, f32, i32);
|
||||
mvr_test!(test_mvr_f32_f32, f32, f32);
|
||||
|
||||
mvr_test!(test_mvr_i64_i32, i64, i32);
|
||||
mvr_test!(test_mvr_i64_f32, i64, f32);
|
||||
mvr_test!(test_mvr_f64_i32, f64, i32);
|
||||
mvr_test!(test_mvr_f64_f32, f64, f32);
|
||||
|
||||
mvr_test!(test_mvr_i32_i64, i32, i64);
|
||||
mvr_test!(test_mvr_f32_i64, f32, i64);
|
||||
mvr_test!(test_mvr_i32_f64, i32, f64);
|
||||
mvr_test!(test_mvr_f32_f64, f32, f64);
|
||||
|
||||
mvr_test!(test_mvr_i32_i32_i32, i32, i32, i32);
|
||||
mvr_test!(test_mvr_i32_i32_f32, i32, i32, f32);
|
||||
mvr_test!(test_mvr_i32_f32_i32, i32, f32, i32);
|
||||
mvr_test!(test_mvr_i32_f32_f32, i32, f32, f32);
|
||||
mvr_test!(test_mvr_f32_i32_i32, f32, i32, i32);
|
||||
mvr_test!(test_mvr_f32_i32_f32, f32, i32, f32);
|
||||
mvr_test!(test_mvr_f32_f32_i32, f32, f32, i32);
|
||||
mvr_test!(test_mvr_f32_f32_f32, f32, f32, f32);
|
||||
|
||||
mvr_test!(test_mvr_i32_i32_i64, i32, i32, i64);
|
||||
mvr_test!(test_mvr_i32_f32_i64, i32, f32, i64);
|
||||
mvr_test!(test_mvr_f32_i32_i64, f32, i32, i64);
|
||||
mvr_test!(test_mvr_f32_f32_i64, f32, f32, i64);
|
||||
mvr_test!(test_mvr_i32_i32_f64, i32, i32, f64);
|
||||
mvr_test!(test_mvr_i32_f32_f64, i32, f32, f64);
|
||||
mvr_test!(test_mvr_f32_i32_f64, f32, i32, f64);
|
||||
mvr_test!(test_mvr_f32_f32_f64, f32, f32, f64);
|
||||
|
||||
mvr_test!(test_mvr_i32_i64_i32, i32, i64, i32);
|
||||
mvr_test!(test_mvr_i32_i64_f32, i32, i64, f32);
|
||||
mvr_test!(test_mvr_f32_i64_i32, f32, i64, i32);
|
||||
mvr_test!(test_mvr_f32_i64_f32, f32, i64, f32);
|
||||
mvr_test!(test_mvr_i32_f64_i32, i32, f64, i32);
|
||||
mvr_test!(test_mvr_i32_f64_f32, i32, f64, f32);
|
||||
mvr_test!(test_mvr_f32_f64_i32, f32, f64, i32);
|
||||
mvr_test!(test_mvr_f32_f64_f32, f32, f64, f32);
|
||||
|
||||
mvr_test!(test_mvr_i64_i32_i32, i64, i32, i32);
|
||||
mvr_test!(test_mvr_i64_i32_f32, i64, i32, f32);
|
||||
mvr_test!(test_mvr_i64_f32_i32, i64, f32, i32);
|
||||
mvr_test!(test_mvr_i64_f32_f32, i64, f32, f32);
|
||||
mvr_test!(test_mvr_f64_i32_i32, f64, i32, i32);
|
||||
mvr_test!(test_mvr_f64_i32_f32, f64, i32, f32);
|
||||
mvr_test!(test_mvr_f64_f32_i32, f64, f32, i32);
|
||||
mvr_test!(test_mvr_f64_f32_f32, f64, f32, f32);
|
||||
|
||||
mvr_test!(test_mvr_i32_i32_i32_i32, i32, i32, i32, i32);
|
||||
mvr_test!(test_mvr_i32_i32_i32_f32, i32, i32, i32, f32);
|
||||
mvr_test!(test_mvr_i32_i32_f32_i32, i32, i32, f32, i32);
|
||||
mvr_test!(test_mvr_i32_i32_f32_f32, i32, i32, f32, f32);
|
||||
mvr_test!(test_mvr_i32_f32_i32_i32, i32, f32, i32, i32);
|
||||
mvr_test!(test_mvr_i32_f32_i32_f32, i32, f32, i32, f32);
|
||||
mvr_test!(test_mvr_i32_f32_f32_i32, i32, f32, f32, i32);
|
||||
mvr_test!(test_mvr_i32_f32_f32_f32, i32, f32, f32, f32);
|
||||
mvr_test!(test_mvr_f32_i32_i32_i32, f32, i32, i32, i32);
|
||||
mvr_test!(test_mvr_f32_i32_i32_f32, f32, i32, i32, f32);
|
||||
mvr_test!(test_mvr_f32_i32_f32_i32, f32, i32, f32, i32);
|
||||
mvr_test!(test_mvr_f32_i32_f32_f32, f32, i32, f32, f32);
|
||||
mvr_test!(test_mvr_f32_f32_i32_i32, f32, f32, i32, i32);
|
||||
mvr_test!(test_mvr_f32_f32_i32_f32, f32, f32, i32, f32);
|
||||
mvr_test!(test_mvr_f32_f32_f32_i32, f32, f32, f32, i32);
|
||||
mvr_test!(test_mvr_f32_f32_f32_f32, f32, f32, f32, f32);
|
||||
|
||||
mvr_test!(test_mvr_i32_i32_i32_i32_i32, i32, i32, i32, i32, i32);
|
||||
|
||||
@@ -1,228 +1,229 @@
|
||||
wasmer_compilers! {
|
||||
use anyhow::Result;
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use wasmer::*;
|
||||
use crate::utils::get_store;
|
||||
use anyhow::Result;
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use wasmer::*;
|
||||
|
||||
#[test]
|
||||
fn test_trap_return() -> Result<()> {
|
||||
let store = get_store();
|
||||
let wat = r#"
|
||||
(module
|
||||
(func $hello (import "" "hello"))
|
||||
#[test]
|
||||
fn test_trap_return() -> Result<()> {
|
||||
let store = get_store();
|
||||
let wat = r#"
|
||||
(module
|
||||
(func $hello (import "" "hello"))
|
||||
(func (export "run") (call $hello))
|
||||
)
|
||||
"#;
|
||||
|
||||
let module = Module::new(&store, wat)?;
|
||||
let hello_type = FunctionType::new(vec![], vec![]);
|
||||
let hello_func =
|
||||
Function::new_dynamic(&store, &hello_type, |_| Err(RuntimeError::new("test 123")));
|
||||
|
||||
let instance = Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"" => {
|
||||
"hello" => hello_func
|
||||
}
|
||||
},
|
||||
)?;
|
||||
let run_func = instance
|
||||
.exports
|
||||
.get_function("run")
|
||||
.expect("expected function export");
|
||||
|
||||
let e = run_func.call(&[]).err().expect("error calling function");
|
||||
|
||||
assert_eq!(e.message(), "test 123");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(any(feature = "test-singlepass", feature = "test-llvm"), ignore)]
|
||||
fn test_trap_trace() -> Result<()> {
|
||||
let store = get_store();
|
||||
let wat = r#"
|
||||
(module $hello_mod
|
||||
(func (export "run") (call $hello))
|
||||
)
|
||||
"#;
|
||||
(func $hello (unreachable))
|
||||
)
|
||||
"#;
|
||||
|
||||
let module = Module::new(&store, wat)?;
|
||||
let hello_type = FunctionType::new(vec![], vec![]);
|
||||
let hello_func =
|
||||
Function::new_dynamic(&store, &hello_type, |_| Err(RuntimeError::new("test 123")));
|
||||
let module = Module::new(&store, wat)?;
|
||||
let instance = Instance::new(&module, &imports! {})?;
|
||||
let run_func = instance
|
||||
.exports
|
||||
.get_function("run")
|
||||
.expect("expected function export");
|
||||
|
||||
let instance = Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"" => {
|
||||
"hello" => hello_func
|
||||
}
|
||||
},
|
||||
)?;
|
||||
let run_func = instance
|
||||
.exports
|
||||
.get_function("run")
|
||||
.expect("expected function export");
|
||||
let e = run_func.call(&[]).err().expect("error calling function");
|
||||
|
||||
let e = run_func.call(&[]).err().expect("error calling function");
|
||||
let trace = e.trace();
|
||||
assert_eq!(trace.len(), 2);
|
||||
assert_eq!(trace[0].module_name(), "hello_mod");
|
||||
assert_eq!(trace[0].func_index(), 1);
|
||||
assert_eq!(trace[0].func_name(), Some("hello"));
|
||||
assert_eq!(trace[1].module_name(), "hello_mod");
|
||||
assert_eq!(trace[1].func_index(), 0);
|
||||
assert_eq!(trace[1].func_name(), None);
|
||||
assert!(
|
||||
e.message().contains("unreachable"),
|
||||
"wrong message: {}",
|
||||
e.message()
|
||||
);
|
||||
|
||||
assert_eq!(e.message(), "test 123");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Ok(())
|
||||
#[test]
|
||||
fn test_trap_trace_cb() -> Result<()> {
|
||||
let store = get_store();
|
||||
let wat = r#"
|
||||
(module $hello_mod
|
||||
(import "" "throw" (func $throw))
|
||||
(func (export "run") (call $hello))
|
||||
(func $hello (call $throw))
|
||||
)
|
||||
"#;
|
||||
|
||||
let fn_type = FunctionType::new(vec![], vec![]);
|
||||
let fn_func = Function::new_dynamic(&store, &fn_type, |_| Err(RuntimeError::new("cb throw")));
|
||||
|
||||
let module = Module::new(&store, wat)?;
|
||||
let instance = Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"" => {
|
||||
"throw" => fn_func
|
||||
}
|
||||
},
|
||||
)?;
|
||||
let run_func = instance
|
||||
.exports
|
||||
.get_function("run")
|
||||
.expect("expected function export");
|
||||
|
||||
let e = run_func.call(&[]).err().expect("error calling function");
|
||||
|
||||
let trace = e.trace();
|
||||
println!("Trace {:?}", trace);
|
||||
// TODO: Reenable this (disabled as it was not working with llvm/singlepass)
|
||||
// assert_eq!(trace.len(), 2);
|
||||
// assert_eq!(trace[0].module_name(), "hello_mod");
|
||||
// assert_eq!(trace[0].func_index(), 2);
|
||||
// assert_eq!(trace[1].module_name(), "hello_mod");
|
||||
// assert_eq!(trace[1].func_index(), 1);
|
||||
assert_eq!(e.message(), "cb throw");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(any(feature = "test-singlepass", feature = "test-llvm"), ignore)]
|
||||
fn test_trap_stack_overflow() -> Result<()> {
|
||||
let store = get_store();
|
||||
let wat = r#"
|
||||
(module $rec_mod
|
||||
(func $run (export "run") (call $run))
|
||||
)
|
||||
"#;
|
||||
|
||||
let module = Module::new(&store, wat)?;
|
||||
let instance = Instance::new(&module, &imports! {})?;
|
||||
let run_func = instance
|
||||
.exports
|
||||
.get_function("run")
|
||||
.expect("expected function export");
|
||||
|
||||
let e = run_func.call(&[]).err().expect("error calling function");
|
||||
|
||||
let trace = e.trace();
|
||||
assert!(trace.len() >= 32);
|
||||
for i in 0..trace.len() {
|
||||
assert_eq!(trace[i].module_name(), "rec_mod");
|
||||
assert_eq!(trace[i].func_index(), 0);
|
||||
assert_eq!(trace[i].func_name(), Some("run"));
|
||||
}
|
||||
assert!(e.message().contains("call stack exhausted"));
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_trap_trace() -> Result<()> {
|
||||
let store = get_store();
|
||||
let wat = r#"
|
||||
(module $hello_mod
|
||||
(func (export "run") (call $hello))
|
||||
(func $hello (unreachable))
|
||||
)
|
||||
"#;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let module = Module::new(&store, wat)?;
|
||||
let instance = Instance::new(&module, &imports! {})?;
|
||||
let run_func = instance
|
||||
.exports
|
||||
.get_function("run")
|
||||
.expect("expected function export");
|
||||
#[test]
|
||||
#[cfg_attr(any(feature = "test-singlepass", feature = "test-llvm"), ignore)]
|
||||
fn trap_display_pretty() -> Result<()> {
|
||||
let store = get_store();
|
||||
let wat = r#"
|
||||
(module $m
|
||||
(func $die unreachable)
|
||||
(func call $die)
|
||||
(func $foo call 1)
|
||||
(func (export "bar") call $foo)
|
||||
)
|
||||
"#;
|
||||
|
||||
let e = run_func.call(&[]).err().expect("error calling function");
|
||||
let module = Module::new(&store, wat)?;
|
||||
let instance = Instance::new(&module, &imports! {})?;
|
||||
let run_func = instance
|
||||
.exports
|
||||
.get_function("bar")
|
||||
.expect("expected function export");
|
||||
|
||||
let trace = e.trace();
|
||||
assert_eq!(trace.len(), 2);
|
||||
assert_eq!(trace[0].module_name(), "hello_mod");
|
||||
assert_eq!(trace[0].func_index(), 1);
|
||||
assert_eq!(trace[0].func_name(), Some("hello"));
|
||||
assert_eq!(trace[1].module_name(), "hello_mod");
|
||||
assert_eq!(trace[1].func_index(), 0);
|
||||
assert_eq!(trace[1].func_name(), None);
|
||||
assert!(
|
||||
e.message().contains("unreachable"),
|
||||
"wrong message: {}",
|
||||
e.message()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trap_trace_cb() -> Result<()> {
|
||||
let store = get_store();
|
||||
let wat = r#"
|
||||
(module $hello_mod
|
||||
(import "" "throw" (func $throw))
|
||||
(func (export "run") (call $hello))
|
||||
(func $hello (call $throw))
|
||||
)
|
||||
"#;
|
||||
|
||||
let fn_type = FunctionType::new(vec![], vec![]);
|
||||
let fn_func = Function::new_dynamic(&store, &fn_type, |_| Err(RuntimeError::new("cb throw")));
|
||||
|
||||
let module = Module::new(&store, wat)?;
|
||||
let instance = Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"" => {
|
||||
"throw" => fn_func
|
||||
}
|
||||
},
|
||||
)?;
|
||||
let run_func = instance
|
||||
.exports
|
||||
.get_function("run")
|
||||
.expect("expected function export");
|
||||
|
||||
let e = run_func.call(&[]).err().expect("error calling function");
|
||||
|
||||
let trace = e.trace();
|
||||
println!("Trace {:?}", trace);
|
||||
// TODO: Reenable this (disabled as it was not working with llvm/singlepass)
|
||||
// assert_eq!(trace.len(), 2);
|
||||
// assert_eq!(trace[0].module_name(), "hello_mod");
|
||||
// assert_eq!(trace[0].func_index(), 2);
|
||||
// assert_eq!(trace[1].module_name(), "hello_mod");
|
||||
// assert_eq!(trace[1].func_index(), 1);
|
||||
assert_eq!(e.message(), "cb throw");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trap_stack_overflow() -> Result<()> {
|
||||
let store = get_store();
|
||||
let wat = r#"
|
||||
(module $rec_mod
|
||||
(func $run (export "run") (call $run))
|
||||
)
|
||||
"#;
|
||||
|
||||
let module = Module::new(&store, wat)?;
|
||||
let instance = Instance::new(&module, &imports! {})?;
|
||||
let run_func = instance
|
||||
.exports
|
||||
.get_function("run")
|
||||
.expect("expected function export");
|
||||
|
||||
let e = run_func.call(&[]).err().expect("error calling function");
|
||||
|
||||
let trace = e.trace();
|
||||
// assert!(trace.len() >= 32);
|
||||
for i in 0..trace.len() {
|
||||
assert_eq!(trace[i].module_name(), "rec_mod");
|
||||
assert_eq!(trace[i].func_index(), 0);
|
||||
assert_eq!(trace[i].func_name(), Some("run"));
|
||||
}
|
||||
assert!(e.message().contains("call stack exhausted"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn trap_display_pretty() -> Result<()> {
|
||||
let store = get_store();
|
||||
let wat = r#"
|
||||
(module $m
|
||||
(func $die unreachable)
|
||||
(func call $die)
|
||||
(func $foo call 1)
|
||||
(func (export "bar") call $foo)
|
||||
)
|
||||
"#;
|
||||
|
||||
let module = Module::new(&store, wat)?;
|
||||
let instance = Instance::new(&module, &imports! {})?;
|
||||
let run_func = instance
|
||||
.exports
|
||||
.get_function("bar")
|
||||
.expect("expected function export");
|
||||
|
||||
let e = run_func.call(&[]).err().expect("error calling function");
|
||||
assert_eq!(
|
||||
e.to_string(),
|
||||
"\
|
||||
let e = run_func.call(&[]).err().expect("error calling function");
|
||||
assert_eq!(
|
||||
e.to_string(),
|
||||
"\
|
||||
RuntimeError: unreachable
|
||||
at die (m[0]:0x23)
|
||||
at <unnamed> (m[1]:0x27)
|
||||
at foo (m[2]:0x2c)
|
||||
at <unnamed> (m[3]:0x31)"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn trap_display_multi_module() -> Result<()> {
|
||||
let store = get_store();
|
||||
let wat = r#"
|
||||
(module $a
|
||||
(func $die unreachable)
|
||||
(func call $die)
|
||||
(func $foo call 1)
|
||||
(func (export "bar") call $foo)
|
||||
)
|
||||
"#;
|
||||
#[test]
|
||||
#[cfg_attr(any(feature = "test-singlepass", feature = "test-llvm"), ignore)]
|
||||
fn trap_display_multi_module() -> Result<()> {
|
||||
let store = get_store();
|
||||
let wat = r#"
|
||||
(module $a
|
||||
(func $die unreachable)
|
||||
(func call $die)
|
||||
(func $foo call 1)
|
||||
(func (export "bar") call $foo)
|
||||
)
|
||||
"#;
|
||||
|
||||
let module = Module::new(&store, wat)?;
|
||||
let instance = Instance::new(&module, &imports! {})?;
|
||||
let bar = instance.exports.get_function("bar")?.clone();
|
||||
let module = Module::new(&store, wat)?;
|
||||
let instance = Instance::new(&module, &imports! {})?;
|
||||
let bar = instance.exports.get_function("bar")?.clone();
|
||||
|
||||
let wat = r#"
|
||||
(module $b
|
||||
(import "" "" (func $bar))
|
||||
(func $middle call $bar)
|
||||
(func (export "bar2") call $middle)
|
||||
)
|
||||
"#;
|
||||
let module = Module::new(&store, wat)?;
|
||||
let instance = Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"" => {
|
||||
"" => bar
|
||||
}
|
||||
},
|
||||
)?;
|
||||
let bar2 = instance
|
||||
.exports
|
||||
.get_function("bar2")
|
||||
.expect("expected function export");
|
||||
let wat = r#"
|
||||
(module $b
|
||||
(import "" "" (func $bar))
|
||||
(func $middle call $bar)
|
||||
(func (export "bar2") call $middle)
|
||||
)
|
||||
"#;
|
||||
let module = Module::new(&store, wat)?;
|
||||
let instance = Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"" => {
|
||||
"" => bar
|
||||
}
|
||||
},
|
||||
)?;
|
||||
let bar2 = instance
|
||||
.exports
|
||||
.get_function("bar2")
|
||||
.expect("expected function export");
|
||||
|
||||
let e = bar2.call(&[]).err().expect("error calling function");
|
||||
assert_eq!(
|
||||
e.to_string(),
|
||||
"\
|
||||
let e = bar2.call(&[]).err().expect("error calling function");
|
||||
assert_eq!(
|
||||
e.to_string(),
|
||||
"\
|
||||
RuntimeError: unreachable
|
||||
at die (a[0]:0x23)
|
||||
at <unnamed> (a[1]:0x27)
|
||||
@@ -230,244 +231,243 @@ RuntimeError: unreachable
|
||||
at <unnamed> (a[3]:0x31)
|
||||
at middle (b[1]:0x29)
|
||||
at <unnamed> (b[2]:0x2e)"
|
||||
);
|
||||
Ok(())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trap_start_function_import() -> Result<()> {
|
||||
let store = get_store();
|
||||
let binary = r#"
|
||||
(module $a
|
||||
(import "" "" (func $foo))
|
||||
(start $foo)
|
||||
)
|
||||
"#;
|
||||
|
||||
let module = Module::new(&store, &binary)?;
|
||||
let sig = FunctionType::new(vec![], vec![]);
|
||||
let func = Function::new_dynamic(&store, &sig, |_| Err(RuntimeError::new("user trap")));
|
||||
let err = Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"" => {
|
||||
"" => func
|
||||
}
|
||||
},
|
||||
)
|
||||
.err()
|
||||
.unwrap();
|
||||
match err {
|
||||
InstantiationError::Link(_) => panic!("It should be a start error"),
|
||||
InstantiationError::Start(err) => {
|
||||
assert_eq!(err.message(), "user trap");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trap_start_function_import() -> Result<()> {
|
||||
let store = get_store();
|
||||
let binary = r#"
|
||||
(module $a
|
||||
(import "" "" (func $foo))
|
||||
(start $foo)
|
||||
)
|
||||
"#;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let module = Module::new(&store, &binary)?;
|
||||
let sig = FunctionType::new(vec![], vec![]);
|
||||
let func = Function::new_dynamic(&store, &sig, |_| Err(RuntimeError::new("user trap")));
|
||||
let err = Instance::new(
|
||||
#[test]
|
||||
fn rust_panic_import() -> Result<()> {
|
||||
let store = get_store();
|
||||
let binary = r#"
|
||||
(module $a
|
||||
(import "" "foo" (func $foo))
|
||||
(import "" "bar" (func $bar))
|
||||
(func (export "foo") call $foo)
|
||||
(func (export "bar") call $bar)
|
||||
)
|
||||
"#;
|
||||
|
||||
let module = Module::new(&store, &binary)?;
|
||||
let sig = FunctionType::new(vec![], vec![]);
|
||||
let func = Function::new_dynamic(&store, &sig, |_| panic!("this is a panic"));
|
||||
let instance = Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"" => {
|
||||
"foo" => func,
|
||||
"bar" => Function::new(&store, || panic!("this is another panic"))
|
||||
}
|
||||
},
|
||||
)?;
|
||||
let func = instance.exports.get_function("foo")?.clone();
|
||||
let err = panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
drop(func.call(&[]));
|
||||
}))
|
||||
.unwrap_err();
|
||||
assert_eq!(err.downcast_ref::<&'static str>(), Some(&"this is a panic"));
|
||||
|
||||
// TODO: Reenable this (disabled as it was not working with llvm/singlepass)
|
||||
// It doesnt' work either with cranelift and `--test-threads=1`.
|
||||
// let func = instance.exports.get_function("bar")?.clone();
|
||||
// let err = panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
// drop(func.call(&[]));
|
||||
// }))
|
||||
// .unwrap_err();
|
||||
// assert_eq!(
|
||||
// err.downcast_ref::<&'static str>(),
|
||||
// Some(&"this is another panic")
|
||||
// );
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rust_panic_start_function() -> Result<()> {
|
||||
let store = get_store();
|
||||
let binary = r#"
|
||||
(module $a
|
||||
(import "" "" (func $foo))
|
||||
(start $foo)
|
||||
)
|
||||
"#;
|
||||
|
||||
let module = Module::new(&store, &binary)?;
|
||||
let sig = FunctionType::new(vec![], vec![]);
|
||||
let func = Function::new_dynamic(&store, &sig, |_| panic!("this is a panic"));
|
||||
let err = panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
drop(Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"" => {
|
||||
"" => func
|
||||
}
|
||||
},
|
||||
)
|
||||
.err()
|
||||
.unwrap();
|
||||
match err {
|
||||
InstantiationError::Link(_) => panic!("It should be a start error"),
|
||||
InstantiationError::Start(err) => {
|
||||
assert_eq!(err.message(), "user trap");
|
||||
}
|
||||
}
|
||||
));
|
||||
}))
|
||||
.unwrap_err();
|
||||
assert_eq!(err.downcast_ref::<&'static str>(), Some(&"this is a panic"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rust_panic_import() -> Result<()> {
|
||||
let store = get_store();
|
||||
let binary = r#"
|
||||
(module $a
|
||||
(import "" "foo" (func $foo))
|
||||
(import "" "bar" (func $bar))
|
||||
(func (export "foo") call $foo)
|
||||
(func (export "bar") call $bar)
|
||||
)
|
||||
"#;
|
||||
|
||||
let module = Module::new(&store, &binary)?;
|
||||
let sig = FunctionType::new(vec![], vec![]);
|
||||
let func = Function::new_dynamic(&store, &sig, |_| panic!("this is a panic"));
|
||||
let instance = Instance::new(
|
||||
let func = Function::new(&store, || panic!("this is another panic"));
|
||||
let err = panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
drop(Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"" => {
|
||||
"foo" => func,
|
||||
"bar" => Function::new(&store, || panic!("this is another panic"))
|
||||
"" => func
|
||||
}
|
||||
},
|
||||
)?;
|
||||
let func = instance.exports.get_function("foo")?.clone();
|
||||
let err = panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
drop(func.call(&[]));
|
||||
}))
|
||||
.unwrap_err();
|
||||
assert_eq!(err.downcast_ref::<&'static str>(), Some(&"this is a panic"));
|
||||
));
|
||||
}))
|
||||
.unwrap_err();
|
||||
assert_eq!(
|
||||
err.downcast_ref::<&'static str>(),
|
||||
Some(&"this is another panic")
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TODO: Reenable this (disabled as it was not working with llvm/singlepass)
|
||||
// It doesnt' work either with cranelift and `--test-threads=1`.
|
||||
// let func = instance.exports.get_function("bar")?.clone();
|
||||
// let err = panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
// drop(func.call(&[]));
|
||||
// }))
|
||||
// .unwrap_err();
|
||||
// assert_eq!(
|
||||
// err.downcast_ref::<&'static str>(),
|
||||
// Some(&"this is another panic")
|
||||
// );
|
||||
Ok(())
|
||||
}
|
||||
#[test]
|
||||
fn mismatched_arguments() -> Result<()> {
|
||||
let store = get_store();
|
||||
let binary = r#"
|
||||
(module $a
|
||||
(func (export "foo") (param i32))
|
||||
)
|
||||
"#;
|
||||
|
||||
#[test]
|
||||
fn rust_panic_start_function() -> Result<()> {
|
||||
let store = get_store();
|
||||
let binary = r#"
|
||||
(module $a
|
||||
(import "" "" (func $foo))
|
||||
(start $foo)
|
||||
)
|
||||
"#;
|
||||
let module = Module::new(&store, &binary)?;
|
||||
let instance = Instance::new(&module, &imports! {})?;
|
||||
let func: &Function = instance.exports.get("foo")?;
|
||||
assert_eq!(
|
||||
func.call(&[]).unwrap_err().message(),
|
||||
"Parameters of type [] did not match signature [I32] -> []"
|
||||
);
|
||||
assert_eq!(
|
||||
func.call(&[Val::F32(0.0)]).unwrap_err().message(),
|
||||
"Parameters of type [F32] did not match signature [I32] -> []",
|
||||
);
|
||||
assert_eq!(
|
||||
func.call(&[Val::I32(0), Val::I32(1)])
|
||||
.unwrap_err()
|
||||
.message(),
|
||||
"Parameters of type [I32, I32] did not match signature [I32] -> []"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let module = Module::new(&store, &binary)?;
|
||||
let sig = FunctionType::new(vec![], vec![]);
|
||||
let func = Function::new_dynamic(&store, &sig, |_| panic!("this is a panic"));
|
||||
let err = panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
drop(Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"" => {
|
||||
"" => func
|
||||
}
|
||||
},
|
||||
));
|
||||
}))
|
||||
.unwrap_err();
|
||||
assert_eq!(err.downcast_ref::<&'static str>(), Some(&"this is a panic"));
|
||||
#[test]
|
||||
#[cfg_attr(any(feature = "test-singlepass", feature = "test-llvm"), ignore)]
|
||||
fn call_signature_mismatch() -> Result<()> {
|
||||
let store = get_store();
|
||||
let binary = r#"
|
||||
(module $a
|
||||
(func $foo
|
||||
i32.const 0
|
||||
call_indirect)
|
||||
(func $bar (param i32))
|
||||
(start $foo)
|
||||
|
||||
let func = Function::new(&store, || panic!("this is another panic"));
|
||||
let err = panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
drop(Instance::new(
|
||||
&module,
|
||||
&imports! {
|
||||
"" => {
|
||||
"" => func
|
||||
}
|
||||
},
|
||||
));
|
||||
}))
|
||||
.unwrap_err();
|
||||
assert_eq!(
|
||||
err.downcast_ref::<&'static str>(),
|
||||
Some(&"this is another panic")
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
(table 1 anyfunc)
|
||||
(elem (i32.const 0) 1)
|
||||
)
|
||||
"#;
|
||||
|
||||
#[test]
|
||||
fn mismatched_arguments() -> Result<()> {
|
||||
let store = get_store();
|
||||
let binary = r#"
|
||||
(module $a
|
||||
(func (export "foo") (param i32))
|
||||
)
|
||||
"#;
|
||||
|
||||
let module = Module::new(&store, &binary)?;
|
||||
let instance = Instance::new(&module, &imports! {})?;
|
||||
let func: &Function = instance.exports.get("foo")?;
|
||||
assert_eq!(
|
||||
func.call(&[]).unwrap_err().message(),
|
||||
"Parameters of type [] did not match signature [I32] -> []"
|
||||
);
|
||||
assert_eq!(
|
||||
func.call(&[Val::F32(0.0)]).unwrap_err().message(),
|
||||
"Parameters of type [F32] did not match signature [I32] -> []",
|
||||
);
|
||||
assert_eq!(
|
||||
func.call(&[Val::I32(0), Val::I32(1)])
|
||||
.unwrap_err()
|
||||
.message(),
|
||||
"Parameters of type [I32, I32] did not match signature [I32] -> []"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn call_signature_mismatch() -> Result<()> {
|
||||
let store = get_store();
|
||||
let binary = r#"
|
||||
(module $a
|
||||
(func $foo
|
||||
i32.const 0
|
||||
call_indirect)
|
||||
(func $bar (param i32))
|
||||
(start $foo)
|
||||
|
||||
(table 1 anyfunc)
|
||||
(elem (i32.const 0) 1)
|
||||
)
|
||||
"#;
|
||||
|
||||
let module = Module::new(&store, &binary)?;
|
||||
let err = Instance::new(&module, &imports! {})
|
||||
.err()
|
||||
.expect("expected error");
|
||||
assert_eq!(
|
||||
format!("{}", err),
|
||||
"\
|
||||
let module = Module::new(&store, &binary)?;
|
||||
let err = Instance::new(&module, &imports! {})
|
||||
.err()
|
||||
.expect("expected error");
|
||||
assert_eq!(
|
||||
format!("{}", err),
|
||||
"\
|
||||
RuntimeError: indirect call type mismatch
|
||||
at foo (a[0]:0x30)\
|
||||
"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
#[test]
|
||||
fn start_trap_pretty() -> Result<()> {
|
||||
let store = get_store();
|
||||
let wat = r#"
|
||||
(module $m
|
||||
(func $die unreachable)
|
||||
(func call $die)
|
||||
(func $foo call 1)
|
||||
(func $start call $foo)
|
||||
(start $start)
|
||||
)
|
||||
"#;
|
||||
#[ignore]
|
||||
#[cfg_attr(any(feature = "test-singlepass", feature = "test-llvm"), ignore)]
|
||||
fn start_trap_pretty() -> Result<()> {
|
||||
let store = get_store();
|
||||
let wat = r#"
|
||||
(module $m
|
||||
(func $die unreachable)
|
||||
(func call $die)
|
||||
(func $foo call 1)
|
||||
(func $start call $foo)
|
||||
(start $start)
|
||||
)
|
||||
"#;
|
||||
|
||||
let module = Module::new(&store, wat)?;
|
||||
let err = Instance::new(&module, &imports! {})
|
||||
.err()
|
||||
.expect("expected error");
|
||||
let module = Module::new(&store, wat)?;
|
||||
let err = Instance::new(&module, &imports! {})
|
||||
.err()
|
||||
.expect("expected error");
|
||||
|
||||
assert_eq!(
|
||||
format!("{}", err),
|
||||
"\
|
||||
assert_eq!(
|
||||
format!("{}", err),
|
||||
"\
|
||||
RuntimeError: unreachable
|
||||
at die (m[0]:0x1d)
|
||||
at <unnamed> (m[1]:0x21)
|
||||
at foo (m[2]:0x26)
|
||||
at start (m[3]:0x2b)\
|
||||
"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn present_after_module_drop() -> Result<()> {
|
||||
let store = get_store();
|
||||
let module = Module::new(&store, r#"(func (export "foo") unreachable)"#)?;
|
||||
let instance = Instance::new(&module, &imports! {})?;
|
||||
let func: Function = instance.exports.get_function("foo")?.clone();
|
||||
#[test]
|
||||
fn present_after_module_drop() -> Result<()> {
|
||||
let store = get_store();
|
||||
let module = Module::new(&store, r#"(func (export "foo") unreachable)"#)?;
|
||||
let instance = Instance::new(&module, &imports! {})?;
|
||||
let func: Function = instance.exports.get_function("foo")?.clone();
|
||||
|
||||
println!("asserting before we drop modules");
|
||||
assert_trap(func.call(&[]).unwrap_err());
|
||||
drop((instance, module));
|
||||
println!("asserting before we drop modules");
|
||||
assert_trap(func.call(&[]).unwrap_err());
|
||||
drop((instance, module));
|
||||
|
||||
println!("asserting after drop");
|
||||
assert_trap(func.call(&[]).unwrap_err());
|
||||
return Ok(());
|
||||
println!("asserting after drop");
|
||||
assert_trap(func.call(&[]).unwrap_err());
|
||||
return Ok(());
|
||||
|
||||
fn assert_trap(t: RuntimeError) {
|
||||
println!("{}", t);
|
||||
// assert_eq!(t.trace().len(), 1);
|
||||
// assert_eq!(t.trace()[0].func_index(), 0);
|
||||
}
|
||||
fn assert_trap(t: RuntimeError) {
|
||||
println!("{}", t);
|
||||
// assert_eq!(t.trace().len(), 1);
|
||||
// assert_eq!(t.trace()[0].func_index(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
29
tests/compilers/utils.rs
Normal file
29
tests/compilers/utils.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
use std::sync::Arc;
|
||||
use test_utils::get_compiler_config_from_str;
|
||||
use wasmer::{Features, Store, Tunables};
|
||||
use wasmer_engine_jit::JITEngine;
|
||||
|
||||
fn get_compiler_str() -> &'static str {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "test-cranelift")] {
|
||||
"cranelift"
|
||||
} else if #[cfg(feature = "test-llvm")] {
|
||||
"llvm"
|
||||
} else if #[cfg(feature = "test-singlepass")] {
|
||||
"singlepass"
|
||||
}
|
||||
else {
|
||||
compile_error!("No compiler chosen for the tests")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_store() -> Store {
|
||||
let features = Features::default();
|
||||
let try_nan_canonicalization = false;
|
||||
let compiler_config =
|
||||
get_compiler_config_from_str(get_compiler_str(), try_nan_canonicalization, features);
|
||||
let tunables = Tunables::for_target(compiler_config.target().triple());
|
||||
let store = Store::new(Arc::new(JITEngine::new(compiler_config, tunables)));
|
||||
store
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
#![cfg(all(feature = "compiler", feature = "engine"))]
|
||||
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use test_utils::get_compiler_config_from_str;
|
||||
use wasmer::{Features, Store, Tunables};
|
||||
#[cfg(feature = "jit")]
|
||||
use wasmer_engine_jit::JITEngine;
|
||||
#[cfg(feature = "native")]
|
||||
use wasmer_engine_native::NativeEngine;
|
||||
use wasmer_wast::Wast;
|
||||
|
||||
// The generated tests (from build.rs) look like:
|
||||
// #[cfg(test)]
|
||||
// mod singlepass {
|
||||
// mod spec {
|
||||
// #[test]
|
||||
// fn address() -> anyhow::Result<()> {
|
||||
// crate::run_wast("tests/spectests/address.wast", "singlepass")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
include!(concat!(env!("OUT_DIR"), "/generated_spectests.rs"));
|
||||
|
||||
// This prefixer returns the hash of the module to prefix each of
|
||||
// the functions in the shared object generated by the `NativeEngine`.
|
||||
fn native_prefixer(bytes: &[u8]) -> String {
|
||||
let hash = blake3::hash(bytes);
|
||||
format!("{}", hash.to_hex())
|
||||
}
|
||||
|
||||
fn run_wast(wast_path: &str, compiler: &str) -> anyhow::Result<()> {
|
||||
println!(
|
||||
"Running wast `{}` with the {} compiler",
|
||||
wast_path, compiler
|
||||
);
|
||||
let try_nan_canonicalization = wast_path.contains("nan-canonicalization");
|
||||
let mut features = Features::default();
|
||||
if wast_path.contains("bulk-memory") {
|
||||
features.bulk_memory(true);
|
||||
}
|
||||
let compiler_config =
|
||||
get_compiler_config_from_str(compiler, try_nan_canonicalization, features);
|
||||
let tunables = Tunables::for_target(compiler_config.target().triple());
|
||||
let store = Store::new(Arc::new(JITEngine::new(compiler_config, tunables)));
|
||||
// let mut native = NativeEngine::new(compiler_config, tunables);
|
||||
// native.set_deterministic_prefixer(native_prefixer);
|
||||
// let store = Store::new(Arc::new(native));
|
||||
let mut wast = Wast::new_with_spectest(store);
|
||||
if compiler == "singlepass" {
|
||||
// We don't support multivalue yet in singlepass
|
||||
wast.allow_instantiation_failures(&[
|
||||
"Validation error: invalid result arity: func type returns multiple values",
|
||||
"Validation error: blocks, loops, and ifs accept no parameters when multi-value is not enabled"
|
||||
]);
|
||||
}
|
||||
wast.fail_fast = false;
|
||||
let path = Path::new(wast_path);
|
||||
wast.run_file(path)
|
||||
}
|
||||
Reference in New Issue
Block a user