Revision control
Copy as Markdown
Other Tools
use wasmparser::*;
#[test]
fn name_annotations() -> anyhow::Result<()> {
assert_module_name("foo", r#"(module $foo)"#)?;
assert_module_name("foo", r#"(module (@name "foo"))"#)?;
assert_module_name("foo", r#"(module $bar (@name "foo"))"#)?;
assert_module_name("foo bar", r#"(module $bar (@name "foo bar"))"#)?;
Ok(())
}
fn assert_module_name(expected_name: &str, wat: &str) -> anyhow::Result<()> {
let wasm = wat::parse_str(wat)?;
let mut found = false;
for s in get_name_section(&wasm)? {
match s? {
Name::Module { name, .. } => {
assert_eq!(name, expected_name);
found = true;
}
_ => {}
}
}
assert!(found);
Ok(())
}
#[test]
fn func_annotations() -> anyhow::Result<()> {
assert_func_name("foo", r#"(module (func $foo))"#)?;
assert_func_name("foo", r#"(module (func (@name "foo")))"#)?;
assert_func_name("foo", r#"(module (func $bar (@name "foo")))"#)?;
assert_func_name("foo bar", r#"(module (func $bar (@name "foo bar")))"#)?;
Ok(())
}
fn assert_func_name(name: &str, wat: &str) -> anyhow::Result<()> {
let wasm = wat::parse_str(wat)?;
let mut found = false;
for s in get_name_section(&wasm)? {
match s? {
Name::Function(n) => {
let naming = n.into_iter().next().unwrap()?;
assert_eq!(naming.index, 0);
assert_eq!(naming.name, name);
found = true;
}
_ => {}
}
}
assert!(found);
Ok(())
}
#[test]
fn local_annotations() -> anyhow::Result<()> {
assert_local_name("foo", r#"(module (func (param $foo i32)))"#)?;
assert_local_name("foo", r#"(module (func (local $foo i32)))"#)?;
assert_local_name("foo", r#"(module (func (param (@name "foo") i32)))"#)?;
assert_local_name("foo", r#"(module (func (local (@name "foo") i32)))"#)?;
assert_local_name("foo", r#"(module (func (param $bar (@name "foo") i32)))"#)?;
assert_local_name("foo", r#"(module (func (local $bar (@name "foo") i32)))"#)?;
assert_local_name(
"foo bar",
r#"(module (func (param $bar (@name "foo bar") i32)))"#,
)?;
assert_local_name(
"foo bar",
r#"(module (func (local $bar (@name "foo bar") i32)))"#,
)?;
Ok(())
}
fn assert_local_name(name: &str, wat: &str) -> anyhow::Result<()> {
let wasm = wat::parse_str(wat)?;
let mut found = false;
for s in get_name_section(&wasm)? {
match s? {
Name::Local(n) => {
let naming = n
.into_iter()
.next()
.unwrap()?
.names
.into_iter()
.next()
.unwrap()?;
assert_eq!(naming.index, 0);
assert_eq!(naming.name, name);
found = true;
}
_ => {}
}
}
assert!(found);
Ok(())
}
fn get_name_section(wasm: &[u8]) -> anyhow::Result<NameSectionReader<'_>> {
for payload in Parser::new(0).parse_all(&wasm) {
if let Payload::CustomSection(c) = payload? {
if let KnownCustom::Name(s) = c.as_known() {
return Ok(s);
}
}
}
panic!("no name section found");
}
#[test]
fn custom_section_order() -> anyhow::Result<()> {
let bytes = wat::parse_str(
r#"
(module
(@custom "A" "aaa")
(type (func))
(@custom "B" (after func) "bbb")
(@custom "C" (before func) "ccc")
(@custom "D" (after last) "ddd")
(table 10 funcref)
(func (type 0))
(@custom "E" (after import) "eee")
(@custom "F" (before type) "fff")
(@custom "G" (after data) "ggg")
(@custom "H" (after code) "hhh")
(@custom "I" (after func) "iii")
(@custom "J" (before func) "jjj")
(@custom "K" (before first) "kkk")
)
"#,
)?;
macro_rules! assert_matches {
($a:expr, $b:pat $(if $cond:expr)? $(,)?) => {
match &$a {
$b $(if $cond)? => {}
a => panic!("`{:?}` doesn't match `{}`", a, stringify!($b)),
}
};
}
let wasm = Parser::new(0)
.parse_all(&bytes)
.collect::<Result<Vec<_>>>()?;
assert_matches!(wasm[0], Payload::Version { .. });
assert_matches!(
wasm[1],
Payload::CustomSection(c) if c.name() == "K"
);
assert_matches!(
wasm[2],
Payload::CustomSection(c) if c.name() == "F"
);
assert_matches!(wasm[3], Payload::TypeSection(_));
assert_matches!(
wasm[4],
Payload::CustomSection(c) if c.name() == "E"
);
assert_matches!(
wasm[5],
Payload::CustomSection(c) if c.name() == "C"
);
assert_matches!(
wasm[6],
Payload::CustomSection(c) if c.name() == "J"
);
assert_matches!(wasm[7], Payload::FunctionSection(_));
assert_matches!(
wasm[8],
Payload::CustomSection(c) if c.name() == "B"
);
assert_matches!(
wasm[9],
Payload::CustomSection(c) if c.name() == "I"
);
assert_matches!(wasm[10], Payload::TableSection(_));
assert_matches!(wasm[11], Payload::CodeSectionStart { .. });
assert_matches!(wasm[12], Payload::CodeSectionEntry { .. });
assert_matches!(
wasm[13],
Payload::CustomSection(c) if c.name() == "H"
);
assert_matches!(
wasm[14],
Payload::CustomSection(c) if c.name() == "G"
);
assert_matches!(
wasm[15],
Payload::CustomSection(c) if c.name() == "A"
);
assert_matches!(
wasm[16],
Payload::CustomSection(c) if c.name() == "D"
);
match &wasm[17] {
Payload::End(x) if *x == bytes.len() => {}
p => panic!("`{:?}` doesn't match expected length of {}", p, bytes.len()),
}
Ok(())
}