Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,44 @@ jobs:
- uses: mlugg/setup-zig@v2.0.5
- name: Run testsuite
run: zig build testsuite
wasi-testsuite-discover:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.discover.outputs.matrix }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Fetch WASI testsuite
run: |
git clone --depth 1 --branch prod/testsuite-base https://github.com/WebAssembly/wasi-testsuite.git /tmp/wasi-testsuite
- name: Discover tests
id: discover
run: |
MATRIX=$(python3 test/wasi-testsuite/discover-wasi-tests.py /tmp/wasi-testsuite --format github-matrix)
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
wasi-testsuite:
needs: wasi-testsuite-discover
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.wasi-testsuite-discover.outputs.matrix) }}
runs-on: ubuntu-latest
name: wasi-${{ matrix.suite }}-${{ matrix.test }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- uses: mlugg/setup-zig@v2.0.5
- name: Fetch WASI testsuite
run: |
git clone --depth 1 --branch prod/testsuite-base https://github.com/WebAssembly/wasi-testsuite.git /tmp/wasi-testsuite
pip3 install -r /tmp/wasi-testsuite/test-runner/requirements.txt
- name: Run WASI test ${{ matrix.suite }}/${{ matrix.test }}
run: zig build wasi-${{ matrix.suite }}-${{ matrix.test }}

lint:
runs-on: ubuntu-latest
steps:
Expand Down
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
zig-cache
.zig-cache
zig-out
test/testrunner/bin
test/testrunner/bin

# WASI testsuite generated files
test/wasi-testsuite/discovered_tests.json
__pycache__/
**/__pycache__/
*.pyc
87 changes: 86 additions & 1 deletion build.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const Build = @import("std").Build;
const std = @import("std");
const Build = std.Build;

pub fn build(b: *Build) !void {
const target = b.standardTargetOptions(.{});
Expand Down Expand Up @@ -60,9 +61,93 @@ pub fn build(b: *Build) !void {
testsuite_step.dependOn(&run_test.step);
}

// WASI testsuite integration - individual and aggregated test steps
const wasi_testsuite_dep = b.dependency("wasi-testsuite", .{});

// Aggregated step that runs all WASI tests at once
const wasi_testsuite_step = b.step("wasi-testsuite", "Run WASI testsuite tests (all languages)");
const run_wasi_tests = b.addSystemCommand(&.{
"python3",
"test-runner/wasi_test_runner.py",
"-t",
"tests/c/testsuite/wasm32-wasip1",
"tests/rust/testsuite/wasm32-wasip1",
"tests/assemblyscript/testsuite/wasm32-wasip1",
"-r",
b.pathFromRoot("test/wasi-testsuite/adapter/zware.py"),
});
run_wasi_tests.setCwd(wasi_testsuite_dep.path("."));
run_wasi_tests.setEnvironmentVariable("ZWARE_RUN", b.getInstallPath(.bin, "zware-run"));
run_wasi_tests.step.dependOn(b.getInstallStep());
wasi_testsuite_step.dependOn(&run_wasi_tests.step);

// Individual test steps - dynamically discovered from testsuite
// Create a helper function to discover and register tests for a suite
const TestSuite = struct {
key: []const u8,
path: []const u8,
};

const test_suites = [_]TestSuite{
.{ .key = "c", .path = "tests/c/testsuite/wasm32-wasip1" },
.{ .key = "rust", .path = "tests/rust/testsuite/wasm32-wasip1" },
.{ .key = "as", .path = "tests/assemblyscript/testsuite/wasm32-wasip1" },
};

for (test_suites) |suite| {
// Get the actual path to the testsuite directory
const suite_dir_path = wasi_testsuite_dep.path(suite.path).getPath(b);

// Open and scan the directory for .wasm files
var suite_dir = std.fs.cwd().openDir(suite_dir_path, .{ .iterate = true }) catch continue;
defer suite_dir.close();

var test_list: std.ArrayList([]const u8) = .empty;
defer test_list.deinit(b.allocator);

var iter = suite_dir.iterate();
while (iter.next() catch null) |entry| {
if (entry.kind == .file and std.mem.endsWith(u8, entry.name, ".wasm")) {
const test_name = entry.name[0 .. entry.name.len - 5]; // remove .wasm extension
const test_name_owned = b.allocator.dupe(u8, test_name) catch continue;
test_list.append(b.allocator, test_name_owned) catch continue;
}
}

// Sort test names for deterministic ordering
std.mem.sort([]const u8, test_list.items, {}, struct {
fn lessThan(_: void, lhs: []const u8, rhs: []const u8) bool {
return std.mem.lessThan(u8, lhs, rhs);
}
}.lessThan);

// Create individual build steps for each discovered test
for (test_list.items) |test_name| {
const run_test = b.addSystemCommand(&.{
"python3",
b.pathFromRoot("test/wasi-testsuite/run-single-wasi-test.py"),
suite.path,
test_name,
"-r",
b.pathFromRoot("test/wasi-testsuite/adapter/zware.py"),
"--test-runner",
"test-runner/wasi_test_runner.py",
});
run_test.setCwd(wasi_testsuite_dep.path("."));
run_test.setEnvironmentVariable("ZWARE_RUN", b.getInstallPath(.bin, "zware-run"));
run_test.step.dependOn(b.getInstallStep());
b.step(
b.fmt("wasi-{s}-{s}", .{ suite.key, test_name }),
b.fmt("Run WASI {s} test: {s}", .{ suite.key, test_name }),
).dependOn(&run_test.step);
}
}

const test_step = b.step("test", "Run all the tests");
test_step.dependOn(unittest_step);
test_step.dependOn(testsuite_step);
// Note: WASI testsuite is not included in default test step due to external dependencies
// Run it explicitly with: zig build wasi-testsuite

{
const exe = b.addExecutable(.{
Expand Down
4 changes: 4 additions & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
.url = "https://github.com/WebAssembly/testsuite/archive/e25ae159357c055b3a6fac99043644e208d26d2a.tar.gz",
.hash = "N-V-__8AAKtbtgBFkB_BMIKSUqC-temKvHmuqBSvjBlf4hD6",
},
.@"wasi-testsuite" = .{
.url = "https://github.com/WebAssembly/wasi-testsuite/archive/refs/heads/prod/testsuite-base.tar.gz",
.hash = "N-V-__8AAHAN1wCGU7h8wcRWoFr0TLZ_5M4KqbBYKfkLqIoY",
},
},
.paths = .{
"build.zig",
Expand Down
9 changes: 9 additions & 0 deletions src/instance.zig
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,15 @@ pub const Instance = struct {
});
}

/// Inherit stdin, stdout, and stderr from the host process.
/// Maps WASI fds 0, 1, 2 to host fds 0, 1, 2 respectively.
/// This matches the behavior of wasmtime's inherit_stdio().
pub fn inheritStdio(self: *Instance) !void {
try self.addWasiPreopen(0, "stdin", 0);
try self.addWasiPreopen(1, "stdout", 1);
try self.addWasiPreopen(2, "stderr", 2);
}

// FIXME: hide any allocation / deinit inside Instance
// Caller must call std.process.argsFree on returned args
//
Expand Down
Loading
Loading