wasm-utils/tests/diff.rs
Sergey Pepyakin 9527b969a4 Impl stack height limiter (#64)
* Initial implementation

* Add wasm-stack-height binary

* Fixes and tracing.

* Doc fixes.

* Fix type resolving for thunks.

* Fix thunk numbering.

* Don't generate thunks for fns with stack_cost = 0

* Diff tests.

* Add table tests.

* Add global test.

* Make tests deterministic.

* Refactoring.

* Clean and refactor.

* Rename Context → Stack in stach_height.

* Don't generate call wrappers if stack_cost = 0

* Errors instead of panics.

* Add with_stack_limit function.

* Fix thunk generation.

* Pass the stack height limit as separate value.

* Use .unwrap_or_default() in diff.rs.

* Remove redundant &.

* Remove simple_test.

* Remove variants of the Error.

* `resolve_func_type` returns an Error.

* Don't unwrap for .last()

* Remove stack_limit from rules::Set

* Rename max_height::compute.
2018-02-27 16:52:37 +03:00

94 lines
2.6 KiB
Rust

extern crate diff;
extern crate wasm_utils;
extern crate wabt;
extern crate parity_wasm;
use std::fs;
use std::io::{self, Read, Write};
use std::path::{Path, PathBuf};
use parity_wasm::elements;
fn slurp<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
let mut f = fs::File::open(path)?;
let mut buf = vec![];
f.read_to_end(&mut buf)?;
Ok(buf)
}
fn dump<P: AsRef<Path>>(path: P, buf: &[u8]) -> io::Result<()> {
let mut f = fs::File::create(path)?;
f.write_all(buf)?;
Ok(())
}
fn validate_wasm(binary: &[u8]) -> Result<(), wabt::Error> {
wabt::Module::read_binary(
&binary,
&Default::default()
)?.validate()?;
Ok(())
}
fn run_diff_test<F: FnOnce(&[u8]) -> Vec<u8>>(test_dir: &str, name: &str, test: F) {
let mut fixture_path = PathBuf::from(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/fixtures/",
));
fixture_path.push(test_dir);
fixture_path.push(name);
let mut expected_path = PathBuf::from(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/expectations/"
));
expected_path.push(test_dir);
expected_path.push(name);
let fixture_wat = slurp(&fixture_path).expect("Failed to read fixture");
let fixture_wasm = wabt::wat2wasm(fixture_wat).expect("Failed to read fixture");
validate_wasm(&fixture_wasm).expect("Fixture is invalid");
let expected_wat = slurp(&expected_path).unwrap_or_default();
let expected_wat = String::from_utf8_lossy(&expected_wat);
let actual_wasm = test(fixture_wasm.as_ref());
validate_wasm(&actual_wasm).expect("Result module is invalid");
let actual_wat = wabt::wasm2wat(&actual_wasm).expect("Failed to convert result wasm to wat");
if actual_wat != expected_wat {
println!("difference!");
println!("--- {}", expected_path.display());
println!("+++ {} test {}", test_dir, name);
for diff in diff::lines(&expected_wat, &actual_wat) {
match diff {
diff::Result::Left(l) => println!("-{}", l),
diff::Result::Both(l, _) => println!(" {}", l),
diff::Result::Right(r) => println!("+{}", r),
}
}
dump(&expected_path, actual_wat.as_bytes()).expect("Failed to write to expected");
panic!();
}
}
macro_rules! def_stack_height_test {
( $name:ident ) => {
#[test]
fn $name() {
run_diff_test("stack-height", concat!(stringify!($name), ".wat"), |input| {
let module = elements::deserialize_buffer(input).expect("Failed to deserialize");
let instrumented = wasm_utils::stack_height::inject_limiter(module, 1024).expect("Failed to instrument with stack counter");
elements::serialize(instrumented).expect("Failed to serialize")
});
}
};
}
def_stack_height_test!(simple);
def_stack_height_test!(table);
def_stack_height_test!(global);
def_stack_height_test!(imports);