mirror of
https://github.com/mii443/wasmer.git
synced 2025-08-22 16:35:33 +00:00
Add WASI wast parsing logic
This commit is contained in:
11
Cargo.lock
generated
11
Cargo.lock
generated
@ -1993,16 +1993,6 @@ version = "0.9.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
|
||||
[[package]]
|
||||
name = "wasi-test-generator"
|
||||
version = "0.17.0"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.63"
|
||||
@ -2109,7 +2099,6 @@ dependencies = [
|
||||
"structopt",
|
||||
"test-generator",
|
||||
"test-utils",
|
||||
"wasi-test-generator",
|
||||
"wasm-common",
|
||||
"wasmer",
|
||||
"wasmer-cache",
|
||||
|
@ -56,7 +56,6 @@ members = [
|
||||
|
||||
[build-dependencies]
|
||||
test-generator = { path = "tests/lib/test-generator" }
|
||||
wasi-test-generator = { path = "tests/lib/wasi-test-generator" }
|
||||
anyhow = "1.0"
|
||||
glob = "0.3"
|
||||
rustc_version = "0.2"
|
||||
|
28
build.rs
28
build.rs
@ -12,38 +12,10 @@ use test_generator::{
|
||||
build_ignores_from_textfile, test_directory, test_directory_module, wast_processor,
|
||||
with_features, with_test_module, Testsuite,
|
||||
};
|
||||
use wasi_test_generator;
|
||||
|
||||
static WASITESTS_ENV_VAR: &str = "WASM_WASI_GENERATE_WASITESTS";
|
||||
static WASITESTS_SET_UP_TOOLCHAIN: &str = "WASM_WASI_SET_UP_TOOLCHAIN";
|
||||
static WASITESTS_GENERATE_ALL: &str = "WASI_TEST_GENERATE_ALL";
|
||||
|
||||
fn is_truthy_env(name: &str) -> bool {
|
||||
env::var(name).map(|n| n == "1").unwrap_or_default()
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-changed=tests/ignores.txt");
|
||||
println!("cargo:rerun-if-env-changed={}", WASITESTS_ENV_VAR);
|
||||
println!("cargo:rerun-if-env-changed={}", WASITESTS_SET_UP_TOOLCHAIN);
|
||||
println!("cargo:rerun-if-env-changed={}", WASITESTS_GENERATE_ALL);
|
||||
|
||||
let wasi_versions = if is_truthy_env(WASITESTS_GENERATE_ALL) {
|
||||
wasi_test_generator::ALL_WASI_VERSIONS
|
||||
} else {
|
||||
wasi_test_generator::LATEST_WASI_VERSION
|
||||
};
|
||||
|
||||
// Install the Rust WASI toolchains for each of the versions
|
||||
if is_truthy_env(WASITESTS_SET_UP_TOOLCHAIN) {
|
||||
wasi_test_generator::install_toolchains(wasi_versions);
|
||||
}
|
||||
|
||||
// Generate the WASI Wasm files
|
||||
if is_truthy_env(WASITESTS_ENV_VAR) {
|
||||
wasi_test_generator::build(wasi_versions);
|
||||
}
|
||||
|
||||
let out_dir = PathBuf::from(
|
||||
env::var_os("OUT_DIR").expect("The OUT_DIR environment variable must be set"),
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
mod error;
|
||||
mod spectest;
|
||||
mod wasi_wast;
|
||||
mod wast;
|
||||
|
||||
pub use crate::error::{DirectiveError, DirectiveErrors};
|
||||
|
243
tests/lib/wast/src/wasi_wast.rs
Normal file
243
tests/lib/wast/src/wasi_wast.rs
Normal file
@ -0,0 +1,243 @@
|
||||
use wast::parser::{self, Parse, Parser};
|
||||
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
pub(crate) struct WasiTest<'a> {
|
||||
wasm_path: &'a str,
|
||||
args: Vec<&'a str>,
|
||||
envs: Vec<(&'a str, &'a str)>,
|
||||
dirs: Vec<&'a str>,
|
||||
mapped_dirs: Vec<&'a str>,
|
||||
assert_return: Option<AssertReturn>,
|
||||
assert_stdout: Option<AssertStdout<'a>>,
|
||||
assert_stderr: Option<AssertStderr<'a>>,
|
||||
}
|
||||
|
||||
mod wasi_kw {
|
||||
wast::custom_keyword!(wasi_test);
|
||||
wast::custom_keyword!(envs);
|
||||
wast::custom_keyword!(args);
|
||||
wast::custom_keyword!(preopens);
|
||||
wast::custom_keyword!(map_dirs);
|
||||
wast::custom_keyword!(assert_return);
|
||||
wast::custom_keyword!(assert_stdout);
|
||||
wast::custom_keyword!(assert_stderr);
|
||||
wast::custom_keyword!(fake_i64_const = "i64.const");
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for WasiTest<'a> {
|
||||
fn parse(parser: Parser<'a>) -> parser::Result<Self> {
|
||||
parser.parens(|parser| {
|
||||
parser.parse::<wasi_kw::wasi_test>()?;
|
||||
// TODO: improve error message here
|
||||
let wasm_path = parser.parse::<&'a str>()?;
|
||||
|
||||
// TODO: allow these to come in any order
|
||||
let envs = if parser.peek2::<wasi_kw::envs>() {
|
||||
parser.parens(|p| p.parse::<Envs>())?.envs
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let args = if parser.peek2::<wasi_kw::args>() {
|
||||
parser.parens(|p| p.parse::<Args>())?.args
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let dirs = if parser.peek2::<wasi_kw::preopens>() {
|
||||
parser.parens(|p| p.parse::<Preopens>())?.preopens
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let mapped_dirs = if parser.peek2::<wasi_kw::map_dirs>() {
|
||||
parser.parens(|p| p.parse::<MapDirs>())?.map_dirs
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let assert_return = if parser.peek2::<wasi_kw::assert_return>() {
|
||||
Some(parser.parens(|p| p.parse::<AssertReturn>())?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let assert_stdout = if parser.peek2::<wasi_kw::assert_stdout>() {
|
||||
Some(parser.parens(|p| p.parse::<AssertStdout>())?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let assert_stderr = if parser.peek2::<wasi_kw::assert_stderr>() {
|
||||
Some(parser.parens(|p| p.parse::<AssertStderr>())?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
wasm_path,
|
||||
args,
|
||||
envs,
|
||||
dirs,
|
||||
mapped_dirs,
|
||||
assert_return,
|
||||
assert_stdout,
|
||||
assert_stderr,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
struct Envs<'a> {
|
||||
envs: Vec<(&'a str, &'a str)>,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for Envs<'a> {
|
||||
fn parse(parser: Parser<'a>) -> parser::Result<Self> {
|
||||
let mut envs = vec![];
|
||||
parser.parse::<wasi_kw::envs>()?;
|
||||
|
||||
while parser.peek::<&'a str>() {
|
||||
let res = parser.parse::<&'a str>()?;
|
||||
let mut strs = res.split('=');
|
||||
let first = strs.next().unwrap();
|
||||
let second = strs.next().unwrap();
|
||||
debug_assert!(strs.next().is_none());
|
||||
envs.push((first, second));
|
||||
}
|
||||
Ok(Self { envs })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
struct Args<'a> {
|
||||
args: Vec<&'a str>,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for Args<'a> {
|
||||
fn parse(parser: Parser<'a>) -> parser::Result<Self> {
|
||||
let mut args = vec![];
|
||||
parser.parse::<wasi_kw::args>()?;
|
||||
|
||||
while parser.peek::<&'a str>() {
|
||||
let res = parser.parse::<&'a str>()?;
|
||||
args.push(res);
|
||||
}
|
||||
Ok(Self { args })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
struct Preopens<'a> {
|
||||
preopens: Vec<&'a str>,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for Preopens<'a> {
|
||||
fn parse(parser: Parser<'a>) -> parser::Result<Self> {
|
||||
let mut preopens = vec![];
|
||||
parser.parse::<wasi_kw::preopens>()?;
|
||||
|
||||
while parser.peek::<&'a str>() {
|
||||
let res = parser.parse::<&'a str>()?;
|
||||
preopens.push(res);
|
||||
}
|
||||
Ok(Self { preopens })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
struct MapDirs<'a> {
|
||||
map_dirs: Vec<&'a str>,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for MapDirs<'a> {
|
||||
fn parse(parser: Parser<'a>) -> parser::Result<Self> {
|
||||
let mut map_dirs = vec![];
|
||||
parser.parse::<wasi_kw::map_dirs>()?;
|
||||
|
||||
while parser.peek::<&'a str>() {
|
||||
let res = parser.parse::<&'a str>()?;
|
||||
map_dirs.push(res);
|
||||
}
|
||||
Ok(Self { map_dirs })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
struct AssertReturn {
|
||||
return_value: i64,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for AssertReturn {
|
||||
fn parse(parser: Parser<'a>) -> parser::Result<Self> {
|
||||
parser.parse::<wasi_kw::assert_return>()?;
|
||||
let return_value = parser.parens(|p| {
|
||||
p.parse::<wasi_kw::fake_i64_const>()?;
|
||||
p.parse::<i64>()
|
||||
})?;
|
||||
Ok(Self { return_value })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
struct AssertStdout<'a> {
|
||||
expected: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for AssertStdout<'a> {
|
||||
fn parse(parser: Parser<'a>) -> parser::Result<Self> {
|
||||
parser.parse::<wasi_kw::assert_stdout>()?;
|
||||
Ok(Self {
|
||||
expected: parser.parse()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
struct AssertStderr<'a> {
|
||||
expected: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for AssertStderr<'a> {
|
||||
fn parse(parser: Parser<'a>) -> parser::Result<Self> {
|
||||
parser.parse::<wasi_kw::assert_stderr>()?;
|
||||
Ok(Self {
|
||||
expected: parser.parse()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_parse() {
|
||||
let pb = wast::parser::ParseBuffer::new(
|
||||
r#"(wasi_test "my_wasm.wasm"
|
||||
(envs "HELLO=WORLD" "RUST_BACKTRACE=1")
|
||||
(args "hello" "world" "--help")
|
||||
(preopens "." "src/io")
|
||||
(assert_return (i64.const 0))
|
||||
(assert_stdout "This is a \"string\" inside a string!")
|
||||
(assert_stderr "")
|
||||
)"#,
|
||||
)
|
||||
.unwrap();
|
||||
let result = wast::parser::parse::<WasiTest>(&pb).unwrap();
|
||||
|
||||
assert_eq!(result.args, vec!["hello", "world", "--help"]);
|
||||
assert_eq!(
|
||||
result.envs,
|
||||
vec![("HELLO", "WORLD"), ("RUST_BACKTRACE", "1")]
|
||||
);
|
||||
assert_eq!(result.dirs, vec![".", "src/io"]);
|
||||
assert_eq!(result.assert_return.unwrap().return_value, 0);
|
||||
assert_eq!(
|
||||
result.assert_stdout.unwrap().expected,
|
||||
"This is a \"string\" inside a string!"
|
||||
);
|
||||
assert_eq!(result.assert_stderr.unwrap().expected, "");
|
||||
}
|
||||
}
|
@ -504,3 +504,5 @@ impl NaNCheck for f64 {
|
||||
(self.to_bits() & 0x7fff_ffff_ffff_ffff) == 0x7ff8_0000_0000_0000
|
||||
}
|
||||
}
|
||||
|
||||
wast::custom_keyword!(wasi_test);
|
||||
|
Reference in New Issue
Block a user