mirror of
https://github.com/fluencelabs/wasmer
synced 2025-04-24 18:02:13 +00:00
Added automatic test generator from wasm spec
This commit is contained in:
parent
5c5fbd309d
commit
a932fef217
@ -5,6 +5,7 @@ authors = ["Syrus Akbary <me@syrusakbary.com>"]
|
||||
edition = "2018"
|
||||
repository = "https://github.com/wafoundation/wasmer"
|
||||
publish = false
|
||||
build = "src/build_spectests.rs"
|
||||
|
||||
[dependencies]
|
||||
cranelift-native = "0.22.0"
|
||||
@ -30,6 +31,9 @@ log = "0.4.5"
|
||||
target-lexicon = { version = "0.0.3", default-features = false }
|
||||
libc = "0.2"
|
||||
|
||||
[build-dependencies]
|
||||
wabt = "0.6.0"
|
||||
|
||||
[dev-dependencies]
|
||||
libffi = "0.6.4"
|
||||
# maplit = "1.0.1"
|
||||
|
@ -110,18 +110,18 @@
|
||||
|
||||
(assert_return (invoke "type-i32") (i32.const 0x132))
|
||||
(assert_return (invoke "type-i64") (i64.const 0x164))
|
||||
;; (assert_return (invoke "type-f32") (f32.const 0xf32))
|
||||
;; (assert_return (invoke "type-f64") (f64.const 0xf64))
|
||||
(assert_return (invoke "type-f32") (f32.const 0xf32))
|
||||
(assert_return (invoke "type-f64") (f64.const 0xf64))
|
||||
|
||||
(assert_return (invoke "type-first-i32") (i32.const 32))
|
||||
(assert_return (invoke "type-first-i64") (i64.const 64))
|
||||
;; (assert_return (invoke "type-first-f32") (f32.const 1.32))
|
||||
;; (assert_return (invoke "type-first-f64") (f64.const 1.64))
|
||||
(assert_return (invoke "type-first-f32") (f32.const 1.32))
|
||||
(assert_return (invoke "type-first-f64") (f64.const 1.64))
|
||||
|
||||
(assert_return (invoke "type-second-i32") (i32.const 32))
|
||||
(assert_return (invoke "type-second-i64") (i64.const 64))
|
||||
;; (assert_return (invoke "type-second-f32") (f32.const 32))
|
||||
;; (assert_return (invoke "type-second-f64") (f64.const 64.1))
|
||||
(assert_return (invoke "type-second-f32") (f32.const 32))
|
||||
(assert_return (invoke "type-second-f64") (f64.const 64.1))
|
||||
|
||||
(assert_return (invoke "fac" (i64.const 0)) (i64.const 1))
|
||||
(assert_return (invoke "fac" (i64.const 1)) (i64.const 1))
|
74
spectests/memory.wast
Normal file
74
spectests/memory.wast
Normal file
@ -0,0 +1,74 @@
|
||||
|
||||
(module (memory 0 0))
|
||||
(module (memory 0 1))
|
||||
(module (memory 1 256))
|
||||
(module (memory 0 65536))
|
||||
|
||||
(assert_invalid (module (memory 0) (memory 0)) "multiple memories")
|
||||
(assert_invalid (module (memory (import "spectest" "memory") 0) (memory 0)) "multiple memories")
|
||||
|
||||
(module (memory (data)) (func (export "memsize") (result i32) (memory.size)))
|
||||
(assert_return (invoke "memsize") (i32.const 0))
|
||||
(module (memory (data "")) (func (export "memsize") (result i32) (memory.size)))
|
||||
(assert_return (invoke "memsize") (i32.const 0))
|
||||
(module (memory (data "x")) (func (export "memsize") (result i32) (memory.size)))
|
||||
(assert_return (invoke "memsize") (i32.const 1))
|
||||
|
||||
(assert_invalid (module (data (i32.const 0))) "unknown memory")
|
||||
(assert_invalid (module (data (i32.const 0) "")) "unknown memory")
|
||||
(assert_invalid (module (data (i32.const 0) "x")) "unknown memory")
|
||||
|
||||
(assert_invalid
|
||||
(module (func (drop (f32.load (i32.const 0)))))
|
||||
"unknown memory"
|
||||
)
|
||||
(assert_invalid
|
||||
(module (func (f32.store (f32.const 0) (i32.const 0))))
|
||||
"unknown memory"
|
||||
)
|
||||
(assert_invalid
|
||||
(module (func (drop (i32.load8_s (i32.const 0)))))
|
||||
"unknown memory"
|
||||
)
|
||||
(assert_invalid
|
||||
(module (func (i32.store8 (i32.const 0) (i32.const 0))))
|
||||
"unknown memory"
|
||||
)
|
||||
(assert_invalid
|
||||
(module (func (drop (memory.size))))
|
||||
"unknown memory"
|
||||
)
|
||||
(assert_invalid
|
||||
(module (func (drop (memory.grow (i32.const 0)))))
|
||||
"unknown memory"
|
||||
)
|
||||
|
||||
|
||||
(assert_invalid
|
||||
(module (memory 1 0))
|
||||
"size minimum must not be greater than maximum"
|
||||
)
|
||||
(assert_invalid
|
||||
(module (memory 65537))
|
||||
"memory size must be at most 65536 pages (4GiB)"
|
||||
)
|
||||
(assert_invalid
|
||||
(module (memory 2147483648))
|
||||
"memory size must be at most 65536 pages (4GiB)"
|
||||
)
|
||||
(assert_invalid
|
||||
(module (memory 4294967295))
|
||||
"memory size must be at most 65536 pages (4GiB)"
|
||||
)
|
||||
(assert_invalid
|
||||
(module (memory 0 65537))
|
||||
"memory size must be at most 65536 pages (4GiB)"
|
||||
)
|
||||
(assert_invalid
|
||||
(module (memory 0 2147483648))
|
||||
"memory size must be at most 65536 pages (4GiB)"
|
||||
)
|
||||
(assert_invalid
|
||||
(module (memory 0 4294967295))
|
||||
"memory size must be at most 65536 pages (4GiB)"
|
||||
)
|
266
src/build_spectests.rs
Normal file
266
src/build_spectests.rs
Normal file
@ -0,0 +1,266 @@
|
||||
use std::fs;
|
||||
use std::io::{self, Read};
|
||||
use std::path::PathBuf;
|
||||
use std::time::SystemTime;
|
||||
use wabt::script::{Action, Command, CommandKind, ModuleBinary, ScriptParser, Value};
|
||||
use wabt::wasm2wat;
|
||||
|
||||
struct WastTestGenerator {
|
||||
last_module: i32,
|
||||
last_line: u64,
|
||||
filename: String,
|
||||
script_parser: ScriptParser,
|
||||
buffer: String,
|
||||
}
|
||||
|
||||
fn wabt2rust_type(v: &Value) -> String {
|
||||
match v {
|
||||
Value::I32(v) => format!("i32"),
|
||||
Value::I64(v) => format!("i64"),
|
||||
Value::F32(v) => format!("f32"),
|
||||
Value::F64(v) => format!("f64"),
|
||||
}
|
||||
}
|
||||
|
||||
fn wabt2rust_value(v: &Value) -> String {
|
||||
match v {
|
||||
Value::I32(v) => format!("{:?} as i32", v),
|
||||
Value::I64(v) => format!("{:?} as i64", v),
|
||||
Value::F32(v) => format!("{:?} as f32", v),
|
||||
Value::F64(v) => format!("{:?} as f64", v),
|
||||
}
|
||||
}
|
||||
|
||||
impl WastTestGenerator {
|
||||
fn new(path: &PathBuf) -> Self {
|
||||
let filename = path.file_name().unwrap().to_str().unwrap();
|
||||
let source = fs::read(&path).unwrap();
|
||||
let mut script: ScriptParser =
|
||||
ScriptParser::from_source_and_name(&source, filename).unwrap();
|
||||
let mut buffer = String::new();
|
||||
WastTestGenerator {
|
||||
last_module: 0,
|
||||
last_line: 0,
|
||||
filename: filename.to_string(),
|
||||
script_parser: script,
|
||||
buffer: buffer,
|
||||
}
|
||||
}
|
||||
|
||||
fn consume(&mut self) {
|
||||
self.buffer.push_str(&format!(
|
||||
"// Rust test file autogenerated from {}
|
||||
// Please do not modify
|
||||
|
||||
use crate::webassembly::{{instantiate, compile, ImportObject, ResultObject, VmCtx, Export}};
|
||||
use wabt::wat2wasm;\n\n",
|
||||
self.filename
|
||||
));
|
||||
while let Some(Command { line, kind }) = &self.script_parser.next().unwrap() {
|
||||
self.last_line = line.clone();
|
||||
self.buffer
|
||||
.push_str(&format!("\n// Line {}\n", self.last_line));
|
||||
self.visit_command(&kind);
|
||||
// &self.buffer.push_str(convert_command(kind));
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_module(&mut self, module: &ModuleBinary, name: &Option<String>) {
|
||||
let wasm_binary: Vec<u8> = module.clone().into_vec();
|
||||
let wast_string = wasm2wat(wasm_binary).expect("Can't convert back to wasm");
|
||||
self.last_module = self.last_module + 1;
|
||||
self.buffer.push_str(
|
||||
format!(
|
||||
"fn create_module_{}() -> ResultObject {{
|
||||
let module_str = \"{}\";
|
||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect(\"WAST not valid or malformed\");
|
||||
instantiate(wasm_binary, ImportObject::new()).expect(\"WASM can't be instantiated\")
|
||||
}}\n",
|
||||
self.last_module,
|
||||
// We do this to ident four spaces back
|
||||
wast_string.replace("\n", "\n ").replace("\"", "\\\""),
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
|
||||
fn visit_assert_invalid(&mut self, module: &ModuleBinary) {
|
||||
let wasm_binary: Vec<u8> = module.clone().into_vec();
|
||||
// let wast_string = wasm2wat(wasm_binary).expect("Can't convert back to wasm");
|
||||
self.buffer.push_str(
|
||||
format!(
|
||||
"
|
||||
#[test]
|
||||
fn l{}_assert_invalid() {{
|
||||
let wasm_binary = {:?};
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), \"WASM should not compile as is invalid\");
|
||||
}}\n",
|
||||
self.last_line,
|
||||
wasm_binary,
|
||||
// We do this to ident four spaces back
|
||||
// String::from_utf8_lossy(&wasm_binary),
|
||||
// wast_string.replace("\n", "\n "),
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
fn visit_assert_malformed(&mut self, module: &ModuleBinary) {
|
||||
let wasm_binary: Vec<u8> = module.clone().into_vec();
|
||||
// let wast_string = wasm2wat(wasm_binary).expect("Can't convert back to wasm");
|
||||
self.buffer.push_str(
|
||||
format!(
|
||||
"
|
||||
#[test]
|
||||
fn l{}_assert_malformed() {{
|
||||
let wasm_binary = {:?};
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), \"WASM should not compile as is malformed\");
|
||||
}}\n",
|
||||
self.last_line,
|
||||
wasm_binary,
|
||||
// We do this to ident four spaces back
|
||||
// String::from_utf8_lossy(&wasm_binary),
|
||||
// wast_string.replace("\n", "\n "),
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
|
||||
fn visit_assert_return(&mut self, action: &Action, expected: &Vec<Value>) {
|
||||
match action {
|
||||
Action::Invoke {
|
||||
module,
|
||||
field,
|
||||
args,
|
||||
} => {
|
||||
let func_return = if expected.len() > 0 {
|
||||
format!(" -> {}", wabt2rust_type(&expected[0]))
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
let expected_result = if expected.len() > 0 {
|
||||
wabt2rust_value(&expected[0])
|
||||
} else {
|
||||
"()".to_string()
|
||||
};
|
||||
// We map the arguments provided into the raw Arguments provided
|
||||
// to libffi
|
||||
let mut args_types: Vec<String> = args.iter().map(wabt2rust_type).collect();
|
||||
args_types.push("&VmCtx".to_string());
|
||||
let mut args_values: Vec<String> = args.iter().map(wabt2rust_value).collect();
|
||||
args_values.push("&vm_context".to_string());
|
||||
self.buffer.push_str(
|
||||
format!(
|
||||
"#[test]
|
||||
fn l{}_assert_return_invoke() {{
|
||||
let ResultObject {{ mut instance, module }} = create_module_{}();
|
||||
let func_index = match module.info.exports.get({:?}) {{
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!(\"Function not found\"),
|
||||
}};
|
||||
let invoke_fn: fn({}){} = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn({});
|
||||
assert_eq!(result, {});
|
||||
}}\n",
|
||||
self.last_line,
|
||||
self.last_module,
|
||||
field,
|
||||
args_types.join(", "),
|
||||
func_return,
|
||||
args_values.join(", "),
|
||||
expected_result,
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
fn visit_command(&mut self, cmd: &CommandKind) {
|
||||
match cmd {
|
||||
CommandKind::Module { module, name } => {
|
||||
self.visit_module(module, name);
|
||||
// c.module(module.into_vec(), name);
|
||||
}
|
||||
CommandKind::AssertReturn { action, expected } => {
|
||||
self.visit_assert_return(action, expected);
|
||||
}
|
||||
CommandKind::AssertReturnCanonicalNan { action } => {
|
||||
// c.assert_return_canonical_nan(action);
|
||||
}
|
||||
CommandKind::AssertReturnArithmeticNan { action } => {
|
||||
// c.assert_return_arithmetic_nan(action);
|
||||
}
|
||||
CommandKind::AssertTrap { action, message: _ } => {
|
||||
// c.assert_trap(action);
|
||||
}
|
||||
CommandKind::AssertInvalid { module, message: _ } => {
|
||||
self.visit_assert_invalid(module);
|
||||
}
|
||||
CommandKind::AssertMalformed { module, message: _ } => {
|
||||
self.visit_assert_malformed(module);
|
||||
// c.assert_malformed(module.into_vec());
|
||||
}
|
||||
CommandKind::AssertUninstantiable { module, message: _ } => {
|
||||
// c.assert_uninstantiable(module.into_vec());
|
||||
}
|
||||
CommandKind::AssertExhaustion { action } => {
|
||||
// c.assert_exhaustion(action);
|
||||
}
|
||||
CommandKind::AssertUnlinkable { module, message: _ } => {
|
||||
// c.assert_unlinkable(module.into_vec());
|
||||
}
|
||||
CommandKind::Register { name, as_name } => {
|
||||
// c.register(name, as_name);
|
||||
}
|
||||
CommandKind::PerformAction(action) => {
|
||||
// c.action(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn finalize(self) -> String {
|
||||
self.buffer
|
||||
}
|
||||
}
|
||||
|
||||
fn wast_to_rust(wast_filepath: &str) {
|
||||
let wast_filepath = format!("{}/{}", env!("CARGO_MANIFEST_DIR"), wast_filepath);
|
||||
let path = PathBuf::from(&wast_filepath);
|
||||
let script_name = path.file_stem().unwrap().to_str().unwrap();
|
||||
let rust_test_filepath = format!(
|
||||
concat!(env!("CARGO_MANIFEST_DIR"), "/src/spectests/{}.rs"),
|
||||
script_name
|
||||
);
|
||||
|
||||
let wast_modified = fs::metadata(&wast_filepath)
|
||||
.expect("Can't get wast file metadata")
|
||||
.modified()
|
||||
.expect("Can't get wast file modified date");
|
||||
let should_modify = match fs::metadata(&rust_test_filepath) {
|
||||
Ok(m) => {
|
||||
m.modified()
|
||||
.expect("Can't get rust test file modified date")
|
||||
< wast_modified
|
||||
}
|
||||
Err(_) => true,
|
||||
};
|
||||
|
||||
// panic!("SOULD MODIFY {:?} {:?}", should_modify, rust_test_filepath);
|
||||
|
||||
if should_modify {
|
||||
let mut generator = WastTestGenerator::new(&path);
|
||||
generator.consume();
|
||||
let generated_script = generator.finalize();
|
||||
fs::write(&rust_test_filepath, generated_script.as_bytes()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
wast_to_rust("spectests/br_if.wast");
|
||||
wast_to_rust("spectests/call.wast");
|
||||
wast_to_rust("spectests/memory.wast");
|
||||
wast_to_rust("spectests/types.wast");
|
||||
}
|
@ -33,7 +33,7 @@ use wabt::wat2wasm;
|
||||
mod macros;
|
||||
pub mod common;
|
||||
pub mod integrations;
|
||||
pub mod spec;
|
||||
pub mod spectests;
|
||||
pub mod webassembly;
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
|
697
src/spec/mod.rs
697
src/spec/mod.rs
@ -1,697 +0,0 @@
|
||||
// Code adapted from greenwasm-spectest
|
||||
// https://github.com/Kimundi/greenwasm/blob/master/greenwasm-spectest/src/lib.rs
|
||||
|
||||
#![deny(missing_docs)]
|
||||
|
||||
//! A library shim around a mirror of the
|
||||
//! official [webassembly MVP testsuite](https://github.com/WebAssembly/spec/tree/master/test/core).
|
||||
//!
|
||||
//! It can be used as a independent testsuite launcher for other
|
||||
//! webassembly implementations by implementing `ScriptHandler`.
|
||||
//!
|
||||
//! Example:
|
||||
//! ```should_fail
|
||||
/*!
|
||||
use wasmer::spec::*;
|
||||
struct DummyHandler;
|
||||
impl ScriptHandler for DummyHandler {
|
||||
fn reset(&mut self) {}
|
||||
fn action_invoke(&mut self,
|
||||
module: Option<String>,
|
||||
field: String,
|
||||
args: Vec<Value>) -> InvokationResult
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
fn action_get(&mut self,
|
||||
module: Option<String>,
|
||||
field: String) -> Value
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
fn module(&mut self, bytes: Vec<u8>, name: Option<String>) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn assert_malformed(&mut self, bytes: Vec<u8>) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn assert_invalid(&mut self, bytes: Vec<u8>) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn assert_uninstantiable(&mut self, bytes: Vec<u8>) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn assert_exhaustion(&mut self, action: Action) {
|
||||
unimplemented!()
|
||||
}
|
||||
fn register(&mut self, name: Option<String>, as_name: String) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
run_mvp_spectest(&mut DummyHandler).present();
|
||||
*/
|
||||
//! ```
|
||||
//! This would result in a output like this:
|
||||
//! ```text
|
||||
/*!
|
||||
Executing address.wast ...
|
||||
Executing align.wast ...
|
||||
Executing binary.wast ...
|
||||
Executing block.wast ...
|
||||
Executing br.wast ...
|
||||
[...]
|
||||
wast failures:
|
||||
address.wast:3, not yet implemented
|
||||
address.wast:104, <not attempted>
|
||||
address.wast:105, <not attempted>
|
||||
...
|
||||
wast total: 0 passed; 17955 failed
|
||||
*/
|
||||
//! ```
|
||||
|
||||
pub extern crate wabt;
|
||||
pub use wabt::script::Action;
|
||||
pub use wabt::script::CommandKind;
|
||||
pub use wabt::script::Value;
|
||||
|
||||
use std::path::Path;
|
||||
use wabt::script::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// Handles the different script commands of the `*.wast` format.
|
||||
pub trait ScriptHandler {
|
||||
/// Reset all state of the handler, specifically
|
||||
/// clearing all loaded modules and assuming a new script file.
|
||||
fn reset(&mut self);
|
||||
|
||||
/// Handles an `invoke` action.
|
||||
///
|
||||
/// Should call a exported function with name `field` and arguments
|
||||
/// `args` from a loaded module.
|
||||
///
|
||||
/// Targets either the last loaded module if `module` is None, or
|
||||
/// the module registered with the given name otherwise.
|
||||
fn action_invoke(
|
||||
&mut self,
|
||||
module: Option<String>,
|
||||
field: String,
|
||||
args: Vec<Value>,
|
||||
) -> InvokationResult;
|
||||
|
||||
/// Handles an `get` action.
|
||||
///
|
||||
/// Should get a exported global with name `field` from a loaded module.
|
||||
///
|
||||
/// Targets either the last loaded module if `module` is None, or
|
||||
/// the module registered with the given name otherwise.
|
||||
fn action_get(&mut self, module: Option<String>, field: String) -> Value;
|
||||
|
||||
/// Handles an `action`.
|
||||
///
|
||||
/// The default implementation dispatches to `action_get` or `
|
||||
/// action_invoke`, gathers the result in an vector, and panics
|
||||
/// if a function call trapped or exhausted the stack.
|
||||
fn action(&mut self, action: Action) -> Vec<Value> {
|
||||
match action {
|
||||
Action::Invoke {
|
||||
module,
|
||||
field,
|
||||
args,
|
||||
} => {
|
||||
if let InvokationResult::Vals(v) = self.action_invoke(module, field, args) {
|
||||
v
|
||||
} else {
|
||||
panic!("invokation returned Trap or exhausted the stack");
|
||||
}
|
||||
}
|
||||
Action::Get { module, field } => vec![self.action_get(module, field)],
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles a module load.
|
||||
///
|
||||
/// The webassembly module is passed in its binary format in
|
||||
/// the `bytes` argument.
|
||||
///
|
||||
/// If `name` is `Some`, it should be registered under that name.
|
||||
/// In any case it should count as the least recently loaded module.
|
||||
fn module(&mut self, bytes: Vec<u8>, name: Option<String>);
|
||||
|
||||
/// Handles an `assert_return`.
|
||||
///
|
||||
/// Per default panics if the result of handling the `action`
|
||||
/// does not result in the `expected` values.
|
||||
///
|
||||
/// Floating point values should, and per default are,
|
||||
/// compared according to their bit-pattern, and not their normal
|
||||
/// `PartialEq` semantic. See the `NanCompare` wrapper type.
|
||||
fn assert_return(&mut self, action: Action, expected: Vec<Value>) {
|
||||
let results = self.action(action);
|
||||
assert_eq!(NanCompare(&expected), NanCompare(&results));
|
||||
}
|
||||
|
||||
/// Handles an `assert_trap`.
|
||||
///
|
||||
/// Per default panics if the result of handling the `action`
|
||||
/// does not trap, or refers to an global.
|
||||
fn assert_trap(&mut self, action: Action) {
|
||||
match action {
|
||||
Action::Invoke {
|
||||
module,
|
||||
field,
|
||||
args,
|
||||
} => {
|
||||
if let InvokationResult::Vals(results) = self.action_invoke(module, field, args) {
|
||||
panic!("invokation did not trap, but returned {:?}", results);
|
||||
}
|
||||
}
|
||||
Action::Get { .. } => panic!("a global access can not trap!"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles an `assert_malformed`.
|
||||
///
|
||||
/// The webassembly module is passed in its binary format in
|
||||
/// the `bytes` argument.
|
||||
///
|
||||
/// Should panic if the module can be successfully decoded.
|
||||
fn assert_malformed(&mut self, bytes: Vec<u8>);
|
||||
|
||||
/// Handles an `assert_malformed`.
|
||||
///
|
||||
/// The webassembly module is passed in its binary format in
|
||||
/// the `bytes` argument.
|
||||
///
|
||||
/// Should panic if the module can be successfully decoded.
|
||||
fn assert_invalid(&mut self, bytes: Vec<u8>);
|
||||
|
||||
/// Handles an `assert_unlinkable`.
|
||||
///
|
||||
/// The webassembly module is passed in its binary format in
|
||||
/// the `bytes` argument.
|
||||
///
|
||||
/// Should panic if the module can be successfully linked.
|
||||
///
|
||||
/// This seems to be a legacy script command, and per default
|
||||
/// just invokes `assert_uninstantiable`.
|
||||
fn assert_unlinkable(&mut self, bytes: Vec<u8>) {
|
||||
// TODO: figure out the exact difference
|
||||
// Currently it looks like a link error is any instantiation error except
|
||||
// a runtime error during execution of a start function
|
||||
self.assert_uninstantiable(bytes);
|
||||
}
|
||||
|
||||
/// Handles an `assert_uninstantiable`.
|
||||
///
|
||||
/// The webassembly module is passed in its binary format in
|
||||
/// the `bytes` argument.
|
||||
///
|
||||
/// Should panic if the module can be successfully instantiated.
|
||||
fn assert_uninstantiable(&mut self, bytes: Vec<u8>);
|
||||
|
||||
/// Handles an `assert_trap`.
|
||||
///
|
||||
/// Should panic if the result of handling the `action`
|
||||
/// does not exhaust the stack, or refers to an global.
|
||||
fn assert_exhaustion(&mut self, action: Action);
|
||||
|
||||
/// Handles an `assert_return_canonical_nan`.
|
||||
///
|
||||
/// Per default panics if the result of handling the `action`
|
||||
/// does not result in single canonical NaN floating point value.
|
||||
///
|
||||
/// Any canonical NaN is also a arithmetic NaN.
|
||||
///
|
||||
/// Floating point values should, and per default are,
|
||||
/// compared according to their bit-pattern, and not their normal
|
||||
/// `PartialEq` semantic. See the `NanCompare` wrapper type.
|
||||
fn assert_return_canonical_nan(&mut self, action: Action) {
|
||||
let results = self.action(action);
|
||||
match *results {
|
||||
[Value::F32(v)] if v.is_canonical_nan() => {}
|
||||
[Value::F64(v)] if v.is_canonical_nan() => {}
|
||||
ref x => {
|
||||
panic!("unexpected value {:?}", NanCompare(x));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles an `assert_return_arithmetic_nan`.
|
||||
///
|
||||
/// Per default panics if the result of handling the `action`
|
||||
/// does not result in single arithmetic NaN floating point value.
|
||||
///
|
||||
/// Any canonical NaN is also a arithmetic NaN.
|
||||
///
|
||||
/// Floating point values should, and per default are,
|
||||
/// compared according to their bit-pattern, and not their normal
|
||||
/// `PartialEq` semantic. See the `NanCompare` wrapper type.
|
||||
fn assert_return_arithmetic_nan(&mut self, action: Action) {
|
||||
let results = self.action(action);
|
||||
match *results {
|
||||
[Value::F32(v)] if v.is_arithmetic_nan() => {}
|
||||
[Value::F64(v)] if v.is_arithmetic_nan() => {}
|
||||
ref x => {
|
||||
panic!("unexpected value {:?}", NanCompare(x));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Register a loaded module under the name `as_name`.
|
||||
///
|
||||
/// If `name` is `Some`, it should be registered under that name.
|
||||
/// In any case it should count as the least recently loaded module.
|
||||
fn register(&mut self, name: Option<String>, as_name: String);
|
||||
}
|
||||
|
||||
/// Wrapper type that compares a list of `wabt` `Value`s
|
||||
/// according to their bit-pattern if they contain floating point values,
|
||||
/// and according to regular `PartialEq` semantics otherwise.
|
||||
pub struct NanCompare<'a>(pub &'a [Value]);
|
||||
|
||||
impl<'a> ::std::cmp::PartialEq for NanCompare<'a> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
if self.0.len() != other.0.len() {
|
||||
return false;
|
||||
}
|
||||
self.0.iter().zip(other.0.iter()).all(|pair| match pair {
|
||||
(Value::I32(l), Value::I32(r)) => l == r,
|
||||
(Value::I64(l), Value::I64(r)) => l == r,
|
||||
(Value::F32(l), Value::F32(r)) if l.is_nan() && r.is_nan() => {
|
||||
l.payload() == r.payload()
|
||||
}
|
||||
(Value::F64(l), Value::F64(r)) if l.is_nan() && r.is_nan() => {
|
||||
l.payload() == r.payload()
|
||||
}
|
||||
(Value::F32(l), Value::F32(r)) => l == r,
|
||||
(Value::F64(l), Value::F64(r)) => l == r,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl<'a> ::std::fmt::Debug for NanCompare<'a> {
|
||||
fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
formatter
|
||||
.debug_list()
|
||||
.entries(self.0.iter().map(|e| match e {
|
||||
Value::F32(v) if v.is_nan() => {
|
||||
let p = v.payload();
|
||||
format!("F32(NaN:0x{:x})", p)
|
||||
}
|
||||
Value::F64(v) if v.is_nan() => {
|
||||
let p = v.payload();
|
||||
format!("F64(NaN:0x{:x})", p)
|
||||
}
|
||||
_ => format!("{:?}", e),
|
||||
}))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Result of invoking a function.
|
||||
pub enum InvokationResult {
|
||||
/// The function returned successfully with a number of `Value`s
|
||||
Vals(Vec<Value>),
|
||||
/// The function trapped.
|
||||
Trap,
|
||||
/// The function exhausted the stack.
|
||||
StackExhaustion,
|
||||
}
|
||||
|
||||
/// Extension trait for floating point values.
|
||||
///
|
||||
/// Provides methods for accessing the payload
|
||||
/// of a NaN according to the webassembly spec.
|
||||
///
|
||||
/// According to the spec, any canonical NaN is also an arithmetic one.
|
||||
pub trait NanPayload {
|
||||
/// Returns the payload bits of a NaN value.
|
||||
fn payload(&self) -> u64;
|
||||
/// Returns the number of significant digits in a NaN value.
|
||||
fn signif() -> u32;
|
||||
/// Returns positive infinite.
|
||||
fn infinite() -> Self;
|
||||
/// Returns the payload of a canonical NaN.
|
||||
fn canonical_payload() -> u64;
|
||||
/// Returns an arithmetic NaN with the given payload.
|
||||
fn arithmetic_nan(payload: u64) -> Self;
|
||||
/// Returns a canonical NaN.
|
||||
fn canonical_nan() -> Self;
|
||||
/// Checks if a value is an arithmetic NaN.
|
||||
fn is_arithmetic_nan(&self) -> bool;
|
||||
/// Checks if a value is a canonical NaN.
|
||||
fn is_canonical_nan(&self) -> bool;
|
||||
}
|
||||
impl NanPayload for f32 {
|
||||
fn payload(&self) -> u64 {
|
||||
assert!(self.is_nan());
|
||||
let bits: u32 = self.to_bits();
|
||||
let mask: u32 = (1u32 << 23) - 1;
|
||||
let p = bits & mask;
|
||||
p as u64
|
||||
}
|
||||
fn signif() -> u32 {
|
||||
23
|
||||
}
|
||||
fn infinite() -> Self {
|
||||
1.0 / 0.0
|
||||
}
|
||||
fn canonical_payload() -> u64 {
|
||||
1u64 << (Self::signif() - 1)
|
||||
}
|
||||
fn arithmetic_nan(payload: u64) -> Self {
|
||||
assert!(payload >= Self::canonical_payload());
|
||||
let bits: u32 = Self::infinite().to_bits();
|
||||
let mask: u32 = (1u32 << Self::signif()) - 1;
|
||||
let bits = bits | (mask & (payload as u32));
|
||||
Self::from_bits(bits)
|
||||
}
|
||||
fn canonical_nan() -> Self {
|
||||
Self::arithmetic_nan(Self::canonical_payload())
|
||||
}
|
||||
fn is_arithmetic_nan(&self) -> bool {
|
||||
self.is_nan()
|
||||
}
|
||||
fn is_canonical_nan(&self) -> bool {
|
||||
self.is_nan() && self.abs().to_bits() == Self::canonical_nan().to_bits()
|
||||
}
|
||||
}
|
||||
impl NanPayload for f64 {
|
||||
fn payload(&self) -> u64 {
|
||||
assert!(self.is_nan());
|
||||
let bits: u64 = self.to_bits();
|
||||
let mask: u64 = (1u64 << 52) - 1;
|
||||
let p = bits & mask;
|
||||
p
|
||||
}
|
||||
fn signif() -> u32 {
|
||||
52
|
||||
}
|
||||
fn infinite() -> Self {
|
||||
1.0 / 0.0
|
||||
}
|
||||
fn canonical_payload() -> u64 {
|
||||
1u64 << (Self::signif() - 1)
|
||||
}
|
||||
fn arithmetic_nan(payload: u64) -> Self {
|
||||
assert!(payload >= Self::canonical_payload());
|
||||
let bits: u64 = Self::infinite().to_bits();
|
||||
let mask: u64 = (1u64 << Self::signif()) - 1;
|
||||
let bits = bits | (mask & payload);
|
||||
Self::from_bits(bits)
|
||||
}
|
||||
fn canonical_nan() -> Self {
|
||||
Self::arithmetic_nan(Self::canonical_payload())
|
||||
}
|
||||
fn is_arithmetic_nan(&self) -> bool {
|
||||
self.is_nan()
|
||||
}
|
||||
fn is_canonical_nan(&self) -> bool {
|
||||
self.is_nan() && self.abs().to_bits() == Self::canonical_nan().to_bits()
|
||||
}
|
||||
}
|
||||
|
||||
/// Result of running a series of script commands.
|
||||
#[must_use]
|
||||
pub struct SpectestResult {
|
||||
/// List of failed commands consisting of
|
||||
/// (filename, line number, panic message) tuples.
|
||||
pub failures: Vec<(String, u64, String)>,
|
||||
|
||||
/// Number of successful commands.
|
||||
pub successes: usize,
|
||||
}
|
||||
|
||||
impl SpectestResult {
|
||||
/// Displays the results in `Self` in a form similar
|
||||
/// to Rusts testsuite, and raises an panic if any tests failed.
|
||||
///
|
||||
/// This is intended to be called from a `#[test]` function.
|
||||
pub fn present(self) {
|
||||
if self.failures.len() > 0 {
|
||||
println!("wast failures:");
|
||||
for (i, f) in self.failures.iter().enumerate() {
|
||||
println!(" {}:{}, {}", f.0, f.1, f.2);
|
||||
if i > 10 {
|
||||
println!(" ...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
println!(
|
||||
"wast total: {} passed; {} failed",
|
||||
self.successes,
|
||||
self.failures.len()
|
||||
);
|
||||
panic!("some wast commands failed");
|
||||
} else {
|
||||
println!(
|
||||
"wast total: {} passed; {} failed",
|
||||
self.successes,
|
||||
self.failures.len()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Run all scripts of the bundled webassembly testsuite on `handler`.
|
||||
pub fn run_mvp_spectest<T: ScriptHandler>(handler: &mut T) -> SpectestResult {
|
||||
run_all_in_directory(
|
||||
format!("{}/testsuite", env!("CARGO_MANIFEST_DIR")).as_ref(),
|
||||
handler,
|
||||
)
|
||||
}
|
||||
|
||||
/// Module that is expected under the name "spectest" by all spectest testcases.
|
||||
///
|
||||
/// This is automatically registered by all `run_` functions in this modules
|
||||
/// that work at file granularity or higher.
|
||||
pub const SPECTEST_MODULE: &[u8] = include_bytes!(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/src/spec/spectest.wasm"
|
||||
));
|
||||
|
||||
/// Run all scripts in a given directory on `handler`.
|
||||
pub fn run_all_in_directory<T: ScriptHandler>(path: &Path, handler: &mut T) -> SpectestResult {
|
||||
use std::fs;
|
||||
let mut res = SpectestResult {
|
||||
failures: vec![],
|
||||
successes: 0,
|
||||
};
|
||||
|
||||
println!("\n\nRunning testsuite at {}:\n", path.display());
|
||||
|
||||
'outer: for dir in fs::read_dir(&path).unwrap() {
|
||||
let dir = dir.unwrap();
|
||||
let path = dir.path();
|
||||
let filename = path.file_name().unwrap().to_str().unwrap();
|
||||
|
||||
if path.metadata().unwrap().file_type().is_file() && filename.ends_with(".wast") {
|
||||
println!("Executing {} ...", filename);
|
||||
let res2 = run_single_file(&path, handler);
|
||||
res.successes += res2.successes;
|
||||
res.failures.extend(res2.failures);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Run `handler` on the single `.wast` script file at `path`.
|
||||
pub fn run_single_file<T: ScriptHandler>(path: &Path, handler: &mut T) -> SpectestResult {
|
||||
use std::fs;
|
||||
|
||||
let mut res = SpectestResult {
|
||||
failures: vec![],
|
||||
successes: 0,
|
||||
};
|
||||
|
||||
let filename = path.file_name().unwrap().to_str().unwrap();
|
||||
let source = fs::read(&path).unwrap();
|
||||
|
||||
let mut script = ScriptParser::from_source_and_name(&source, filename).unwrap();
|
||||
let mut fatal = false;
|
||||
|
||||
handler.reset();
|
||||
{
|
||||
let module = SPECTEST_MODULE.to_vec();
|
||||
let name = Some("spectest".into());
|
||||
|
||||
use std::panic::*;
|
||||
|
||||
let r = if let Err(msg) = catch_unwind(AssertUnwindSafe(|| {
|
||||
handler.module(module, name);
|
||||
})) {
|
||||
let msg = if let Some(msg) = msg.downcast_ref::<String>() {
|
||||
msg.to_string()
|
||||
} else if let Some(msg) = msg.downcast_ref::<&'static str>() {
|
||||
msg.to_string()
|
||||
} else {
|
||||
"<unknown>".to_string()
|
||||
};
|
||||
Err(msg)
|
||||
} else {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
match r {
|
||||
Err(msg) => {
|
||||
res.failures
|
||||
.push(("<internal spectest module>".to_owned(), 0, msg));
|
||||
fatal = true;
|
||||
}
|
||||
Ok(()) => {
|
||||
res.successes += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while let Some(Command { line, kind }) = script.next().unwrap() {
|
||||
if fatal {
|
||||
res.failures
|
||||
.push((filename.to_owned(), line, "<not attempted>".to_string()));
|
||||
continue;
|
||||
}
|
||||
match run_single_command(kind, handler) {
|
||||
Err(msg) => {
|
||||
res.failures.push((filename.to_owned(), line, msg));
|
||||
fatal = true;
|
||||
}
|
||||
Ok(()) => {
|
||||
res.successes += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Run `handler` on a single wabt script command, catching any panic that
|
||||
/// might happen in the process.
|
||||
///
|
||||
/// Note that `T` needs to be exception safe, in the sense that any
|
||||
/// panic that happened during a method call should not affect it beyond
|
||||
/// a subsequent `reset()` call.
|
||||
pub fn run_single_command<T: ScriptHandler>(
|
||||
kind: CommandKind,
|
||||
handler: &mut T,
|
||||
) -> Result<(), String> {
|
||||
use std::panic::*;
|
||||
|
||||
if let Err(msg) = catch_unwind(AssertUnwindSafe(|| {
|
||||
run_single_command_no_catch(kind, handler);
|
||||
})) {
|
||||
let msg = if let Some(msg) = msg.downcast_ref::<String>() {
|
||||
msg.to_string()
|
||||
} else if let Some(msg) = msg.downcast_ref::<&'static str>() {
|
||||
msg.to_string()
|
||||
} else {
|
||||
"<unknown>".to_string()
|
||||
};
|
||||
Err(msg)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Run `handler` on a single wabt script command.
|
||||
///
|
||||
/// Unlike `run_single_command`, this does not catch a panic.
|
||||
pub fn run_single_command_no_catch<C: ScriptHandler>(cmd: CommandKind, c: &mut C) {
|
||||
// TODO: Figure out if the "message" fields need to actually be handled
|
||||
use wabt::script::CommandKind::*;
|
||||
match cmd {
|
||||
Module { module, name } => {
|
||||
c.module(module.into_vec(), name);
|
||||
}
|
||||
AssertReturn { action, expected } => {
|
||||
c.assert_return(action, expected);
|
||||
}
|
||||
AssertReturnCanonicalNan { action } => {
|
||||
c.assert_return_canonical_nan(action);
|
||||
}
|
||||
AssertReturnArithmeticNan { action } => {
|
||||
c.assert_return_arithmetic_nan(action);
|
||||
}
|
||||
AssertTrap { action, message: _ } => {
|
||||
c.assert_trap(action);
|
||||
}
|
||||
AssertInvalid { module, message: _ } => {
|
||||
c.assert_invalid(module.into_vec());
|
||||
}
|
||||
AssertMalformed { module, message: _ } => {
|
||||
c.assert_malformed(module.into_vec());
|
||||
}
|
||||
AssertUninstantiable { module, message: _ } => {
|
||||
c.assert_uninstantiable(module.into_vec());
|
||||
}
|
||||
AssertExhaustion { action } => {
|
||||
c.assert_exhaustion(action);
|
||||
}
|
||||
AssertUnlinkable { module, message: _ } => {
|
||||
c.assert_unlinkable(module.into_vec());
|
||||
}
|
||||
Register { name, as_name } => {
|
||||
c.register(name, as_name);
|
||||
}
|
||||
PerformAction(action) => {
|
||||
c.action(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Spectest module .wat, based on wabt's spectest-interp.cc
|
||||
static void InitEnvironment(Environment* env) {
|
||||
HostModule* host_module = env->AppendHostModule("spectest");
|
||||
host_module->AppendFuncExport("print", {{}, {}}, PrintCallback);
|
||||
host_module->AppendFuncExport("print_i32", {{Type::I32}, {}}, PrintCallback);
|
||||
host_module->AppendFuncExport("print_f32", {{Type::F32}, {}}, PrintCallback);
|
||||
host_module->AppendFuncExport("print_f64", {{Type::F64}, {}}, PrintCallback);
|
||||
host_module->AppendFuncExport("print_i32_f32", {{Type::I32, Type::F32}, {}},
|
||||
PrintCallback);
|
||||
host_module->AppendFuncExport("print_f64_f64", {{Type::F64, Type::F64}, {}},
|
||||
PrintCallback);
|
||||
host_module->AppendTableExport("table", Limits(10, 20));
|
||||
host_module->AppendMemoryExport("memory", Limits(1, 2));
|
||||
host_module->AppendGlobalExport("global_i32", false, uint32_t(666));
|
||||
host_module->AppendGlobalExport("global_i64", false, uint64_t(666));
|
||||
host_module->AppendGlobalExport("global_f32", false, float(666.6f));
|
||||
host_module->AppendGlobalExport("global_f64", false, double(666.6));
|
||||
}
|
||||
=>
|
||||
(module
|
||||
(type (func))
|
||||
(type (func (param i32)))
|
||||
(type (func (param f32)))
|
||||
(type (func (param f64)))
|
||||
(type (func (param i32) (param f32)))
|
||||
(type (func (param f64) (param f64)))
|
||||
(func (type 0))
|
||||
(func (type 1))
|
||||
(func (type 2))
|
||||
(func (type 3))
|
||||
(func (type 4))
|
||||
(func (type 5))
|
||||
(table 10 20 anyfunc)
|
||||
(memory 1 2)
|
||||
(global i32 (i32.const 666))
|
||||
(global i64 (i64.const 666))
|
||||
(global f32 (f32.const 666.6))
|
||||
(global f64 (f64.const 666.6))
|
||||
(export "print" (func 0))
|
||||
(export "print_i32" (func 1))
|
||||
(export "print_f32" (func 2))
|
||||
(export "print_f64" (func 3))
|
||||
(export "print_i32_f32" (func 4))
|
||||
(export "print_f64_f64" (func 5))
|
||||
(export "table" (table 0))
|
||||
(export "memory" (memory 0))
|
||||
(export "global_i32" (global 0))
|
||||
(export "global_i64" (global 1))
|
||||
(export "global_f32" (global 2))
|
||||
(export "global_f64" (global 3))
|
||||
)
|
||||
the file spectest.wasm in the crate root contains a copy of it as a binary module
|
||||
*/
|
Binary file not shown.
@ -1,31 +0,0 @@
|
||||
(module
|
||||
(type (;0;) (func))
|
||||
(type (;1;) (func (param i32)))
|
||||
(type (;2;) (func (param f32)))
|
||||
(type (;3;) (func (param f64)))
|
||||
(type (;4;) (func (param i32 f32)))
|
||||
(type (;5;) (func (param f64 f64)))
|
||||
(func (;0;) (type 0))
|
||||
(func (;1;) (type 1) (param i32))
|
||||
(func (;2;) (type 2) (param f32))
|
||||
(func (;3;) (type 3) (param f64))
|
||||
(func (;4;) (type 4) (param i32 f32))
|
||||
(func (;5;) (type 5) (param f64 f64))
|
||||
(table (;0;) 10 20 anyfunc)
|
||||
(memory (;0;) 1 2)
|
||||
(global (;0;) i32 (i32.const 666))
|
||||
(global (;1;) i64 (i64.const 666))
|
||||
(global (;2;) f32 (f32.const 0x1.4d4cccp+9 (;=666.6;)))
|
||||
(global (;3;) f64 (f64.const 0x1.4d4cccccccccdp+9 (;=666.6;)))
|
||||
(export "print" (func 0))
|
||||
(export "print_i32" (func 1))
|
||||
(export "print_f32" (func 2))
|
||||
(export "print_f64" (func 3))
|
||||
(export "print_i32_f32" (func 4))
|
||||
(export "print_f64_f64" (func 5))
|
||||
(export "table" (table 0))
|
||||
(export "memory" (memory 0))
|
||||
(export "global_i32" (global 0))
|
||||
(export "global_i64" (global 1))
|
||||
(export "global_f32" (global 2))
|
||||
(export "global_f64" (global 3)))
|
@ -1,286 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
|
||||
use cranelift_codegen::ir::types;
|
||||
use cranelift_entity::EntityRef;
|
||||
use libffi::high::call::*;
|
||||
use libffi::high::types::{CType, Type};
|
||||
use libffi::middle;
|
||||
use std::clone::Clone;
|
||||
use std::iter::Iterator;
|
||||
use std::marker::{Copy, PhantomData};
|
||||
use wabt::script::{Action, Value};
|
||||
// use crate::webassembly::instance::InvokeResult;
|
||||
|
||||
use super::{run_single_file, InvokationResult, ScriptHandler};
|
||||
use crate::webassembly::{
|
||||
compile, instantiate, Error, ErrorKind, Export, ImportObject, Instance, Module, ResultObject,
|
||||
VmCtx,
|
||||
};
|
||||
|
||||
// impl Clone for VmCtx {
|
||||
// fn clone(&self) -> Self {
|
||||
// unimplemented!()
|
||||
// }
|
||||
// }
|
||||
// impl Copy for VmCtx {
|
||||
// }
|
||||
|
||||
// unsafe impl<> CType for VmCtx {
|
||||
// fn reify() -> Type<Self> {
|
||||
// // Type::make(middle::Type::i64())
|
||||
// Type {
|
||||
// untyped: middle::Type::i64(),
|
||||
// _marker: PhantomData,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
struct StoreCtrl<'module> {
|
||||
last_module: Option<ResultObject>,
|
||||
modules: HashMap<String, Rc<&'module ResultObject>>,
|
||||
}
|
||||
|
||||
impl<'module> StoreCtrl<'module> {
|
||||
fn new() -> Self {
|
||||
// let (tx, rx) = channel();
|
||||
|
||||
// let _handle = thread::spawn(|| {
|
||||
// let _: FrameWitness = store_thread_frame(
|
||||
// StSt { store: Store::new(), stack: Stack::new(), recv: rx});
|
||||
// });
|
||||
|
||||
StoreCtrl {
|
||||
// tx,
|
||||
// _handle,
|
||||
modules: HashMap::new(),
|
||||
last_module: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_module(&mut self, name: Option<String>, module: &'module ResultObject) {
|
||||
// self.last_module = Some(Rc::new(module));
|
||||
// if let Some(name) = name {
|
||||
// // self.modules[&name] = module;
|
||||
// self.modules.insert(name, Rc::new(self.last_module.unwrap()));
|
||||
// }
|
||||
// println!("ADD MODULE {:?}", name);
|
||||
// self.modules
|
||||
// .insert(name.unwrap_or("__last_module".to_string()), module);
|
||||
// }
|
||||
// self.modules.insert("__last_module".to_string(), module);
|
||||
// self.last_module = Some(module);
|
||||
}
|
||||
|
||||
fn get_module(self, name: Option<String>) -> &'module ResultObject {
|
||||
unimplemented!()
|
||||
// self.last_module.expect("exists")
|
||||
// return self
|
||||
// .modules
|
||||
// .get(&name)
|
||||
// .or(self.modules.get("__last_module"));
|
||||
// return None;
|
||||
// return self.modules[&name];
|
||||
// name.map(|name| self.modules[&name]).or(self.last_module).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'module> ScriptHandler for StoreCtrl<'module> {
|
||||
fn reset(&mut self) {}
|
||||
fn action_invoke(
|
||||
&mut self,
|
||||
module: Option<String>,
|
||||
field: String,
|
||||
args: Vec<Value>,
|
||||
) -> InvokationResult {
|
||||
if let Some(result) = &mut self.last_module {
|
||||
let instance = &mut result.instance;
|
||||
let module = &result.module;
|
||||
let func_index = match module.info.exports.get(&field) {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
// We map the arguments provided into the raw Arguments provided
|
||||
// to libffi
|
||||
let mut call_args: Vec<Arg> = args
|
||||
.iter()
|
||||
.map(|a| match a {
|
||||
Value::I32(v) => arg(v),
|
||||
Value::I64(v) => arg(v),
|
||||
Value::F32(v) => arg(v),
|
||||
Value::F64(v) => arg(v),
|
||||
})
|
||||
.collect();
|
||||
// let vmctx = &instance.generate_context();
|
||||
// let vmctx_ref = vmctx as *const _;
|
||||
// let u8_ref = &(vmctx_ref as *const isize);
|
||||
// call_args.push(arg(u8_ref));
|
||||
// We use libffi to call a function with a vector of arguments
|
||||
let call_func: fn() = instance.get_function(func_index);
|
||||
let result: i64 = unsafe { call(CodePtr(call_func as *mut _), &call_args) };
|
||||
|
||||
// We retrieve the return type of the function, and wrap the result with it
|
||||
let signature_index = module.info.functions[func_index].entity;
|
||||
let signature = &module.info.signatures[signature_index];
|
||||
let return_values = if signature.returns.len() > 0 {
|
||||
let val = match signature.returns[0].value_type {
|
||||
types::I32 => Value::I32(result as _),
|
||||
types::I64 => Value::I64(result as _),
|
||||
types::F32 => Value::F32(result as f32),
|
||||
types::F64 => Value::F64(result as f64),
|
||||
_ => panic!("Unexpected type"),
|
||||
};
|
||||
vec![val]
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
println!(
|
||||
"Function {:?}(index: {:?}) ({:?}) => returned {:?}",
|
||||
field.to_string(),
|
||||
func_index,
|
||||
call_args,
|
||||
return_values
|
||||
);
|
||||
|
||||
return InvokationResult::Vals(return_values);
|
||||
}
|
||||
panic!("module not found");
|
||||
}
|
||||
fn action_get(&mut self, module: Option<String>, field: String) -> Value {
|
||||
// println!("action get");
|
||||
unimplemented!()
|
||||
}
|
||||
fn module(&mut self, bytes: Vec<u8>, name: Option<String>) {
|
||||
let mut import_object = ImportObject::new();
|
||||
extern "C" fn identity(x: i32) -> i32 {
|
||||
x
|
||||
};
|
||||
import_object.set("test", "identity", identity as *const u8);
|
||||
// let import_object = import_object!{
|
||||
// test.identity => fn(x: i32) {x},
|
||||
// }
|
||||
let module_wrapped = instantiate(bytes, import_object);
|
||||
let mut result = module_wrapped.expect("Module is invalid");
|
||||
// let module: &'module Module = result.module;
|
||||
self.last_module = Some(result);
|
||||
// self.add_module(name, &mut result);
|
||||
// println!("ADD MODULE {}", name.unwrap_or("no name".to_string()))
|
||||
}
|
||||
fn assert_malformed(&mut self, bytes: Vec<u8>) {
|
||||
let module_wrapped = instantiate(bytes, ImportObject::new());
|
||||
match module_wrapped {
|
||||
Err(ErrorKind::CompileError(v)) => {}
|
||||
_ => panic!("Module compilation should have failed"),
|
||||
}
|
||||
}
|
||||
fn assert_invalid(&mut self, bytes: Vec<u8>) {
|
||||
// print!("IS INVALID");
|
||||
let module_wrapped = instantiate(bytes, ImportObject::new());
|
||||
// print!("IS INVALID?? {:?}", module_wrapped);
|
||||
match module_wrapped {
|
||||
Err(ErrorKind::CompileError(v)) => {}
|
||||
_ => assert!(false, "Module compilation should have failed"),
|
||||
}
|
||||
}
|
||||
fn assert_uninstantiable(&mut self, bytes: Vec<u8>) {
|
||||
// unimplemented!()
|
||||
}
|
||||
fn assert_exhaustion(&mut self, action: Action) {
|
||||
// unimplemented!()
|
||||
}
|
||||
fn register(&mut self, name: Option<String>, as_name: String) {
|
||||
// println!("ADD MODULE {:?} {:?}", name.unwrap(), as_name);
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
mod tests {
|
||||
use super::run_single_file;
|
||||
use crate::test::Bencher;
|
||||
use std::mem;
|
||||
use std::path::Path;
|
||||
#[macro_use]
|
||||
use crate::webassembly::{
|
||||
compile, instantiate, Error, ErrorKind, Export, Instance, Module, ResultObject,
|
||||
ImportObject, VmCtx,
|
||||
};
|
||||
use wabt::wat2wasm;
|
||||
|
||||
fn do_test(test_name: String) {
|
||||
let mut handler = &mut super::StoreCtrl::new();
|
||||
let test_path_str = format!(
|
||||
"{}/src/spec/tests/{}.wast",
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
test_name
|
||||
);
|
||||
let test_path = Path::new(&test_path_str);
|
||||
let res = run_single_file(&test_path, handler);
|
||||
res.present()
|
||||
}
|
||||
|
||||
macro_rules! wasm_tests {
|
||||
($($name:ident,)*) => {
|
||||
$(
|
||||
#[test]
|
||||
fn $name() {
|
||||
// let test_filename = $value;
|
||||
// assert_eq!(expected, fib(input));
|
||||
do_test(stringify!($name).to_string());
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! instantiate_from_wast {
|
||||
($x:expr) => {{
|
||||
let wasm_bytes = include_wast2wasm_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), $x));
|
||||
let result_object =
|
||||
instantiate(wasm_bytes, ImportObject::new()).expect("Not compiled properly");
|
||||
result_object
|
||||
}};
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_identity(b: &mut Bencher) {
|
||||
let result_object = instantiate_from_wast!("/src/spec/tests/benchmark.wast");
|
||||
let instance = result_object.instance;
|
||||
let module = result_object.module;
|
||||
let func_index = match module.info.exports.get("identity") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let func: fn(i32) -> i32 = get_instance_function!(instance, func_index);
|
||||
assert_eq!(func(1), 1, "Identity function not working.");
|
||||
b.iter(|| {
|
||||
func(1);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_memory() {
|
||||
let result_object = instantiate_from_wast!("/src/spec/tests/memory2.wast");
|
||||
let mut instance = result_object.instance;
|
||||
let module = result_object.module;
|
||||
let func_index = match module.info.exports.get("memsize") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let func: fn(&VmCtx) -> i32 = get_instance_function!(instance, func_index);
|
||||
let ctx = instance.generate_context();
|
||||
assert_eq!(func(ctx), 1, "Identity function not working.");
|
||||
// b.iter(|| {
|
||||
// func(1);
|
||||
// });
|
||||
}
|
||||
|
||||
wasm_tests!{
|
||||
_type,
|
||||
br_if,
|
||||
call,
|
||||
import,
|
||||
// memory,
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
(module
|
||||
(table 0 anyfunc)
|
||||
(memory 0)
|
||||
(func (export "identity") (param i32) (result i32)
|
||||
(get_local 0)
|
||||
)
|
||||
)
|
@ -1,8 +0,0 @@
|
||||
(module
|
||||
(func $identity (import "test" "identity") (param i32) (result i32))
|
||||
(func (export "exported_func") (param i32) (result i32)
|
||||
(call $identity (get_local 0))
|
||||
)
|
||||
)
|
||||
|
||||
(assert_return (invoke "exported_func" (i32.const 42)) (i32.const 42))
|
@ -1,75 +0,0 @@
|
||||
|
||||
(module (memory 0 0))
|
||||
(module (memory 0 1))
|
||||
(module (memory 1 256))
|
||||
(module (memory 0 65536))
|
||||
|
||||
(assert_invalid (module (memory 0) (memory 0)) "multiple memories")
|
||||
(assert_invalid (module (memory (import "spectest" "memory") 0) (memory 0)) "multiple memories")
|
||||
|
||||
(module (memory (data)) (func (export "memsize") (result i32) (memory.size)))
|
||||
(assert_return (invoke "memsize") (i32.const 0))
|
||||
;; (module (memory (data "")) (func (export "memsize") (result i32) (memory.size)))
|
||||
;; (assert_return (invoke "memsize") (i32.const 0))
|
||||
;; (module (memory (data "x")) (func (export "memsize") (result i32) (memory.size)))
|
||||
;; (assert_return (invoke "memsize") (i32.const 1))
|
||||
|
||||
;; (assert_invalid (module (data (i32.const 0))) "unknown memory")
|
||||
;; (assert_invalid (module (data (i32.const 0) "")) "unknown memory")
|
||||
;; (assert_invalid (module (data (i32.const 0) "x")) "unknown memory")
|
||||
|
||||
;; (assert_invalid
|
||||
;; (module (func (drop (f32.load (i32.const 0)))))
|
||||
;; "unknown memory"
|
||||
;; )
|
||||
;; (assert_invalid
|
||||
;; (module (func (f32.store (f32.const 0) (i32.const 0))))
|
||||
;; "unknown memory"
|
||||
;; )
|
||||
;; (assert_invalid
|
||||
;; (module (func (drop (i32.load8_s (i32.const 0)))))
|
||||
;; "unknown memory"
|
||||
;; )
|
||||
;; (assert_invalid
|
||||
;; (module (func (i32.store8 (i32.const 0) (i32.const 0))))
|
||||
;; "unknown memory"
|
||||
;; )
|
||||
;; (assert_invalid
|
||||
;; (module (func (drop (memory.size))))
|
||||
;; "unknown memory"
|
||||
;; )
|
||||
;; (assert_invalid
|
||||
;; (module (func (drop (memory.grow (i32.const 0)))))
|
||||
;; "unknown memory"
|
||||
;; )
|
||||
|
||||
|
||||
;; (assert_invalid
|
||||
;; (module (memory 1 0))
|
||||
;; "size minimum must not be greater than maximum"
|
||||
;; )
|
||||
;; (assert_invalid
|
||||
;; (module (memory 65537))
|
||||
;; "memory size must be at most 65536 pages (4GiB)"
|
||||
;; )
|
||||
;; (assert_invalid
|
||||
;; (module (memory 2147483648))
|
||||
;; "memory size must be at most 65536 pages (4GiB)"
|
||||
;; )
|
||||
;; (assert_invalid
|
||||
;; (module (memory 4294967295))
|
||||
;; "memory size must be at most 65536 pages (4GiB)"
|
||||
;; )
|
||||
;; (assert_invalid
|
||||
;; (module (memory 0 65537))
|
||||
;; "memory size must be at most 65536 pages (4GiB)"
|
||||
;; )
|
||||
;; (assert_invalid
|
||||
;; (module (memory 0 2147483648))
|
||||
;; "memory size must be at most 65536 pages (4GiB)"
|
||||
;; )
|
||||
;; (assert_invalid
|
||||
;; (module (memory 0 4294967295))
|
||||
;; "memory size must be at most 65536 pages (4GiB)"
|
||||
;; )
|
||||
|
@ -1,6 +0,0 @@
|
||||
(module
|
||||
(memory (data "a"))
|
||||
(func (export "memsize") (result i32)
|
||||
(memory.size)
|
||||
)
|
||||
)
|
1788
src/spectests/br_if.rs
Normal file
1788
src/spectests/br_if.rs
Normal file
File diff suppressed because it is too large
Load Diff
754
src/spectests/call.rs
Normal file
754
src/spectests/call.rs
Normal file
@ -0,0 +1,754 @@
|
||||
// Rust test file autogenerated from call.wast
|
||||
// Please do not modify
|
||||
|
||||
use crate::webassembly::{instantiate, compile, ImportObject, ResultObject, VmCtx, Export};
|
||||
use wabt::wat2wasm;
|
||||
|
||||
|
||||
// Line 3
|
||||
fn create_module_1() -> ResultObject {
|
||||
let module_str = "(module
|
||||
(type (;0;) (func (result i32)))
|
||||
(type (;1;) (func (result i64)))
|
||||
(type (;2;) (func (result f32)))
|
||||
(type (;3;) (func (result f64)))
|
||||
(type (;4;) (func (param i32) (result i32)))
|
||||
(type (;5;) (func (param i64) (result i64)))
|
||||
(type (;6;) (func (param f32) (result f32)))
|
||||
(type (;7;) (func (param f64) (result f64)))
|
||||
(type (;8;) (func (param f32 i32) (result i32)))
|
||||
(type (;9;) (func (param i32 i64) (result i64)))
|
||||
(type (;10;) (func (param f64 f32) (result f32)))
|
||||
(type (;11;) (func (param i64 f64) (result f64)))
|
||||
(type (;12;) (func (param i64 i64) (result i64)))
|
||||
(type (;13;) (func (param i64) (result i32)))
|
||||
(type (;14;) (func))
|
||||
(func (;0;) (type 0) (result i32)
|
||||
i32.const 306)
|
||||
(func (;1;) (type 1) (result i64)
|
||||
i64.const 356)
|
||||
(func (;2;) (type 2) (result f32)
|
||||
f32.const 0x1.e64p+11 (;=3890;))
|
||||
(func (;3;) (type 3) (result f64)
|
||||
f64.const 0x1.ec8p+11 (;=3940;))
|
||||
(func (;4;) (type 4) (param i32) (result i32)
|
||||
get_local 0)
|
||||
(func (;5;) (type 5) (param i64) (result i64)
|
||||
get_local 0)
|
||||
(func (;6;) (type 6) (param f32) (result f32)
|
||||
get_local 0)
|
||||
(func (;7;) (type 7) (param f64) (result f64)
|
||||
get_local 0)
|
||||
(func (;8;) (type 8) (param f32 i32) (result i32)
|
||||
get_local 1)
|
||||
(func (;9;) (type 9) (param i32 i64) (result i64)
|
||||
get_local 1)
|
||||
(func (;10;) (type 10) (param f64 f32) (result f32)
|
||||
get_local 1)
|
||||
(func (;11;) (type 11) (param i64 f64) (result f64)
|
||||
get_local 1)
|
||||
(func (;12;) (type 0) (result i32)
|
||||
call 0)
|
||||
(func (;13;) (type 1) (result i64)
|
||||
call 1)
|
||||
(func (;14;) (type 2) (result f32)
|
||||
call 2)
|
||||
(func (;15;) (type 3) (result f64)
|
||||
call 3)
|
||||
(func (;16;) (type 0) (result i32)
|
||||
i32.const 32
|
||||
call 4)
|
||||
(func (;17;) (type 1) (result i64)
|
||||
i64.const 64
|
||||
call 5)
|
||||
(func (;18;) (type 2) (result f32)
|
||||
f32.const 0x1.51eb86p+0 (;=1.32;)
|
||||
call 6)
|
||||
(func (;19;) (type 3) (result f64)
|
||||
f64.const 0x1.a3d70a3d70a3dp+0 (;=1.64;)
|
||||
call 7)
|
||||
(func (;20;) (type 0) (result i32)
|
||||
f32.const 0x1.00ccccp+5 (;=32.1;)
|
||||
i32.const 32
|
||||
call 8)
|
||||
(func (;21;) (type 1) (result i64)
|
||||
i32.const 32
|
||||
i64.const 64
|
||||
call 9)
|
||||
(func (;22;) (type 2) (result f32)
|
||||
f64.const 0x1p+6 (;=64;)
|
||||
f32.const 0x1p+5 (;=32;)
|
||||
call 10)
|
||||
(func (;23;) (type 3) (result f64)
|
||||
i64.const 64
|
||||
f64.const 0x1.0066666666666p+6 (;=64.1;)
|
||||
call 11)
|
||||
(func (;24;) (type 5) (param i64) (result i64)
|
||||
get_local 0
|
||||
i64.eqz
|
||||
if (result i64) ;; label = @1
|
||||
i64.const 1
|
||||
else
|
||||
get_local 0
|
||||
get_local 0
|
||||
i64.const 1
|
||||
i64.sub
|
||||
call 24
|
||||
i64.mul
|
||||
end)
|
||||
(func (;25;) (type 12) (param i64 i64) (result i64)
|
||||
get_local 0
|
||||
i64.eqz
|
||||
if (result i64) ;; label = @1
|
||||
get_local 1
|
||||
else
|
||||
get_local 0
|
||||
i64.const 1
|
||||
i64.sub
|
||||
get_local 0
|
||||
get_local 1
|
||||
i64.mul
|
||||
call 25
|
||||
end)
|
||||
(func (;26;) (type 5) (param i64) (result i64)
|
||||
get_local 0
|
||||
i64.const 1
|
||||
i64.le_u
|
||||
if (result i64) ;; label = @1
|
||||
i64.const 1
|
||||
else
|
||||
get_local 0
|
||||
i64.const 2
|
||||
i64.sub
|
||||
call 26
|
||||
get_local 0
|
||||
i64.const 1
|
||||
i64.sub
|
||||
call 26
|
||||
i64.add
|
||||
end)
|
||||
(func (;27;) (type 13) (param i64) (result i32)
|
||||
get_local 0
|
||||
i64.eqz
|
||||
if (result i32) ;; label = @1
|
||||
i32.const 44
|
||||
else
|
||||
get_local 0
|
||||
i64.const 1
|
||||
i64.sub
|
||||
call 28
|
||||
end)
|
||||
(func (;28;) (type 13) (param i64) (result i32)
|
||||
get_local 0
|
||||
i64.eqz
|
||||
if (result i32) ;; label = @1
|
||||
i32.const 99
|
||||
else
|
||||
get_local 0
|
||||
i64.const 1
|
||||
i64.sub
|
||||
call 27
|
||||
end)
|
||||
(func (;29;) (type 14)
|
||||
call 29)
|
||||
(func (;30;) (type 14)
|
||||
call 31)
|
||||
(func (;31;) (type 14)
|
||||
call 30)
|
||||
(export \"type-i32\" (func 12))
|
||||
(export \"type-i64\" (func 13))
|
||||
(export \"type-f32\" (func 14))
|
||||
(export \"type-f64\" (func 15))
|
||||
(export \"type-first-i32\" (func 16))
|
||||
(export \"type-first-i64\" (func 17))
|
||||
(export \"type-first-f32\" (func 18))
|
||||
(export \"type-first-f64\" (func 19))
|
||||
(export \"type-second-i32\" (func 20))
|
||||
(export \"type-second-i64\" (func 21))
|
||||
(export \"type-second-f32\" (func 22))
|
||||
(export \"type-second-f64\" (func 23))
|
||||
(export \"fac\" (func 24))
|
||||
(export \"fac-acc\" (func 25))
|
||||
(export \"fib\" (func 26))
|
||||
(export \"even\" (func 27))
|
||||
(export \"odd\" (func 28))
|
||||
(export \"runaway\" (func 29))
|
||||
(export \"mutual-runaway\" (func 30)))
|
||||
";
|
||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
||||
instantiate(wasm_binary, ImportObject::new()).expect("WASM can't be instantiated")
|
||||
}
|
||||
|
||||
// Line 111
|
||||
#[test]
|
||||
fn l111_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("type-i32") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(&VmCtx) -> i32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(&vm_context);
|
||||
assert_eq!(result, 306 as i32);
|
||||
}
|
||||
|
||||
// Line 112
|
||||
#[test]
|
||||
fn l112_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("type-i64") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(&VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(&vm_context);
|
||||
assert_eq!(result, 356 as i64);
|
||||
}
|
||||
|
||||
// Line 113
|
||||
#[test]
|
||||
fn l113_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("type-f32") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(&VmCtx) -> f32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(&vm_context);
|
||||
assert_eq!(result, 3890.0 as f32);
|
||||
}
|
||||
|
||||
// Line 114
|
||||
#[test]
|
||||
fn l114_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("type-f64") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(&VmCtx) -> f64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(&vm_context);
|
||||
assert_eq!(result, 3940.0 as f64);
|
||||
}
|
||||
|
||||
// Line 116
|
||||
#[test]
|
||||
fn l116_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("type-first-i32") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(&VmCtx) -> i32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(&vm_context);
|
||||
assert_eq!(result, 32 as i32);
|
||||
}
|
||||
|
||||
// Line 117
|
||||
#[test]
|
||||
fn l117_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("type-first-i64") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(&VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(&vm_context);
|
||||
assert_eq!(result, 64 as i64);
|
||||
}
|
||||
|
||||
// Line 118
|
||||
#[test]
|
||||
fn l118_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("type-first-f32") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(&VmCtx) -> f32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(&vm_context);
|
||||
assert_eq!(result, 1.32 as f32);
|
||||
}
|
||||
|
||||
// Line 119
|
||||
#[test]
|
||||
fn l119_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("type-first-f64") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(&VmCtx) -> f64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(&vm_context);
|
||||
assert_eq!(result, 1.64 as f64);
|
||||
}
|
||||
|
||||
// Line 121
|
||||
#[test]
|
||||
fn l121_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("type-second-i32") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(&VmCtx) -> i32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(&vm_context);
|
||||
assert_eq!(result, 32 as i32);
|
||||
}
|
||||
|
||||
// Line 122
|
||||
#[test]
|
||||
fn l122_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("type-second-i64") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(&VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(&vm_context);
|
||||
assert_eq!(result, 64 as i64);
|
||||
}
|
||||
|
||||
// Line 123
|
||||
#[test]
|
||||
fn l123_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("type-second-f32") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(&VmCtx) -> f32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(&vm_context);
|
||||
assert_eq!(result, 32.0 as f32);
|
||||
}
|
||||
|
||||
// Line 124
|
||||
#[test]
|
||||
fn l124_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("type-second-f64") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(&VmCtx) -> f64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(&vm_context);
|
||||
assert_eq!(result, 64.1 as f64);
|
||||
}
|
||||
|
||||
// Line 126
|
||||
#[test]
|
||||
fn l126_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("fac") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(0 as i64, &vm_context);
|
||||
assert_eq!(result, 1 as i64);
|
||||
}
|
||||
|
||||
// Line 127
|
||||
#[test]
|
||||
fn l127_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("fac") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(1 as i64, &vm_context);
|
||||
assert_eq!(result, 1 as i64);
|
||||
}
|
||||
|
||||
// Line 128
|
||||
#[test]
|
||||
fn l128_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("fac") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(5 as i64, &vm_context);
|
||||
assert_eq!(result, 120 as i64);
|
||||
}
|
||||
|
||||
// Line 129
|
||||
#[test]
|
||||
fn l129_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("fac") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(25 as i64, &vm_context);
|
||||
assert_eq!(result, 7034535277573963776 as i64);
|
||||
}
|
||||
|
||||
// Line 130
|
||||
#[test]
|
||||
fn l130_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("fac-acc") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, i64, &VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(0 as i64, 1 as i64, &vm_context);
|
||||
assert_eq!(result, 1 as i64);
|
||||
}
|
||||
|
||||
// Line 131
|
||||
#[test]
|
||||
fn l131_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("fac-acc") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, i64, &VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(1 as i64, 1 as i64, &vm_context);
|
||||
assert_eq!(result, 1 as i64);
|
||||
}
|
||||
|
||||
// Line 132
|
||||
#[test]
|
||||
fn l132_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("fac-acc") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, i64, &VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(5 as i64, 1 as i64, &vm_context);
|
||||
assert_eq!(result, 120 as i64);
|
||||
}
|
||||
|
||||
// Line 134
|
||||
#[test]
|
||||
fn l134_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("fac-acc") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, i64, &VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(25 as i64, 1 as i64, &vm_context);
|
||||
assert_eq!(result, 7034535277573963776 as i64);
|
||||
}
|
||||
|
||||
// Line 138
|
||||
#[test]
|
||||
fn l138_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("fib") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(0 as i64, &vm_context);
|
||||
assert_eq!(result, 1 as i64);
|
||||
}
|
||||
|
||||
// Line 139
|
||||
#[test]
|
||||
fn l139_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("fib") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(1 as i64, &vm_context);
|
||||
assert_eq!(result, 1 as i64);
|
||||
}
|
||||
|
||||
// Line 140
|
||||
#[test]
|
||||
fn l140_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("fib") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(2 as i64, &vm_context);
|
||||
assert_eq!(result, 2 as i64);
|
||||
}
|
||||
|
||||
// Line 141
|
||||
#[test]
|
||||
fn l141_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("fib") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(5 as i64, &vm_context);
|
||||
assert_eq!(result, 8 as i64);
|
||||
}
|
||||
|
||||
// Line 142
|
||||
#[test]
|
||||
fn l142_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("fib") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i64 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(20 as i64, &vm_context);
|
||||
assert_eq!(result, 10946 as i64);
|
||||
}
|
||||
|
||||
// Line 144
|
||||
#[test]
|
||||
fn l144_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("even") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(0 as i64, &vm_context);
|
||||
assert_eq!(result, 44 as i32);
|
||||
}
|
||||
|
||||
// Line 145
|
||||
#[test]
|
||||
fn l145_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("even") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(1 as i64, &vm_context);
|
||||
assert_eq!(result, 99 as i32);
|
||||
}
|
||||
|
||||
// Line 146
|
||||
#[test]
|
||||
fn l146_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("even") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(100 as i64, &vm_context);
|
||||
assert_eq!(result, 44 as i32);
|
||||
}
|
||||
|
||||
// Line 147
|
||||
#[test]
|
||||
fn l147_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("even") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(77 as i64, &vm_context);
|
||||
assert_eq!(result, 99 as i32);
|
||||
}
|
||||
|
||||
// Line 148
|
||||
#[test]
|
||||
fn l148_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("odd") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(0 as i64, &vm_context);
|
||||
assert_eq!(result, 99 as i32);
|
||||
}
|
||||
|
||||
// Line 149
|
||||
#[test]
|
||||
fn l149_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("odd") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(1 as i64, &vm_context);
|
||||
assert_eq!(result, 44 as i32);
|
||||
}
|
||||
|
||||
// Line 150
|
||||
#[test]
|
||||
fn l150_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("odd") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(200 as i64, &vm_context);
|
||||
assert_eq!(result, 99 as i32);
|
||||
}
|
||||
|
||||
// Line 151
|
||||
#[test]
|
||||
fn l151_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_1();
|
||||
let func_index = match module.info.exports.get("odd") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(i64, &VmCtx) -> i32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(77 as i64, &vm_context);
|
||||
assert_eq!(result, 44 as i32);
|
||||
}
|
||||
|
||||
// Line 153
|
||||
|
||||
// Line 154
|
||||
|
||||
// Line 160
|
||||
|
||||
#[test]
|
||||
fn l160_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 3, 2, 0, 0, 10, 10, 2, 5, 0, 16, 1, 69, 11, 2, 0, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 167
|
||||
|
||||
#[test]
|
||||
fn l167_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 96, 0, 0, 96, 0, 1, 126, 3, 3, 2, 0, 1, 10, 12, 2, 5, 0, 16, 1, 69, 11, 4, 0, 66, 1, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 175
|
||||
|
||||
#[test]
|
||||
fn l175_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 96, 0, 0, 96, 1, 127, 0, 3, 3, 2, 0, 1, 10, 9, 2, 4, 0, 16, 1, 11, 2, 0, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 182
|
||||
|
||||
#[test]
|
||||
fn l182_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 9, 2, 96, 0, 0, 96, 2, 124, 127, 0, 3, 3, 2, 0, 1, 10, 9, 2, 4, 0, 16, 1, 11, 2, 0, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 189
|
||||
|
||||
#[test]
|
||||
fn l189_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 3, 2, 0, 0, 10, 11, 2, 6, 0, 65, 1, 16, 1, 11, 2, 0, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 196
|
||||
|
||||
#[test]
|
||||
fn l196_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 3, 2, 0, 0, 10, 20, 2, 15, 0, 68, 0, 0, 0, 0, 0, 0, 0, 64, 65, 1, 16, 1, 11, 2, 0, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 204
|
||||
|
||||
#[test]
|
||||
fn l204_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 9, 2, 96, 0, 0, 96, 2, 127, 127, 0, 3, 3, 2, 0, 1, 10, 12, 2, 7, 0, 1, 65, 1, 16, 1, 11, 2, 0, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 211
|
||||
|
||||
#[test]
|
||||
fn l211_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 9, 2, 96, 0, 0, 96, 2, 127, 127, 0, 3, 3, 2, 0, 1, 10, 12, 2, 7, 0, 65, 1, 1, 16, 1, 11, 2, 0, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 218
|
||||
|
||||
#[test]
|
||||
fn l218_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 9, 2, 96, 0, 0, 96, 2, 127, 124, 0, 3, 3, 2, 0, 1, 10, 20, 2, 15, 0, 68, 0, 0, 0, 0, 0, 0, 240, 63, 65, 1, 16, 1, 11, 2, 0, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 225
|
||||
|
||||
#[test]
|
||||
fn l225_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 9, 2, 96, 0, 0, 96, 2, 124, 127, 0, 3, 3, 2, 0, 1, 10, 20, 2, 15, 0, 65, 1, 68, 0, 0, 0, 0, 0, 0, 240, 63, 16, 1, 11, 2, 0, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 236
|
||||
|
||||
#[test]
|
||||
fn l236_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 6, 1, 4, 0, 16, 1, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 240
|
||||
|
||||
#[test]
|
||||
fn l240_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 10, 1, 8, 0, 16, 148, 152, 219, 226, 3, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
288
src/spectests/memory.rs
Normal file
288
src/spectests/memory.rs
Normal file
@ -0,0 +1,288 @@
|
||||
// Rust test file autogenerated from memory.wast
|
||||
// Please do not modify
|
||||
|
||||
use crate::webassembly::{instantiate, compile, ImportObject, ResultObject, VmCtx, Export};
|
||||
use wabt::wat2wasm;
|
||||
|
||||
|
||||
// Line 2
|
||||
fn create_module_1() -> ResultObject {
|
||||
let module_str = "(module
|
||||
(memory (;0;) 0 0))
|
||||
";
|
||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
||||
instantiate(wasm_binary, ImportObject::new()).expect("WASM can't be instantiated")
|
||||
}
|
||||
|
||||
// Line 3
|
||||
fn create_module_2() -> ResultObject {
|
||||
let module_str = "(module
|
||||
(memory (;0;) 0 1))
|
||||
";
|
||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
||||
instantiate(wasm_binary, ImportObject::new()).expect("WASM can't be instantiated")
|
||||
}
|
||||
|
||||
// Line 4
|
||||
fn create_module_3() -> ResultObject {
|
||||
let module_str = "(module
|
||||
(memory (;0;) 1 256))
|
||||
";
|
||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
||||
instantiate(wasm_binary, ImportObject::new()).expect("WASM can't be instantiated")
|
||||
}
|
||||
|
||||
// Line 5
|
||||
fn create_module_4() -> ResultObject {
|
||||
let module_str = "(module
|
||||
(memory (;0;) 0 65536))
|
||||
";
|
||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
||||
instantiate(wasm_binary, ImportObject::new()).expect("WASM can't be instantiated")
|
||||
}
|
||||
|
||||
// Line 7
|
||||
|
||||
#[test]
|
||||
fn l7_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 5, 5, 2, 0, 0, 0, 0];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 8
|
||||
|
||||
#[test]
|
||||
fn l8_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 2, 20, 1, 8, 115, 112, 101, 99, 116, 101, 115, 116, 6, 109, 101, 109, 111, 114, 121, 2, 0, 0, 5, 3, 1, 0, 0];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 10
|
||||
fn create_module_5() -> ResultObject {
|
||||
let module_str = "(module
|
||||
(type (;0;) (func (result i32)))
|
||||
(func (;0;) (type 0) (result i32)
|
||||
memory.size)
|
||||
(memory (;0;) 0 0)
|
||||
(export \"memsize\" (func 0))
|
||||
(data (i32.const 0) \"\"))
|
||||
";
|
||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
||||
instantiate(wasm_binary, ImportObject::new()).expect("WASM can't be instantiated")
|
||||
}
|
||||
|
||||
// Line 11
|
||||
#[test]
|
||||
fn l11_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_5();
|
||||
let func_index = match module.info.exports.get("memsize") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(&VmCtx) -> i32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(&vm_context);
|
||||
assert_eq!(result, 0 as i32);
|
||||
}
|
||||
|
||||
// Line 12
|
||||
fn create_module_6() -> ResultObject {
|
||||
let module_str = "(module
|
||||
(type (;0;) (func (result i32)))
|
||||
(func (;0;) (type 0) (result i32)
|
||||
memory.size)
|
||||
(memory (;0;) 0 0)
|
||||
(export \"memsize\" (func 0))
|
||||
(data (i32.const 0) \"\"))
|
||||
";
|
||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
||||
instantiate(wasm_binary, ImportObject::new()).expect("WASM can't be instantiated")
|
||||
}
|
||||
|
||||
// Line 13
|
||||
#[test]
|
||||
fn l13_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_6();
|
||||
let func_index = match module.info.exports.get("memsize") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(&VmCtx) -> i32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(&vm_context);
|
||||
assert_eq!(result, 0 as i32);
|
||||
}
|
||||
|
||||
// Line 14
|
||||
fn create_module_7() -> ResultObject {
|
||||
let module_str = "(module
|
||||
(type (;0;) (func (result i32)))
|
||||
(func (;0;) (type 0) (result i32)
|
||||
memory.size)
|
||||
(memory (;0;) 1 1)
|
||||
(export \"memsize\" (func 0))
|
||||
(data (i32.const 0) \"x\"))
|
||||
";
|
||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
||||
instantiate(wasm_binary, ImportObject::new()).expect("WASM can't be instantiated")
|
||||
}
|
||||
|
||||
// Line 15
|
||||
#[test]
|
||||
fn l15_assert_return_invoke() {
|
||||
let ResultObject { mut instance, module } = create_module_7();
|
||||
let func_index = match module.info.exports.get("memsize") {
|
||||
Some(&Export::Function(index)) => index,
|
||||
_ => panic!("Function not found"),
|
||||
};
|
||||
let invoke_fn: fn(&VmCtx) -> i32 = get_instance_function!(instance, func_index);
|
||||
let vm_context = instance.generate_context();
|
||||
let result = invoke_fn(&vm_context);
|
||||
assert_eq!(result, 1 as i32);
|
||||
}
|
||||
|
||||
// Line 17
|
||||
|
||||
#[test]
|
||||
fn l17_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 11, 6, 1, 0, 65, 0, 11, 0];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 18
|
||||
|
||||
#[test]
|
||||
fn l18_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 11, 6, 1, 0, 65, 0, 11, 0];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 19
|
||||
|
||||
#[test]
|
||||
fn l19_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 11, 7, 1, 0, 65, 0, 11, 1, 120];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 22
|
||||
|
||||
#[test]
|
||||
fn l22_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 10, 1, 8, 0, 65, 0, 42, 2, 0, 26, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 26
|
||||
|
||||
#[test]
|
||||
fn l26_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 14, 1, 12, 0, 67, 0, 0, 0, 0, 65, 0, 56, 2, 0, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 30
|
||||
|
||||
#[test]
|
||||
fn l30_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 10, 1, 8, 0, 65, 0, 44, 0, 0, 26, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 34
|
||||
|
||||
#[test]
|
||||
fn l34_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 11, 1, 9, 0, 65, 0, 65, 0, 58, 0, 0, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 38
|
||||
|
||||
#[test]
|
||||
fn l38_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 7, 1, 5, 0, 63, 0, 26, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 42
|
||||
|
||||
#[test]
|
||||
fn l42_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 9, 1, 7, 0, 65, 0, 64, 0, 26, 11];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 48
|
||||
|
||||
#[test]
|
||||
fn l48_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 5, 4, 1, 1, 1, 0];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 52
|
||||
|
||||
#[test]
|
||||
fn l52_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 5, 5, 1, 0, 129, 128, 4];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 56
|
||||
|
||||
#[test]
|
||||
fn l56_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 5, 7, 1, 0, 128, 128, 128, 128, 8];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 60
|
||||
|
||||
#[test]
|
||||
fn l60_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 5, 7, 1, 0, 255, 255, 255, 255, 15];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 64
|
||||
|
||||
#[test]
|
||||
fn l64_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 5, 6, 1, 1, 0, 129, 128, 4];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 68
|
||||
|
||||
#[test]
|
||||
fn l68_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 5, 8, 1, 1, 0, 128, 128, 128, 128, 8];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 72
|
||||
|
||||
#[test]
|
||||
fn l72_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 5, 8, 1, 1, 0, 255, 255, 255, 255, 15];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
4
src/spectests/mod.rs
Normal file
4
src/spectests/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
mod br_if;
|
||||
mod call;
|
||||
mod memory;
|
||||
mod types;
|
64
src/spectests/types.rs
Normal file
64
src/spectests/types.rs
Normal file
@ -0,0 +1,64 @@
|
||||
// Rust test file autogenerated from types.wast
|
||||
// Please do not modify
|
||||
|
||||
use crate::webassembly::{instantiate, compile, ImportObject, ResultObject, VmCtx, Export};
|
||||
use wabt::wat2wasm;
|
||||
|
||||
|
||||
// Line 3
|
||||
fn create_module_1() -> ResultObject {
|
||||
let module_str = "(module
|
||||
(type (;0;) (func))
|
||||
(type (;1;) (func))
|
||||
(type (;2;) (func (param i32)))
|
||||
(type (;3;) (func (param i32)))
|
||||
(type (;4;) (func (result i32)))
|
||||
(type (;5;) (func (param i32) (result i32)))
|
||||
(type (;6;) (func (param i32) (result i32)))
|
||||
(type (;7;) (func (param f32 f64)))
|
||||
(type (;8;) (func (param f32 f64)))
|
||||
(type (;9;) (func (param f32 f64)))
|
||||
(type (;10;) (func (param f32 f64)))
|
||||
(type (;11;) (func (param f32 f64)))
|
||||
(type (;12;) (func (param f32 f64 i32 f64 i32 i32)))
|
||||
(type (;13;) (func (param f32 f64 i32))))
|
||||
";
|
||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
||||
instantiate(wasm_binary, ImportObject::new()).expect("WASM can't be instantiated")
|
||||
}
|
||||
|
||||
// Line 44
|
||||
|
||||
#[test]
|
||||
fn l44_assert_malformed() {
|
||||
let wasm_binary = [40, 116, 121, 112, 101, 32, 40, 102, 117, 110, 99, 32, 40, 114, 101, 115, 117, 108, 116, 32, 105, 51, 50, 41, 32, 40, 112, 97, 114, 97, 109, 32, 105, 51, 50, 41, 41, 41];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is malformed");
|
||||
}
|
||||
|
||||
// Line 48
|
||||
|
||||
#[test]
|
||||
fn l48_assert_malformed() {
|
||||
let wasm_binary = [40, 116, 121, 112, 101, 32, 40, 102, 117, 110, 99, 32, 40, 114, 101, 115, 117, 108, 116, 32, 36, 120, 32, 105, 51, 50, 41, 41, 41];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is malformed");
|
||||
}
|
||||
|
||||
// Line 53
|
||||
|
||||
#[test]
|
||||
fn l53_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 6, 1, 96, 0, 2, 127, 127];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
||||
|
||||
// Line 57
|
||||
|
||||
#[test]
|
||||
fn l57_assert_invalid() {
|
||||
let wasm_binary = [0, 97, 115, 109, 1, 0, 0, 0, 1, 6, 1, 96, 0, 2, 127, 127];
|
||||
let compilation = compile(wasm_binary.to_vec());
|
||||
assert!(compilation.is_err(), "WASM should not compile as is invalid");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user