Separate testing per compiler

This commit is contained in:
Syrus
2020-06-09 14:33:12 -07:00
parent f8fbb33b00
commit a68bcf95ed
11 changed files with 776 additions and 986 deletions

View File

@ -65,6 +65,7 @@ anyhow = "1.0"
blake3 = "0.3"
lazy_static = "1.4"
test-utils = { path = "tests/lib/test-utils" }
# test-macros = { path = "tests/lib/test-macros" }
wasmer-engine-dummy = { path = "tests/lib/engine-dummy" }
[features]
@ -106,5 +107,16 @@ llvm = [
"compiler",
]
# Testing features
test-singlepass = [
"singlepass",
]
test-cranelift = [
"cranelift",
]
test-llvm = [
"llvm",
]
# [profile.release]
# lto = "fat"

View File

@ -93,8 +93,21 @@ build-capi-llvm:
# Testing #
###########
test:
cargo test --release $(compiler_features)
test: $(foreach compiler,$(compilers),test-$(compiler)) test-packages
test-singlepass:
cargo test --release $(compiler_features) --features "test-singlepass"
test-cranelift:
cargo test --release $(compiler_features) --features "test-cranelift"
test-llvm:
cargo test --release $(compiler_features) --features "test-llvm"
test-packages:
cargo test -p wasmer --release
cargo test -p wasmer-runtime --release
cargo test -p wasm-common --release
test-capi-singlepass: build-capi-singlepass
cargo test --manifest-path lib/c-api/Cargo.toml --release \

View File

@ -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(())
}

View File

@ -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)*
}
};
}

View File

@ -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;

View File

@ -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);

View File

@ -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
View 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
}

View File

@ -169,7 +169,7 @@ pub fn with_features(
f: impl Fn(&mut Testsuite) -> anyhow::Result<()> + Copy,
) -> anyhow::Result<()> {
for compiler in features.iter() {
writeln!(out.buffer, "#[cfg(feature=\"{}\")]", compiler)?;
writeln!(out.buffer, "#[cfg(feature=\"test-{}\")]", compiler)?;
writeln!(out.buffer, "#[cfg(test)]")?;
writeln!(out.buffer, "#[allow(non_snake_case)]")?;
with_test_module(&mut out, &compiler, f)?;

View File

@ -20,11 +20,7 @@ pub fn wast_processor(out: &mut Testsuite, p: PathBuf) -> Option<Test> {
let compiler = out.path.get(0).unwrap();
// The implementation of `run_wast` lives in /tests/spectest.rs
let body = format!(
"crate::wast::run_wast(r#\"{}\"#, \"{}\")",
p.display(),
compiler
);
let body = format!("crate::run_wast(r#\"{}\"#, \"{}\")", p.display(), compiler);
Some(Test {
name: testname,