From 727e36de00b4e87bfa24586ea6bb7136b2dbce7f Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 10 Feb 2023 15:14:10 +0100 Subject: [PATCH] Add a basic Wasm VM test (#159) --- Cargo.lock | 43 +++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/executor/vm.rs | 2 +- src/executor/vm/tests.rs | 51 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 5a4747d861..e238a416a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1407,6 +1407,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + [[package]] name = "libc" version = "0.2.139" @@ -2391,6 +2397,7 @@ dependencies = [ "twox-hash", "wasmi", "wasmtime", + "wat", ] [[package]] @@ -2797,6 +2804,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + [[package]] name = "unicode-xid" version = "0.2.2" @@ -2924,6 +2937,15 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +[[package]] +name = "wasm-encoder" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c3e4bc09095436c8e7584d86d33e6c3ee67045af8fb262cbb9cc321de553428" +dependencies = [ + "leb128", +] + [[package]] name = "wasmi" version = "0.9.1" @@ -3128,6 +3150,27 @@ dependencies = [ "wasmparser", ] +[[package]] +name = "wast" +version = "53.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8244fa24196b1d8fd3ca4a96a3a164c40f846498c5deab6caf414c67340ca4af" +dependencies = [ + "leb128", + "memchr", + "unicode-width", + "wasm-encoder", +] + +[[package]] +name = "wat" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4620f1059add6dad511decb9d5d88b4a0a0d3e2e315ed34f79b0dc0dce18aa4b" +dependencies = [ + "wast", +] + [[package]] name = "web-sys" version = "0.3.55" diff --git a/Cargo.toml b/Cargo.toml index c580494ab6..753cdd4cbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -107,6 +107,7 @@ wasmtime = { version = "3.0.0", default-features = false, features = ["async", " async-std = "1.12.0" criterion = "0.4.0" tempfile = "3.3.0" +wat = "1.0.58" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/src/executor/vm.rs b/src/executor/vm.rs index 083b9683e7..7ee1022593 100644 --- a/src/executor/vm.rs +++ b/src/executor/vm.rs @@ -494,7 +494,7 @@ impl TryFrom for Signature { } /// Value that a Wasm function can accept or produce. -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum WasmValue { /// A 32-bits integer. There is no fundamental difference between signed and unsigned /// integer, and the signed-ness should be determined depending on the context. diff --git a/src/executor/vm/tests.rs b/src/executor/vm/tests.rs index c6bd011ae0..a48f80d02e 100644 --- a/src/executor/vm/tests.rs +++ b/src/executor/vm/tests.rs @@ -17,6 +17,8 @@ #![cfg(test)] +use core::iter; + #[test] fn is_send() { // Makes sure that the virtual machine types implement `Send`. @@ -117,3 +119,52 @@ fn unsupported_type() { assert!(super::VirtualMachinePrototype::new(&module2, |_, _, _| Ok(0)).is_err()); } } + +#[test] +fn basic_host_function_return_value_works() { + let module_bytes = wat::parse_str( + r#" + (module + (import "host" "hello" (func $host_hello (param i32) (result i32))) + (import "env" "memory" (memory $mem 0 4096)) + (func (export "hello") (result i32) + (call $host_hello (i32.const 3)) + ) + ) + "#, + ) + .unwrap(); + + for exec_hint in iter::once(super::ExecHint::ForceWasmi) + .chain(super::ExecHint::force_wasmtime_if_available().into_iter()) + { + let module = super::Module::new(&module_bytes, exec_hint).unwrap(); + + let prototype = super::VirtualMachinePrototype::new(&module, |_, _, _| Ok(0)).unwrap(); + + let mut vm = prototype + .start(super::HeapPages::new(1024), "hello", &[]) + .unwrap(); + + let mut resume_value = None; + loop { + match vm.run(resume_value) { + Ok(super::ExecOutcome::Finished { + return_value: Ok(value), + }) => { + assert_eq!(value, Some(super::WasmValue::I32(3))); + break; + } + Ok(super::ExecOutcome::Finished { + return_value: Err(_), + }) => panic!(), + Ok(super::ExecOutcome::Interrupted { id: 0, params }) => { + assert_eq!(params, vec![super::WasmValue::I32(3)]); + resume_value = Some(super::WasmValue::I32(3)); + } + Ok(super::ExecOutcome::Interrupted { .. }) => panic!(), + Err(_) => panic!(), + } + } + } +}