mod context; mod descriptor; mod error; mod profile; mod run; use self::{ context::TestContext, descriptor::{TestDescriptor, TestSpan}, error::TestError, profile::TestProfile, run::{ParsingMode, RunnerConfig}, }; use wasmi::Config; macro_rules! define_tests { ( let folder = $test_folder:literal; let config = $get_config:expr; let runner = $runner_fn:path; $( $(#[$attr:meta])* fn $test_name:ident($file_name:literal); )* ) => { $( #[test] $( #[$attr] )* fn $test_name() { let name: &'static ::core::primitive::str = ::core::concat!($test_folder, "/", $file_name); let file: &'static ::core::primitive::str = self::blobs::$test_name(); $runner_fn(name, file, $get_config) } )* }; } macro_rules! define_spec_tests { ( let config = $get_config:expr; let runner = $runner_fn:path; $( $(#[$attr:meta])* fn $test_name:ident($file_name:literal); )* ) => { define_tests! { let folder = "testsuite"; let config = $get_config; let runner = $runner_fn; $( $( #[$attr] )* fn $test_name($file_name); )* } }; } /// Create a [`Config`] for the Wasm MVP feature set. fn mvp_config() -> Config { let mut config = Config::default(); config .wasm_mutable_global(false) .wasm_saturating_float_to_int(false) .wasm_sign_extension(false) .wasm_multi_value(false); config } /// Create a [`Config`] with all Wasm feature supported by Wasmi enabled. /// /// # Note /// /// The Wasm MVP has no Wasm proposals enabled. fn test_config(consume_fuel: bool, mode: ParsingMode) -> RunnerConfig { let mut config = mvp_config(); // We have to enable the `mutable-global` Wasm proposal because // it seems that the entire Wasm spec test suite is already built // on the basis of its semantics. config .wasm_mutable_global(true) .wasm_saturating_float_to_int(true) .wasm_sign_extension(true) .wasm_multi_value(true) .wasm_bulk_memory(true) .wasm_reference_types(true) .wasm_tail_call(true) .wasm_extended_const(true) .consume_fuel(consume_fuel); RunnerConfig { config, mode } } macro_rules! expand_tests { ( $mac:ident, $( $args:tt )* ) => { $mac! { $( $args )* fn wasm_address("address"); fn wasm_align("align"); fn wasm_binary_leb128("binary-leb128"); fn wasm_binary("binary"); fn wasm_block("block"); fn wasm_br("br"); fn wasm_br_if("br_if"); fn wasm_br_table("br_table"); fn wasm_bulk("bulk"); fn wasm_call("call"); fn wasm_call_indirect("call_indirect"); fn wasm_extended_const_data("proposals/extended-const/data"); fn wasm_extended_const_elem("proposals/extended-const/elem"); fn wasm_extended_const_global("proposals/extended-const/global"); fn wasm_return_call("proposals/tail-call/return_call"); fn wasm_return_call_indirect("proposals/tail-call/return_call_indirect"); fn wasm_comments("comments"); fn wasm_const("const"); fn wasm_conversions("conversions"); fn wasm_custom("custom"); fn wasm_data("data"); fn wasm_elem("elem"); fn wasm_endianness("endianness"); fn wasm_exports("exports"); fn wasm_f32("f32"); fn wasm_f32_bitwise("f32_bitwise"); fn wasm_f32_cmp("f32_cmp"); fn wasm_f64("f64"); fn wasm_f64_bitwise("f64_bitwise"); fn wasm_f64_cmp("f64_cmp"); fn wasm_fac("fac"); fn wasm_float_exprs("float_exprs"); fn wasm_float_literals("float_literals"); fn wasm_float_memory("float_memory"); fn wasm_float_misc("float_misc"); fn wasm_forward("forward"); fn wasm_func("func"); fn wasm_func_ptrs("func_ptrs"); fn wasm_global("global"); fn wasm_i32("i32"); fn wasm_i64("i64"); fn wasm_if("if"); fn wasm_imports("imports"); fn wasm_inline_module("inline-module"); fn wasm_int_exprs("int_exprs"); fn wasm_int_literals("int_literals"); fn wasm_labels("labels"); fn wasm_left_to_right("left-to-right"); fn wasm_linking("linking"); fn wasm_load("load"); fn wasm_local_get("local_get"); fn wasm_local_set("local_set"); fn wasm_local_tee("local_tee"); fn wasm_loop("loop"); fn wasm_memory("memory"); fn wasm_memory_copy("memory_copy"); fn wasm_memory_fill("memory_fill"); fn wasm_memory_grow("memory_grow"); fn wasm_memory_init("memory_init"); fn wasm_memory_redundancy("memory_redundancy"); fn wasm_memory_size("memory_size"); fn wasm_memory_trap("memory_trap"); fn wasm_names("names"); fn wasm_nop("nop"); fn wasm_ref_func("ref_func"); fn wasm_ref_is_null("ref_is_null"); fn wasm_ref_null("ref_null"); fn wasm_return("return"); fn wasm_select("select"); fn wasm_skip_stack_guard_page("skip-stack-guard-page"); fn wasm_stack("stack"); fn wasm_start("start"); fn wasm_store("store"); fn wasm_switch("switch"); fn wasm_table_sub("table-sub"); fn wasm_table("table"); fn wasm_table_copy("table_copy"); fn wasm_table_fill("table_fill"); fn wasm_table_get("table_get"); fn wasm_table_grow("table_grow"); fn wasm_table_init("table_init"); fn wasm_table_set("table_set"); fn wasm_table_size("table_size"); fn wasm_token("token"); fn wasm_traps("traps"); fn wasm_type("type"); fn wasm_unreachable("unreachable"); fn wasm_unreached_invalid("unreached-invalid"); fn wasm_unreached_valid("unreached-valid"); fn wasm_unwind("unwind"); fn wasm_utf8_custom_section_id("utf8-custom-section-id"); fn wasm_utf8_import_field("utf8-import-field"); fn wasm_utf8_import_module("utf8-import-module"); fn wasm_utf8_invalid_encoding("utf8-invalid-encoding"); } }; } macro_rules! include_wasm_blobs { ( let folder = $test_folder:literal; $( $(#[$attr:meta])* fn $test_name:ident($file_name:literal); )* ) => { $( $( #[$attr] )* pub fn $test_name() -> &'static str { ::core::include_str!( ::core::concat!($test_folder, "/", $file_name, ".wast") ) } )* }; } mod blobs { expand_tests! { include_wasm_blobs, let folder = "testsuite"; } } expand_tests! { define_spec_tests, let config = test_config(false, ParsingMode::Buffered); let runner = run::run_wasm_spec_test; } mod fueled { use super::*; expand_tests! { define_spec_tests, let config = test_config(true, ParsingMode::Buffered); let runner = run::run_wasm_spec_test; } } mod streaming { use super::*; expand_tests! { define_spec_tests, let config = test_config(false, ParsingMode::Streaming); let runner = run::run_wasm_spec_test; } }