Added automatic test generator from wasm spec

This commit is contained in:
Syrus Akbary 2018-10-19 01:29:12 +02:00
parent 5c5fbd309d
commit a932fef217
20 changed files with 3249 additions and 1117 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +0,0 @@
(module
(table 0 anyfunc)
(memory 0)
(func (export "identity") (param i32) (result i32)
(get_local 0)
)
)

View File

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

View File

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

View File

@ -1,6 +0,0 @@
(module
(memory (data "a"))
(func (export "memsize") (result i32)
(memory.size)
)
)

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
View 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
View 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
View File

@ -0,0 +1,4 @@
mod br_if;
mod call;
mod memory;
mod types;

64
src/spectests/types.rs Normal file
View 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");
}