diff --git a/Cargo.toml b/Cargo.toml index c89eb11f2..9c397fddd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/Makefile b/Makefile index 8daf38b2b..518bfea4c 100644 --- a/Makefile +++ b/Makefile @@ -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 \ diff --git a/tests/compilers/imports.rs b/tests/compilers/imports.rs index 65857feba..a46cab37e 100644 --- a/tests/compilers/imports.rs +++ b/tests/compilers/imports.rs @@ -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 { - 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 { + 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(()) } diff --git a/tests/compilers/macros.rs b/tests/compilers/macros.rs deleted file mode 100644 index ee5d25f7b..000000000 --- a/tests/compilers/macros.rs +++ /dev/null @@ -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)* - } - }; -} diff --git a/tests/compilers/main.rs b/tests/compilers/main.rs index 5aaf101b6..0de5af90f 100644 --- a/tests/compilers/main.rs +++ b/tests/compilers/main.rs @@ -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; diff --git a/tests/compilers/multi_value_imports.rs b/tests/compilers/multi_value_imports.rs index 559a3a519..ec75086ab 100644 --- a/tests/compilers/multi_value_imports.rs +++ b/tests/compilers/multi_value_imports.rs @@ -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); diff --git a/tests/compilers/traps.rs b/tests/compilers/traps.rs index 4be3969d3..a882217b0 100644 --- a/tests/compilers/traps.rs +++ b/tests/compilers/traps.rs @@ -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 (m[1]:0x27) at foo (m[2]:0x2c) at (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 (a[1]:0x27) @@ -230,244 +231,243 @@ RuntimeError: unreachable at (a[3]:0x31) at middle (b[1]:0x29) at (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 (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); } } diff --git a/tests/compilers/utils.rs b/tests/compilers/utils.rs new file mode 100644 index 000000000..0b8e7c9c4 --- /dev/null +++ b/tests/compilers/utils.rs @@ -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 +} diff --git a/tests/lib/test-generator/src/lib.rs b/tests/lib/test-generator/src/lib.rs index 629174f5b..b810a2fb3 100644 --- a/tests/lib/test-generator/src/lib.rs +++ b/tests/lib/test-generator/src/lib.rs @@ -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)?; diff --git a/tests/lib/test-generator/src/processors.rs b/tests/lib/test-generator/src/processors.rs index 70931ab72..4d36db63c 100644 --- a/tests/lib/test-generator/src/processors.rs +++ b/tests/lib/test-generator/src/processors.rs @@ -20,11 +20,7 @@ pub fn wast_processor(out: &mut Testsuite, p: PathBuf) -> Option { 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, diff --git a/tests/compilers/wast.rs b/tests/wast.rs similarity index 100% rename from tests/compilers/wast.rs rename to tests/wast.rs