Skip to content

Commit

Permalink
Merge pull request #56 from kateinoigakukun/katei/wasi-testsuite-pr
Browse files Browse the repository at this point in the history
test: Setup wasi-testsuite with Node.js adapter
  • Loading branch information
bjorn3 authored Dec 14, 2023
2 parents 14686d4 + 53582ae commit 0426003
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: git submodule update --init test/wasi-testsuite
- uses: actions/setup-node@v3
with:
node-version: "16.x"
registry-url: "https://registry.npmjs.org"
- run: npm ci
- run: npm run check
- run: python3 -m pip install -r ./test/wasi-testsuite/test-runner/requirements.txt
- run: npm test
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
[submodule "examples/wasm-rustc"]
path = examples/wasm-rustc
url = [email protected]:bjorn3/wasm-rustc.git
[submodule "test/wasi-testsuite"]
path = test/wasi-testsuite
url = https://github.com/WebAssembly/wasi-testsuite
branch = prod/testsuite-base
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ $ npx http-server

And visit [http://127.0.0.1:8080/examples/rustc.html]() in your browser.

## Testing

```
$ python3 -m pip install -r ./test/wasi-testsuite/test-runner/requirements.txt
$ npm test
```

## License

Licensed under either of
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"scripts": {
"build": "swc src -d dist && tsc --emitDeclarationOnly",
"prepare": "swc src -d dist && tsc --emitDeclarationOnly",
"test": "./test/run-testsuite.sh",
"check": "tsc --noEmit && prettier src -c && eslint src/"
},
"repository": {
Expand Down
13 changes: 13 additions & 0 deletions test/adapter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import subprocess
import pathlib
import sys
import os

run_wasi_mjs = pathlib.Path(__file__).parent / "run-wasi.mjs"
args = sys.argv[1:]
cmd = ["node", str(run_wasi_mjs)] + args
if os.environ.get("VERBOSE_ADAPTER") is not None:
print(" ".join(map(lambda x: f"'{x}'", cmd)))

result = subprocess.run(cmd, check=False)
sys.exit(result.returncode)
14 changes: 14 additions & 0 deletions test/run-testsuite.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash

set -euo pipefail

TEST_DIR="$(cd "$(dirname $0)" && pwd)"
TESTSUITE_ROOT="$TEST_DIR/wasi-testsuite"

python3 "$TESTSUITE_ROOT/test-runner/wasi_test_runner.py" \
--test-suite "$TESTSUITE_ROOT/tests/assemblyscript/testsuite/" \
"$TESTSUITE_ROOT/tests/c/testsuite/" \
"$TESTSUITE_ROOT/tests/rust/testsuite/" \
--runtime-adapter "$TEST_DIR/adapter.py" \
--exclude-filter "$TEST_DIR/skip.json" \
$@
133 changes: 133 additions & 0 deletions test/run-wasi.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#!/usr/bin/env node

import fs from 'fs/promises';
import path from 'path';
import { WASI, wasi, strace, OpenFile, File, Directory, PreopenDirectory, Fd } from "../dist/index.js"

function parseArgs() {
const args = process.argv.slice(2);
const options = {
"version": false,
"test-file": null,
"arg": [],
"env": [],
"dir": [],
};
while (args.length > 0) {
const arg = args.shift();
if (arg.startsWith("--")) {
let [name, value] = arg.split("=");
name = name.slice(2);
if (Object.prototype.hasOwnProperty.call(options, name)) {
if (value === undefined) {
value = args.shift() || true;
}
if (Array.isArray(options[name])) {
options[name].push(value);
} else {
options[name] = value;
}
}
}
}

return options;
}

class NodeStdout extends Fd {
constructor(out) {
super();
this.out = out;
}

fd_filestat_get() {
const filestat = new wasi.Filestat(
wasi.FILETYPE_CHARACTER_DEVICE,
BigInt(0),
);
return { ret: 0, filestat };
}

fd_fdstat_get() {
const fdstat = new wasi.Fdstat(wasi.FILETYPE_CHARACTER_DEVICE, 0);
fdstat.fs_rights_base = BigInt(wasi.RIGHTS_FD_WRITE);
return { ret: 0, fdstat };
}

fd_write(view8, iovs) {
let nwritten = 0;
for (let iovec of iovs) {
let buffer = view8.slice(iovec.buf, iovec.buf + iovec.buf_len);
this.out.write(buffer);
nwritten += iovec.buf_len;
}
return { ret: 0, nwritten };
}
}

async function cloneToMemfs(dir) {
const destContents = {};
const srcContents = await fs.readdir(dir, { withFileTypes: true });
for (let entry of srcContents) {
const entryPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
destContents[entry.name] = new Directory(await cloneToMemfs(entryPath));
} else {
const buffer = await fs.readFile(entryPath);
const file = new File(buffer);
destContents[entry.name] = file;
}
}
return destContents;
}

async function derivePreopens(dirs) {
const preopens = [];
for (let dir of dirs) {
const contents = await cloneToMemfs(dir);
const preopen = new PreopenDirectory(dir, contents);
preopens.push(preopen);
}
return preopens;
}

async function runWASI(options) {
const testFile = options["test-file"]
if (!testFile) {
throw new Error("Missing --test-file");
}

// arg0 is the given test file
const args = [testFile].concat(options.arg)
const fds = [
new OpenFile(new File([])),
new NodeStdout(process.stdout),
new NodeStdout(process.stderr),
];
const preopens = await derivePreopens(options.dir);
fds.push(...preopens);
const wasi = new WASI(args, options.env, fds, { debug: false })

let wasiImport = wasi.wasiImport;
if (process.env["STRACE"]) {
wasiImport = strace(wasiImport, []);
}
const importObject = { wasi_snapshot_preview1: wasiImport }

const wasm = await WebAssembly.compile(await fs.readFile(testFile));
const instance = await WebAssembly.instantiate(wasm, importObject);
const status = wasi.start(instance);
process.exit(status);
}

async function main() {
const options = parseArgs();
if (options.version) {
const pkg = JSON.parse(await fs.readFile(new URL("../package.json", import.meta.url)));
console.log(`${pkg.name} v${pkg.version}`);
return;
}
runWASI(options);
}

await main();
40 changes: 40 additions & 0 deletions test/skip.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"WASI Assemblyscript tests": {
},
"WASI C tests": {
"sock_shutdown-invalid_fd": "not implemented yet",
"stat-dev-ino": "fail",
"sock_shutdown-not_sock": "fail",
"fdopendir-with-access": "fail"
},
"WASI Rust tests": {
"sched_yield": "not implemented yet",
"path_rename": "fail",
"fd_advise": "fail",
"path_exists": "fail",
"path_open_dirfd_not_dir": "fail",
"fd_filestat_set": "fail",
"symlink_create": "fail",
"overwrite_preopen": "fail",
"path_open_read_write": "fail",
"path_rename_dir_trailing_slashes": "fail",
"fd_flags_set": "fail",
"path_filestat": "fail",
"path_link": "fail",
"fd_fdstat_set_rights": "fail",
"readlink": "fail",
"unlink_file_trailing_slashes": "fail",
"path_symlink_trailing_slashes": "fail",
"poll_oneoff_stdio": "fail",
"dangling_symlink": "fail",
"dir_fd_op_failures": "fail",
"file_allocate": "fail",
"nofollow_errors": "fail",
"path_open_preopen": "fail",
"fd_readdir": "fail",
"directory_seek": "fail",
"symlink_filestat": "fail",
"symlink_loop": "fail",
"interesting_paths": "fail"
}
}
1 change: 1 addition & 0 deletions test/wasi-testsuite
Submodule wasi-testsuite added at 616f50

0 comments on commit 0426003

Please sign in to comment.