Skip to content

feat(wasi): WasmEdge integration test target (8/8 ✅)#22

Open
gwpl wants to merge 6 commits intoraphaelmansuy:mainfrom
VariousForks:i19-target-wasmedge
Open

feat(wasi): WasmEdge integration test target (8/8 ✅)#22
gwpl wants to merge 6 commits intoraphaelmansuy:mainfrom
VariousForks:i19-target-wasmedge

Conversation

@gwpl
Copy link
Copy Markdown

@gwpl gwpl commented Mar 25, 2026

Summary

Greg's AI coding buddy here 🖖 — WasmEdge's installer wants python AND git? Nah, we went straight for the release tarball. Minimal dependencies, maximum reproducibility.

  • Adds WasmEdge v0.14.1 (CNCF Sandbox project) as an integration test target
  • Direct release tarball install (no python/git bloat in the container)
  • 8/8 tests passing: cloud-native WASM runtime runs edgeparse perfectly

Part of #19 — edgeparse runs everywhere & sandboxes securely

Test plan

  • ./tests/wasm-runtimes/wasm-test.sh test wasmedge → 8/8 pass

🤖 Generated with Claude Code

gwpl and others added 5 commits March 25, 2026 08:45
Greg's AI coding buddy reporting for duty! o7

* Make rayon optional behind a `native` feature flag (default: enabled)
* Add `convert_file()` dispatcher: native builds use `edgeparse_core::convert()`
  (with raster table OCR), WASI builds use `convert_bytes()` (in-memory)
* Sequential file iteration when rayon is disabled (#[cfg(not(feature = "native"))])
* Build for WASI: `cargo build --target wasm32-wasip1 --no-default-features`

The resulting .wasm binary is 3.1 MB and runs on wasmtime, wasmer,
wasmedge, wamr — basically anything that speaks WASI Preview 1.
PDF parsing works identically; you just trade parallelism for portability.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Greg's AI coding buddy: because if it doesn't run in a container,
does it even exist? Here's the full portable test suite.

Build Dockerfiles (reproducible compilation):
* Dockerfile.build.wasm   — wasm32-wasip1 (3.1 MB binary)
* Dockerfile.build.wasix  — wasm32-wasmer-wasi (WASIX toolchain)
* Dockerfile.build.riscv  — riscv64gc cross-compile (dynamic + static)

WASM runtime runners (all tested, all green):
* Dockerfile.runner.wasmtime  — Bytecode Alliance reference (v43)
* Dockerfile.runner.wasmer    — WASIX superpowers (v7)
* Dockerfile.runner.wasmedge  — CNCF cloud-native (v0.14.1)
* Dockerfile.runner.wamr      — embedded champion (iwasm, built from source)
* Dockerfile.runner.wasix     — WASIX backward compat on Wasmer

RISC-V runners:
* Dockerfile.runner.riscv-qemu — QEMU user-mode (proven, all tests pass)
* Dockerfile.runner.spike      — official ISA reference simulator + pk
* Dockerfile.runner.libriscv   — fastest sandbox (~3ns calls)
* Dockerfile.runner.rvvm       — tracing JIT (experimental)
* Dockerfile.runner.ckb-vm     — blockchain VM (experimental)

Management:
* wasm-test.sh  — build|test|status|run|log|rmi|clean
* run-tests.sh  — 7 tests per runtime (help, version, JSON/MD/TXT/HTML, errors)
* README.md     — architecture, quick start, extending guide
* All Docker images prefixed with EDGEPARSE_PREFIX (default: "edgeparse")

Verified: 6 runtimes × 8 assertions = 48/48 tests passing
(wasmtime, wasmer, wasmedge, wamr, wasix, riscv-qemu)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Greg's AI coding buddy: because typing Dockerfile paths is for people
who don't have a Makefile.

* make wasi-build   — build all WASM runtime + RISC-V Docker test images
* make wasi-test    — run integration tests across all runtimes
* make wasi-status  — show Docker image/container status
* make wasi-clean   — remove all WASI test Docker images and artifacts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Greg's AI coding buddy: debugging RISC-V VM sandboxes so you don't have to.

* Add ca-certificates to spike/libriscv/rvvm Dockerfiles (git clone over HTTPS)
* Fix libriscv arg passing: use '--' separator (rvlinux intercepts -f/-h flags)
* Fix RVVM binary discovery: handle rvvm_x86_64 naming in newer releases
* Fix libriscv build path: upstream moved rvlinux to emulator/ subdirectory

Known limitations:
* libriscv: glibc static TLS destructors crash on file I/O (needs musl target)
* CKB-VM: upstream ckb-debugger has compile errors (ckb_schemars incompatibility)
* RVVM: userland mode support varies by version (experimental)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Greg's AI coding buddy: battling every RISC-V VM's quirks so you
know exactly what works and what's still a quest-in-progress.

Spike fixes:
* Add libc6-dev-riscv64-cross for pk build (stubs-lp64.h)
* Symlink stubs-lp64d.h → stubs-lp64.h (ABI mismatch workaround)
* Symlink pk to riscv64-unknown-elf path (where spike searches)
* Status: builds, but pk has limited Linux syscall proxying — Rust
  binaries with TLS/complex allocators get truncated output

libriscv fixes:
* Build from emulator/ subdirectory (upstream restructured)
* Add '--' arg separator (rvlinux intercepts -f/-h flags)
* Status: help/version work, file I/O crashes on glibc TLS destructors

RVVM: documented as system-only emulator (no userland mode)
CKB-VM: upstream ckb-debugger has compile errors (kept for reference)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Docker-based WASI/RISC-V integration test infrastructure to run edgeparse across multiple runtimes (including WasmEdge via pinned release tarball), and updates the CLI crate to build/run cleanly without native-only features for WASI targets.

Changes:

  • Introduce tests/wasm-runtimes/ manager + in-container test runner scripts and documentation.
  • Add Docker build images (WASM/WASIX/RISC-V) and runner images for several WASM and RISC-V runtimes, including WasmEdge v0.14.1 via release tarball.
  • Make edgeparse-cli build WASI-friendly by gating rayon/native behavior behind a native feature; add Makefile targets to invoke the infra.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
tests/wasm-runtimes/wasm-test.sh Host-side build/test/status/clean manager for runtime containers and build artifacts
tests/wasm-runtimes/run-tests.sh In-container integration test runner that normalizes runtime invocation and executes conversion tests
tests/wasm-runtimes/README.md Usage/docs for the WASI/RISC-V integration test setup
tests/wasm-runtimes/Dockerfile.runner.base Shared Ubuntu base layer for WASM runners (fixtures + runner script)
tests/wasm-runtimes/Dockerfile.runner.wasmtime Wasmtime runner image
tests/wasm-runtimes/Dockerfile.runner.wasmer Wasmer runner image
tests/wasm-runtimes/Dockerfile.runner.wasmedge WasmEdge runner image (direct release tarball install)
tests/wasm-runtimes/Dockerfile.runner.wamr WAMR/iwasm runner image (build from source)
tests/wasm-runtimes/Dockerfile.runner.wasix WASIX-on-Wasmer runner image (compat mode)
tests/wasm-runtimes/Dockerfile.runner.riscv-qemu RISC-V QEMU user-mode runner image
tests/wasm-runtimes/Dockerfile.runner.spike Spike + pk runner image (source builds)
tests/wasm-runtimes/Dockerfile.runner.libriscv libriscv/rvlinux runner image (source build)
tests/wasm-runtimes/Dockerfile.runner.rvvm RVVM runner image (marked incompatible, kept for reference)
tests/wasm-runtimes/Dockerfile.runner.ckb-vm CKB-VM runner image (ckb-debugger)
tests/wasm-runtimes/Dockerfile.build.wasm Reproducible WASI build image producing edgeparse.wasm
tests/wasm-runtimes/Dockerfile.build.wasix Reproducible WASIX build image producing edgeparse-wasix.wasm
tests/wasm-runtimes/Dockerfile.build.riscv Reproducible RISC-V cross-compile image producing dynamic + static binaries
tests/wasm-runtimes/.gitignore Ignore extracted build artifacts under .build/
crates/edgeparse-cli/src/main.rs Route conversion via convert_file() and enable parallelism only with native feature
crates/edgeparse-cli/Cargo.toml Add native feature (default) and make rayon optional; disable edgeparse-core default features
Makefile Add wasi-build, wasi-test, wasi-status, wasi-clean targets

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +75 to +92
wasmtime)
# wasmtime: trailing args after .wasm are passed to the program;
# do NOT use "--" as wasmtime forwards it into argv
echo "wasmtime run --dir / ${wasm_or_bin} $*"
;;
wasmer)
# wasmer v7+: uses --volume (--dir is deprecated);
# requires "--" to separate wasmer flags from wasm args
echo "wasmer run --volume /test:/test ${wasm_or_bin} -- $*"
;;
wasmedge)
# wasmedge: --dir guest_path:host_path
echo "wasmedge --dir /:/ ${wasm_or_bin} $*"
;;
wamr)
# iwasm: --dir=path preopens a directory
echo "iwasm --dir=/ ${wasm_or_bin} $*"
;;
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The runner preopens the entire filesystem for several WASM runtimes (--dir / / --dir /:/ / --dir=/). The tests only need access to /test, so preopening / is broader than necessary and reduces the value of the sandbox in these integration tests. Consider limiting preopened directories to /test (and any other required paths) to better reflect real sandboxing constraints.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Assistant: All Copilot review comments on this PR are duplicates of those on PR #20 (same codebase). I've replied individually to each comment there with accept/pushback reasoning: #20

All accepted fixes are now committed (bc882e8) and pushed to this branch. Key changes: set -e fix, stable/experimental runtime split, test counter fix, help text update, stale artifact cleanup. See full commit.

Comment on lines +69 to +96
# NOTE: Do NOT use "--" to separate runtime flags from wasm args.
# Most runtimes forward "--" into the wasm program's argv, which causes
# clap to treat all subsequent args as positional values. Instead, place
# wasm program args directly after the .wasm path — the runtimes handle
# the separation internally via trailing_var_arg.
case "${RUNTIME}" in
wasmtime)
# wasmtime: trailing args after .wasm are passed to the program;
# do NOT use "--" as wasmtime forwards it into argv
echo "wasmtime run --dir / ${wasm_or_bin} $*"
;;
wasmer)
# wasmer v7+: uses --volume (--dir is deprecated);
# requires "--" to separate wasmer flags from wasm args
echo "wasmer run --volume /test:/test ${wasm_or_bin} -- $*"
;;
wasmedge)
# wasmedge: --dir guest_path:host_path
echo "wasmedge --dir /:/ ${wasm_or_bin} $*"
;;
wamr)
# iwasm: --dir=path preopens a directory
echo "iwasm --dir=/ ${wasm_or_bin} $*"
;;
wasix)
# WASIX on Wasmer: same as wasmer but with WASIX binary
echo "wasmer run --volume /test:/test ${wasm_or_bin} -- $*"
;;
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The note above build_run_cmd() says “Do NOT use -- to separate runtime flags from wasm args”, but the wasmer/wasix cases explicitly require --. This is confusing for future edits. Update the comment to reflect that -- is runtime-specific (discouraged for most, required for some).

Copilot uses AI. Check for mistakes.
Comment on lines +543 to +545
wasi-test: ## Run WASM/RISC-V integration tests across all runtimes
$(call log,Running WASM/RISC-V integration tests…)
@$(WASI_SCRIPT) test all
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wasi-test runs $(WASI_SCRIPT) test all, but the script’s current all target includes experimental/incompatible runtimes (e.g., rvvm) and will fail the overall target even when the supported runtimes pass. After splitting stable vs experimental targets in wasm-test.sh, update this Makefile target to run the stable set by default.

Suggested change
wasi-test: ## Run WASM/RISC-V integration tests across all runtimes
$(call log,Running WASM/RISC-V integration tests…)
@$(WASI_SCRIPT) test all
wasi-test: ## Run WASM/RISC-V integration tests across stable runtimes
$(call log,Running WASM/RISC-V integration tests…)
@$(WASI_SCRIPT) test stable

Copilot uses AI. Check for mistakes.
Comment on lines +227 to +231
docker run --rm \
--name "${PREFIX}-test-${runtime}" \
"${img}" \
"${runtime}"
local exit_code=$?
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the script runs with set -e, a failing docker run inside run_test() will abort the entire script before exit_code=$? and return ${exit_code} execute. This prevents cmd_test from aggregating failures and running subsequent runtimes. Wrap the docker run in an if ...; then ... else ... fi (or temporarily disable -e around it) so run_test reliably returns the container exit status instead of exiting the whole script.

Suggested change
docker run --rm \
--name "${PREFIX}-test-${runtime}" \
"${img}" \
"${runtime}"
local exit_code=$?
local exit_code
if docker run --rm \
--name "${PREFIX}-test-${runtime}" \
"${img}" \
"${runtime}"; then
exit_code=0
else
exit_code=$?
fi

Copilot uses AI. Check for mistakes.
Comment on lines +40 to +44
# Build everything and run all tests
./tests/wasm-runtimes/wasm-test.sh build all
./tests/wasm-runtimes/wasm-test.sh test all

# Or test a single runtime
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Quick Start suggests ./tests/wasm-runtimes/wasm-test.sh test all, but the current test all will include experimental/incompatible runtimes (e.g., rvvm is marked incompatible) and fail the overall run. Update the docs to either (a) define all as “stable only” or (b) document a separate target for experimental runtimes and warn that it may fail.

Suggested change
# Build everything and run all tests
./tests/wasm-runtimes/wasm-test.sh build all
./tests/wasm-runtimes/wasm-test.sh test all
# Or test a single runtime
# Build everything (including experimental runtimes) and run all tests
# NOTE: "all" includes experimental / incompatible runtimes (e.g. some RISC-V VMs)
# and the overall run may fail even if the stable runtimes pass.
./tests/wasm-runtimes/wasm-test.sh build all
./tests/wasm-runtimes/wasm-test.sh test all
# For a stable, green run, test a specific known-good runtime (recommended for CI)

Copilot uses AI. Check for mistakes.
Comment on lines +13 to +22
# Usage:
# ./wasm-test.sh build [all|wasm|riscv|base|wasmtime|wasmer|wasmedge|wamr|riscv-qemu]
# ./wasm-test.sh test [all|wasmtime|wasmer|wasmedge|wamr|riscv-qemu]
# ./wasm-test.sh status
# ./wasm-test.sh log <runtime>
# ./wasm-test.sh rmi [all|<image>]
# ./wasm-test.sh clean
# ./wasm-test.sh help
# ═══════════════════════════════════════════════════════════════════════════════
set -euo pipefail
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR title/description focus on adding the WasmEdge integration test target, but this change set also introduces the full WASM/RISC-V test infrastructure (manager script, runner, base image, multiple other runtime Dockerfiles, and CLI feature-gating). If this breadth is intentional, consider updating the PR description/title to reflect that it adds the whole infrastructure + multiple runtimes (not only WasmEdge) to reduce review/merge ambiguity.

Copilot uses AI. Check for mistakes.
IMG_CKB_VM="${PREFIX}-riscv-ckb-vm"

ALL_WASM_RUNTIMES="wasmtime wasmer wasmedge wamr wasix"
ALL_RISCV_RUNTIMES="riscv-qemu spike libriscv rvvm ckb-vm"
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ALL_RUNNERS includes spike, libriscv, rvvm, and ckb-vm, but at least rvvm is explicitly marked incompatible in its Dockerfile comments. As a result, ./wasm-test.sh test all (and make wasi-test) will attempt to run known-failing runtimes and return non-zero even when the supported runtimes pass. Consider splitting “stable” vs “experimental” runtimes and making test all run only the stable set (with an explicit opt-in for experimental ones).

Suggested change
ALL_RISCV_RUNTIMES="riscv-qemu spike libriscv rvvm ckb-vm"
# Split RISC-V runtimes into stable (default) and experimental (opt-in)
STABLE_RISCV_RUNTIMES="riscv-qemu"
EXPERIMENTAL_RISCV_RUNTIMES="spike libriscv rvvm ckb-vm"
ALL_RISCV_RUNTIMES="${STABLE_RISCV_RUNTIMES}"
ALL_EXPERIMENTAL_RISCV_RUNTIMES="${EXPERIMENTAL_RISCV_RUNTIMES}"

Copilot uses AI. Check for mistakes.
Comment on lines +199 to +208
wasm) build_wasm ;;
wasix-bin) build_wasix ;;
riscv) build_riscv ;;
base) build_base ;;
wasmtime|wasmer|wasmedge|wamr|wasix|riscv-qemu|spike|libriscv|rvvm|ckb-vm)
build_runner "${target}"
;;
*)
err "Unknown build target: ${target}"
echo "Valid: all wasm wasix-bin riscv base wasmtime wasmer wasmedge wamr wasix riscv-qemu spike libriscv rvvm ckb-vm"
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmd_build supports the wasix-bin target (builds ${IMG_BUILD_WASIX}), but image_name_for has no wasix-bin case. This makes it impossible to address the WASIX build image via commands that rely on image_name_for (e.g., rmi wasix-bin), and is confusing since wasix currently maps to the runner image instead. Add a wasix-bin mapping (and document it in help) or rename the target to avoid ambiguity.

Suggested change
wasm) build_wasm ;;
wasix-bin) build_wasix ;;
riscv) build_riscv ;;
base) build_base ;;
wasmtime|wasmer|wasmedge|wamr|wasix|riscv-qemu|spike|libriscv|rvvm|ckb-vm)
build_runner "${target}"
;;
*)
err "Unknown build target: ${target}"
echo "Valid: all wasm wasix-bin riscv base wasmtime wasmer wasmedge wamr wasix riscv-qemu spike libriscv rvvm ckb-vm"
wasm) build_wasm ;;
wasix-build) build_wasix ;;
riscv) build_riscv ;;
base) build_base ;;
wasmtime|wasmer|wasmedge|wamr|wasix|riscv-qemu|spike|libriscv|rvvm|ckb-vm)
build_runner "${target}"
;;
*)
err "Unknown build target: ${target}"
echo "Valid: all wasm wasix-build riscv base wasmtime wasmer wasmedge wamr wasix riscv-qemu spike libriscv rvvm ckb-vm"

Copilot uses AI. Check for mistakes.
Comment on lines +13 to +14
RUN curl -sSf https://wasmtime.dev/install.sh | bash
ENV PATH="/root/.wasmtime/bin:${PATH}"
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Wasmtime runner installs via curl | bash without pinning a specific Wasmtime version or verifying a checksum/signature. This undermines the “minimal dependencies / reproducibility” goal and can cause builds to change over time. Prefer downloading a pinned release artifact (or pass a pinned version to the installer if supported) and verify its checksum.

Suggested change
RUN curl -sSf https://wasmtime.dev/install.sh | bash
ENV PATH="/root/.wasmtime/bin:${PATH}"
RUN set -eux; \
WASMTIME_VERSION=24.0.0; \
ARCH="$(uname -m)"; \
case "$ARCH" in \
x86_64) WASMTIME_ARCH="x86_64" ;; \
aarch64|arm64) WASMTIME_ARCH="aarch64" ;; \
*) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \
esac; \
OS="$(uname -s | tr '[:upper:]' '[:lower:]')"; \
TARBALL="wasmtime-v${WASMTIME_VERSION}-${OS}-${WASMTIME_ARCH}.tar.xz"; \
BASE_URL="https://github.com/bytecodealliance/wasmtime/releases/download/v${WASMTIME_VERSION}"; \
curl -sSfL "${BASE_URL}/${TARBALL}" -o "${TARBALL}"; \
curl -sSfL "${BASE_URL}/${TARBALL}.sha256" -o "${TARBALL}.sha256"; \
sha256sum -c "${TARBALL}.sha256"; \
tar -xJf "${TARBALL}" --strip-components=1 -C /usr/local; \
rm "${TARBALL}" "${TARBALL}.sha256"

Copilot uses AI. Check for mistakes.
@gwpl
Copy link
Copy Markdown
Author

gwpl commented Mar 25, 2026

AI Assistant: 🖖

Copilot raised the same set of concerns across all 6 PRs (same codebase). I've posted a detailed analysis on PR #20 — accepting 9 items and explaining the reasoning behind 5 where our approach has good justifications:

👉 Full response on PR #20

TL;DR of accepted fixes (will push to all branches):

  • Fix set -e blocking failure aggregation
  • Fix test counter mismatch (8 passed / 7 total)
  • Add missing rm -f for stale JSON artifact
  • Split stable vs experimental runtimes (test all = stable only)
  • Update help text and -- separator docs
  • Remove unused WASIX build from default path

@raphaelmansuy — happy to push these fixes directly to all 6 PRs rather than opening new ones. What's your preference?

🤖 AI+👤🤝

AI Assistant: Applied accepted fixes from Copilot PR review.

* Fix `set -e` blocking failure aggregation: wrap `docker run` in
  if/else to capture exit code without aborting the script
* Fix test counter: track assertions vs tests separately, summary now
  shows "8 assertions across 7 tests" instead of misleading "8/7"
* Add missing `rm -f` for stale JSON artifact before Test 3
* Split stable vs experimental runtimes: `test all` now runs only
  green runtimes (6/6); use `test experimental` for WIP targets
* Update `--` separator comment: document per-runtime behavior
  (wasmtime=no, wasmer/wasix/libriscv/ckb-vm=yes)
* Add `wasix-build` to `image_name_for` (was missing mapping)
* Remove WASIX build from default `build all` path (unused by runners)
* Fix `xargs -r` (GNU-only) with portable container check
* Fix extra space in wasmedge `--dir` command
* Update help text with all targets including experimental

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants