Skip to content

Commit 66d593d

Browse files
committed
Add test for consuming interface types inputs
This commit adds a test suite for consuming interface types modules as input and producing a JS polyfill output. The tests are relatively simple today and don't exercise a ton of functionality, but they should hopefully cover the breadth of at least some basics of what wasm interface types supports today. A few small fixes were applied along the way, such as: * Don't require modules to have a stack pointer * Allow passing `*.wat`, `*.wit`, or `*.wasm` files as input to `wasm-bindgen` instead of always requiring `*.wasm`.
1 parent 203d86f commit 66d593d

File tree

21 files changed

+316
-15
lines changed

21 files changed

+316
-15
lines changed

crates/cli-support/Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,19 @@ Shared support for the wasm-bindgen-cli package, an internal dependency
1212
edition = '2018'
1313

1414
[dependencies]
15-
base64 = "0.9"
1615
anyhow = "1.0"
16+
base64 = "0.9"
1717
log = "0.4"
1818
rustc-demangle = "0.1.13"
1919
serde_json = "1.0"
2020
tempfile = "3.0"
2121
walrus = "0.14.0"
2222
wasm-bindgen-anyref-xform = { path = '../anyref-xform', version = '=0.2.55' }
23-
wasm-bindgen-shared = { path = "../shared", version = '=0.2.55' }
2423
wasm-bindgen-multi-value-xform = { path = '../multi-value-xform', version = '=0.2.55' }
24+
wasm-bindgen-shared = { path = "../shared", version = '=0.2.55' }
2525
wasm-bindgen-threads-xform = { path = '../threads-xform', version = '=0.2.55' }
2626
wasm-bindgen-wasm-conventions = { path = '../wasm-conventions', version = '=0.2.55' }
2727
wasm-bindgen-wasm-interpreter = { path = "../wasm-interpreter", version = '=0.2.55' }
28+
wit-text = "0.1.1"
2829
wit-walrus = "0.1.0"
30+
wit-validator = "0.1.0"

crates/cli-support/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,10 @@ impl Bindgen {
264264
(mem::replace(m, blank_module), &name[..])
265265
}
266266
Input::Path(ref path) => {
267-
let contents = fs::read(&path)
267+
let wasm = wit_text::parse_file(&path)
268268
.with_context(|| format!("failed to read `{}`", path.display()))?;
269+
wit_validator::validate(&wasm)
270+
.with_context(|| format!("failed to validate `{}`", path.display()))?;
269271
let module = walrus::ModuleConfig::new()
270272
// Skip validation of the module as LLVM's output is
271273
// generally already well-formed and so we won't gain much
@@ -278,7 +280,7 @@ impl Bindgen {
278280
.generate_name_section(!self.remove_name_section)
279281
.generate_producers_section(!self.remove_producers_section)
280282
.on_parse(wit_walrus::on_parse)
281-
.parse(&contents)
283+
.parse(&wasm)
282284
.context("failed to parse input file as wasm")?;
283285
let stem = match &self.out_name {
284286
Some(name) => &name,

crates/cli-support/src/wit/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ pub fn process(
9292

9393
impl<'a> Context<'a> {
9494
fn init(&mut self) -> Result<(), Error> {
95-
let stack_pointer = wasm_bindgen_wasm_conventions::get_shadow_stack_pointer(self.module)?;
96-
self.aux.shadow_stack_pointer = Some(stack_pointer);
95+
self.aux.shadow_stack_pointer =
96+
wasm_bindgen_wasm_conventions::get_shadow_stack_pointer(self.module);
9797

9898
// Make a map from string name to ids of all exports
9999
for export in self.module.exports.iter() {

crates/cli/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,17 @@ rayon = "1.0"
3636
tempfile = "3.0"
3737
walrus = "0.14"
3838
wit-printer = "0.1"
39+
wit-text = "0.1"
3940
wit-validator = "0.1"
4041
wit-walrus = "0.1"
4142

4243
[[test]]
4344
name = "reference"
4445
harness = false
4546

47+
[[test]]
48+
name = "interface-types"
49+
harness = false
50+
4651
[features]
4752
vendored-openssl = ['openssl/vendored']

crates/cli/tests/interface-types.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use anyhow::{bail, Result};
2+
use assert_cmd::prelude::*;
3+
use rayon::prelude::*;
4+
use std::env;
5+
use std::path::Path;
6+
use std::process::Command;
7+
8+
fn main() -> Result<()> {
9+
let filter = env::args().nth(1);
10+
11+
let mut tests = Vec::new();
12+
let dir = env::current_dir()?.join("tests/interface-types");
13+
for entry in dir.read_dir()? {
14+
let path = entry?.path();
15+
if path.extension().and_then(|s| s.to_str()) != Some("wit") {
16+
continue;
17+
}
18+
if let Some(filter) = &filter {
19+
if !path.display().to_string().contains(filter) {
20+
continue;
21+
}
22+
}
23+
tests.push(path);
24+
}
25+
tests.sort();
26+
27+
let errs = tests
28+
.par_iter()
29+
.filter_map(|t| runtest(t).err().map(|e| (t, e)))
30+
.collect::<Vec<_>>();
31+
32+
if errs.len() == 0 {
33+
println!("{} tests passed", tests.len());
34+
return Ok(());
35+
}
36+
eprintln!("failed tests:\n");
37+
for (test, err) in errs {
38+
eprintln!("{} failure\n{}", test.display(), tab(&format!("{:?}", err)));
39+
}
40+
bail!("tests failed");
41+
}
42+
43+
fn runtest(test: &Path) -> Result<()> {
44+
let js = test.with_extension("js");
45+
let td = tempfile::TempDir::new()?;
46+
47+
let mut bindgen = Command::cargo_bin("wasm-bindgen")?;
48+
bindgen
49+
.arg("--out-dir")
50+
.arg(td.path())
51+
.arg(test)
52+
.arg("--out-name=wasm")
53+
.arg("--nodejs")
54+
.arg("--no-typescript");
55+
exec(&mut bindgen)?;
56+
57+
exec(Command::new("node")
58+
.arg("--experimental-wasm-anyref")
59+
.arg("--experimental-wasm-mv")
60+
.arg(&js).env("NODE_PATH", td.path()))?;
61+
62+
Ok(())
63+
}
64+
65+
fn exec(cmd: &mut Command) -> Result<()> {
66+
let output = cmd.output()?;
67+
if output.status.success() {
68+
return Ok(());
69+
}
70+
let mut err = format!("command failed {:?}", cmd);
71+
err.push_str(&format!("\nstatus: {}", output.status));
72+
err.push_str(&format!(
73+
"\nstderr:\n{}",
74+
tab(&String::from_utf8_lossy(&output.stderr))
75+
));
76+
err.push_str(&format!(
77+
"\nstdout:\n{}",
78+
tab(&String::from_utf8_lossy(&output.stdout))
79+
));
80+
bail!("{}", err);
81+
}
82+
83+
fn tab(s: &str) -> String {
84+
format!(" {}", s.replace("\n", "\n "))
85+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const assert = require('assert');
2+
const wasm = require('wasm');
3+
4+
const obj = {};
5+
assert.strictEqual(wasm.foo(obj), obj);
6+
7+
wasm.store('x');
8+
assert.strictEqual(wasm.load(), 'x');
9+
10+
const obj2 = {};
11+
wasm.store(obj2);
12+
assert.strictEqual(wasm.load(), obj2);
13+
assert.strictEqual(wasm.load(), obj2);
14+
15+
wasm.store(undefined);
16+
assert.strictEqual(wasm.load(), undefined);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
(module
2+
(func $foo (param anyref) (result anyref)
3+
local.get 0)
4+
5+
(func $store (param anyref)
6+
i32.const 0
7+
local.get 0
8+
table.set 0)
9+
10+
(func $load (result anyref)
11+
i32.const 0
12+
table.get 0)
13+
14+
(table 1 anyref)
15+
16+
(@interface func (export "foo") (param anyref) (result anyref)
17+
arg.get 0
18+
call-core $foo)
19+
20+
(@interface func (export "store") (param anyref)
21+
arg.get 0
22+
call-core $store)
23+
24+
(@interface func (export "load") (result anyref)
25+
call-core $load)
26+
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const wasm = require('wasm');
2+
const assert = require('assert');
3+
4+
assert.strictEqual(wasm.foo(), 0);
5+
assert.strictEqual(wasm.get(), 1);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
(module
2+
(global $ctr (mut i32) (i32.const 0))
3+
4+
(func $increment
5+
global.get $ctr
6+
i32.const 1
7+
i32.add
8+
global.set $ctr)
9+
10+
(func $get (result i32)
11+
global.get $ctr)
12+
13+
(@interface func (export "foo") (result s32)
14+
defer-call-core $increment
15+
call-core $get
16+
i32-to-s32)
17+
18+
(@interface func (export "get") (result s32)
19+
call-core $get
20+
i32-to-s32)
21+
)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const m = require('wasm');
2+

0 commit comments

Comments
 (0)