mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-12 20:41:24 +00:00
Add test for consuming interface types inputs (#1900)
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`.
This commit is contained in:
85
crates/cli/tests/interface-types.rs
Normal file
85
crates/cli/tests/interface-types.rs
Normal file
@ -0,0 +1,85 @@
|
||||
use anyhow::{bail, Result};
|
||||
use assert_cmd::prelude::*;
|
||||
use rayon::prelude::*;
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let filter = env::args().nth(1);
|
||||
|
||||
let mut tests = Vec::new();
|
||||
let dir = env::current_dir()?.join("tests/interface-types");
|
||||
for entry in dir.read_dir()? {
|
||||
let path = entry?.path();
|
||||
if path.extension().and_then(|s| s.to_str()) != Some("wit") {
|
||||
continue;
|
||||
}
|
||||
if let Some(filter) = &filter {
|
||||
if !path.display().to_string().contains(filter) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
tests.push(path);
|
||||
}
|
||||
tests.sort();
|
||||
|
||||
let errs = tests
|
||||
.par_iter()
|
||||
.filter_map(|t| runtest(t).err().map(|e| (t, e)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if errs.len() == 0 {
|
||||
println!("{} tests passed", tests.len());
|
||||
return Ok(());
|
||||
}
|
||||
eprintln!("failed tests:\n");
|
||||
for (test, err) in errs {
|
||||
eprintln!("{} failure\n{}", test.display(), tab(&format!("{:?}", err)));
|
||||
}
|
||||
bail!("tests failed");
|
||||
}
|
||||
|
||||
fn runtest(test: &Path) -> Result<()> {
|
||||
let js = test.with_extension("js");
|
||||
let td = tempfile::TempDir::new()?;
|
||||
|
||||
let mut bindgen = Command::cargo_bin("wasm-bindgen")?;
|
||||
bindgen
|
||||
.arg("--out-dir")
|
||||
.arg(td.path())
|
||||
.arg(test)
|
||||
.arg("--out-name=wasm")
|
||||
.arg("--nodejs")
|
||||
.arg("--no-typescript");
|
||||
exec(&mut bindgen)?;
|
||||
|
||||
exec(Command::new("node")
|
||||
.arg("--experimental-wasm-anyref")
|
||||
.arg("--experimental-wasm-mv")
|
||||
.arg(&js).env("NODE_PATH", td.path()))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn exec(cmd: &mut Command) -> Result<()> {
|
||||
let output = cmd.output()?;
|
||||
if output.status.success() {
|
||||
return Ok(());
|
||||
}
|
||||
let mut err = format!("command failed {:?}", cmd);
|
||||
err.push_str(&format!("\nstatus: {}", output.status));
|
||||
err.push_str(&format!(
|
||||
"\nstderr:\n{}",
|
||||
tab(&String::from_utf8_lossy(&output.stderr))
|
||||
));
|
||||
err.push_str(&format!(
|
||||
"\nstdout:\n{}",
|
||||
tab(&String::from_utf8_lossy(&output.stdout))
|
||||
));
|
||||
bail!("{}", err);
|
||||
}
|
||||
|
||||
fn tab(s: &str) -> String {
|
||||
format!(" {}", s.replace("\n", "\n "))
|
||||
}
|
16
crates/cli/tests/interface-types/anyref.js
Normal file
16
crates/cli/tests/interface-types/anyref.js
Normal file
@ -0,0 +1,16 @@
|
||||
const assert = require('assert');
|
||||
const wasm = require('wasm');
|
||||
|
||||
const obj = {};
|
||||
assert.strictEqual(wasm.foo(obj), obj);
|
||||
|
||||
wasm.store('x');
|
||||
assert.strictEqual(wasm.load(), 'x');
|
||||
|
||||
const obj2 = {};
|
||||
wasm.store(obj2);
|
||||
assert.strictEqual(wasm.load(), obj2);
|
||||
assert.strictEqual(wasm.load(), obj2);
|
||||
|
||||
wasm.store(undefined);
|
||||
assert.strictEqual(wasm.load(), undefined);
|
26
crates/cli/tests/interface-types/anyref.wit
Normal file
26
crates/cli/tests/interface-types/anyref.wit
Normal file
@ -0,0 +1,26 @@
|
||||
(module
|
||||
(func $foo (param anyref) (result anyref)
|
||||
local.get 0)
|
||||
|
||||
(func $store (param anyref)
|
||||
i32.const 0
|
||||
local.get 0
|
||||
table.set 0)
|
||||
|
||||
(func $load (result anyref)
|
||||
i32.const 0
|
||||
table.get 0)
|
||||
|
||||
(table 1 anyref)
|
||||
|
||||
(@interface func (export "foo") (param anyref) (result anyref)
|
||||
arg.get 0
|
||||
call-core $foo)
|
||||
|
||||
(@interface func (export "store") (param anyref)
|
||||
arg.get 0
|
||||
call-core $store)
|
||||
|
||||
(@interface func (export "load") (result anyref)
|
||||
call-core $load)
|
||||
)
|
5
crates/cli/tests/interface-types/defer-call.js
Normal file
5
crates/cli/tests/interface-types/defer-call.js
Normal file
@ -0,0 +1,5 @@
|
||||
const wasm = require('wasm');
|
||||
const assert = require('assert');
|
||||
|
||||
assert.strictEqual(wasm.foo(), 0);
|
||||
assert.strictEqual(wasm.get(), 1);
|
21
crates/cli/tests/interface-types/defer-call.wit
Normal file
21
crates/cli/tests/interface-types/defer-call.wit
Normal file
@ -0,0 +1,21 @@
|
||||
(module
|
||||
(global $ctr (mut i32) (i32.const 0))
|
||||
|
||||
(func $increment
|
||||
global.get $ctr
|
||||
i32.const 1
|
||||
i32.add
|
||||
global.set $ctr)
|
||||
|
||||
(func $get (result i32)
|
||||
global.get $ctr)
|
||||
|
||||
(@interface func (export "foo") (result s32)
|
||||
defer-call-core $increment
|
||||
call-core $get
|
||||
i32-to-s32)
|
||||
|
||||
(@interface func (export "get") (result s32)
|
||||
call-core $get
|
||||
i32-to-s32)
|
||||
)
|
2
crates/cli/tests/interface-types/empty.js
Normal file
2
crates/cli/tests/interface-types/empty.js
Normal file
@ -0,0 +1,2 @@
|
||||
const m = require('wasm');
|
||||
|
1
crates/cli/tests/interface-types/empty.wit
Normal file
1
crates/cli/tests/interface-types/empty.wit
Normal file
@ -0,0 +1 @@
|
||||
(module)
|
9
crates/cli/tests/interface-types/integers.js
Normal file
9
crates/cli/tests/interface-types/integers.js
Normal file
@ -0,0 +1,9 @@
|
||||
const assert = require('assert');
|
||||
const wasm = require('wasm');
|
||||
|
||||
assert.strictEqual(wasm.add_i8(0, 1), 1);
|
||||
assert.strictEqual(wasm.add_u8(0, 1), 1);
|
||||
assert.strictEqual(wasm.add_i16(0, 1), 1);
|
||||
assert.strictEqual(wasm.add_u16(0, 1), 1);
|
||||
assert.strictEqual(wasm.add_i32(0, 1), 1);
|
||||
assert.strictEqual(wasm.add_u32(0, 1), 1);
|
54
crates/cli/tests/interface-types/integers.wit
Normal file
54
crates/cli/tests/interface-types/integers.wit
Normal file
@ -0,0 +1,54 @@
|
||||
(module
|
||||
(func $add_i32 (param i32 i32) (result i32)
|
||||
local.get 0
|
||||
local.get 1
|
||||
i32.add)
|
||||
|
||||
(@interface func (export "add_i8") (param s8) (param s8) (result s8)
|
||||
arg.get 0
|
||||
s8-to-i32
|
||||
arg.get 1
|
||||
s8-to-i32
|
||||
call-core $add_i32
|
||||
i32-to-s8)
|
||||
|
||||
(@interface func (export "add_i16") (param s16) (param s16) (result s16)
|
||||
arg.get 0
|
||||
s16-to-i32
|
||||
arg.get 1
|
||||
s16-to-i32
|
||||
call-core $add_i32
|
||||
i32-to-s16)
|
||||
|
||||
(@interface func (export "add_i32") (param s32) (param s32) (result s32)
|
||||
arg.get 0
|
||||
s32-to-i32
|
||||
arg.get 1
|
||||
s32-to-i32
|
||||
call-core $add_i32
|
||||
i32-to-s32)
|
||||
|
||||
(@interface func (export "add_u8") (param s8) (param s8) (result s8)
|
||||
arg.get 0
|
||||
s8-to-i32
|
||||
arg.get 1
|
||||
s8-to-i32
|
||||
call-core $add_i32
|
||||
i32-to-s8)
|
||||
|
||||
(@interface func (export "add_u16") (param u16) (param u16) (result u16)
|
||||
arg.get 0
|
||||
u16-to-i32
|
||||
arg.get 1
|
||||
u16-to-i32
|
||||
call-core $add_i32
|
||||
i32-to-u16)
|
||||
|
||||
(@interface func (export "add_u32") (param u32) (param u32) (result u32)
|
||||
arg.get 0
|
||||
u32-to-i32
|
||||
arg.get 1
|
||||
u32-to-i32
|
||||
call-core $add_i32
|
||||
i32-to-u32)
|
||||
)
|
5
crates/cli/tests/interface-types/memory-to-string.js
Normal file
5
crates/cli/tests/interface-types/memory-to-string.js
Normal file
@ -0,0 +1,5 @@
|
||||
const wasm = require('wasm');
|
||||
const assert = require('assert');
|
||||
|
||||
assert.strictEqual(wasm.foo(), 'foo');
|
||||
assert.strictEqual(wasm.hexa(), 'hexa');
|
21
crates/cli/tests/interface-types/memory-to-string.wit
Normal file
21
crates/cli/tests/interface-types/memory-to-string.wit
Normal file
@ -0,0 +1,21 @@
|
||||
(module
|
||||
(memory 1)
|
||||
|
||||
(func $foo (result i32 i32)
|
||||
i32.const 0
|
||||
i32.const 3)
|
||||
(func $hexa (result i32 i32)
|
||||
i32.const 10
|
||||
i32.const 4)
|
||||
|
||||
(data (i32.const 0) "foo")
|
||||
(data (i32.const 10) "hexa")
|
||||
|
||||
(@interface func (export "foo") (result string)
|
||||
call-core $foo
|
||||
memory-to-string)
|
||||
|
||||
(@interface func (export "hexa") (result string)
|
||||
call-core $hexa
|
||||
memory-to-string)
|
||||
)
|
5
crates/cli/tests/interface-types/no-wasm.js
Normal file
5
crates/cli/tests/interface-types/no-wasm.js
Normal file
@ -0,0 +1,5 @@
|
||||
const assert = require('assert');
|
||||
const wasm = require('wasm');
|
||||
|
||||
wasm.nop();
|
||||
assert.strictEqual(wasm.roundtrip(1), 1);
|
5
crates/cli/tests/interface-types/no-wasm.wit
Normal file
5
crates/cli/tests/interface-types/no-wasm.wit
Normal file
@ -0,0 +1,5 @@
|
||||
(module
|
||||
(@interface func (export "nop"))
|
||||
(@interface func (export "roundtrip") (param s32) (result s32)
|
||||
arg.get 0)
|
||||
)
|
11
crates/cli/tests/interface-types/string-to-memory.js
Normal file
11
crates/cli/tests/interface-types/string-to-memory.js
Normal file
@ -0,0 +1,11 @@
|
||||
const wasm = require('wasm');
|
||||
const assert = require('assert');
|
||||
|
||||
const test = s => {
|
||||
wasm.set(s);
|
||||
assert.strictEqual(s, wasm.get());
|
||||
};
|
||||
|
||||
test('');
|
||||
test('x');
|
||||
test('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
|
27
crates/cli/tests/interface-types/string-to-memory.wit
Normal file
27
crates/cli/tests/interface-types/string-to-memory.wit
Normal file
@ -0,0 +1,27 @@
|
||||
(module
|
||||
(memory 1)
|
||||
|
||||
(global $glen (mut i32) (i32.const 0))
|
||||
(global $gptr (mut i32) (i32.const 0))
|
||||
|
||||
(func $malloc (param i32) (result i32) i32.const 23)
|
||||
|
||||
(func $set (param $ptr i32) (param $len i32)
|
||||
local.get $ptr
|
||||
global.set $gptr
|
||||
local.get $len
|
||||
global.set $glen)
|
||||
|
||||
(func $get (result i32 i32)
|
||||
global.get $gptr
|
||||
global.get $glen)
|
||||
|
||||
(@interface func (export "set") (param string)
|
||||
arg.get 0
|
||||
string-to-memory $malloc
|
||||
call-core $set)
|
||||
|
||||
(@interface func (export "get") (result string)
|
||||
call-core $get
|
||||
memory-to-string)
|
||||
)
|
Reference in New Issue
Block a user