diff --git a/tests/Sanity/rust-wasi-smoke-test/demo.rs b/tests/Sanity/rust-wasi-smoke-test/demo.rs new file mode 100644 index 0000000..ef652b3 --- /dev/null +++ b/tests/Sanity/rust-wasi-smoke-test/demo.rs @@ -0,0 +1,34 @@ +// Example taken from WASI documentation: +// https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-tutorial.md#from-rust +use std::env; +use std::fs; +use std::io::{Read, Write}; + +fn process(input_fname: &str, output_fname: &str) -> Result<(), String> { + let mut input_file = + fs::File::open(input_fname).map_err(|err| format!("error opening input {}: {}", input_fname, err))?; + let mut contents = Vec::new(); + input_file + .read_to_end(&mut contents) + .map_err(|err| format!("read error: {}", err))?; + + let mut output_file = fs::File::create(output_fname) + .map_err(|err| format!("error opening output {}: {}", output_fname, err))?; + output_file + .write_all(&contents) + .map_err(|err| format!("write error: {}", err)) +} + +fn main() { + let args: Vec = env::args().collect(); + let program = args[0].clone(); + + if args.len() < 3 { + eprintln!("usage: {} ", program); + return; + } + + if let Err(err) = process(&args[1], &args[2]) { + eprintln!("{}", err) + } +} diff --git a/tests/Sanity/rust-wasi-smoke-test/main.fmf b/tests/Sanity/rust-wasi-smoke-test/main.fmf new file mode 100644 index 0000000..239367a --- /dev/null +++ b/tests/Sanity/rust-wasi-smoke-test/main.fmf @@ -0,0 +1,23 @@ +summary: Compile and run a wasi app from rust +require+: + - rust-std-static-wasm32-wasi +duration: 5m +tier: 1 +tag: + - CI-Tier-1 +link: + - relates: https://bugzilla.redhat.com/show_bug.cgi?id=1980080 + - relates: https://bugzilla.redhat.com/show_bug.cgi?id=1980082 +adjust+: + - because: "WASI target not supported in s390x" + enabled: false + when: arch == s390x + continue: false + - because: "WASI target not shipped in RHEL older than 8" + enabled: false + when: distro < rhel-8 + continue: false +extra-nitrate: TC#0612641 +extra-summary: /tools/rust/Sanity/rust-wasi-smoke-test +extra-task: /tools/rust/Sanity/rust-wasi-smoke-test +id: 4b9bcfab-0527-4c68-8f8a-7d025f40c06e diff --git a/tests/Sanity/rust-wasi-smoke-test/runtest.sh b/tests/Sanity/rust-wasi-smoke-test/runtest.sh new file mode 100755 index 0000000..ffb56f3 --- /dev/null +++ b/tests/Sanity/rust-wasi-smoke-test/runtest.sh @@ -0,0 +1,80 @@ +#!/bin/bash +# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# runtest.sh of /tools/rust/Sanity/rust-wasi-smoke-test +# Description: Compile and run a wasi app from rust +# Author: Jesus Checa +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2021 Red Hat, Inc. +# +# This program is free software: you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation, either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# Include Beaker environment +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +PACKAGES="$(rpm -qf $(which rustc)) rust-std-static-wasm32-wasi" + +rlJournalStart + rlPhaseStartSetup + rlAssertRpm --all + rlRun "TmpDir=\$(mktemp -d)" 0 "Creating tmp directory" + # Because we need a specific nodejs version that supports WASI, we need + # to install it explicitly here. + if rlIsRHEL 8; then + # nodejs-16 has support for wasi. + rlRun "yum -y module switch-to nodejs:16" + rlRun "yum -y module install nodejs" + else # RHEL > 8 + # We ship nodejs-16 in rhel-9. + rlRun "yum -y install nodejs" + fi + # Example taken from WASI documentation: + # https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-tutorial.md#from-rust + rlRun "cp demo.rs $TmpDir" + rlRun "cp wasi_test*.js $TmpDir" + rlRun "pushd $TmpDir" + rlPhaseEnd + + rlPhaseStartTest + rlRun "rustc --target wasm32-wasi demo.rs -o demo.wasm" 0 "Building WASI binary" + rlAssertExists "demo.wasm" + + ### Test sandboxing + + TESTSTR="This is a test string" + rlRun "echo \"$TESTSTR\" > input.txt" + + # Test without preopening + rlRun "node --experimental-wasi-unstable-preview1 wasi_test_no_preopen.js 2> node.out" + rlAssertGrep "error opening" node.out + rlAssertGrep "failed to find a pre-opened file descriptor" node.out + rlAssertNotExists "output.txt" + + # Test with pre-opened directory + rlRun "node --experimental-wasi-unstable-preview1 wasi_test_preopen.js 2> node.out" + rlAssertNotGrep "error opening" node.out + rlAssertExists "output.txt" + rlAssertGrep "$TESTSTR" output.txt + rlPhaseEnd + + rlPhaseStartCleanup + rlRun "popd" + rlRun "rm -r $TmpDir" 0 "Removing tmp directory" + rlPhaseEnd +rlJournalEnd diff --git a/tests/Sanity/rust-wasi-smoke-test/wasi_test_no_preopen.js b/tests/Sanity/rust-wasi-smoke-test/wasi_test_no_preopen.js new file mode 100644 index 0000000..b9c188a --- /dev/null +++ b/tests/Sanity/rust-wasi-smoke-test/wasi_test_no_preopen.js @@ -0,0 +1,23 @@ +// From nodejs doc https://nodejs.org/api/wasi.html + +'use strict'; +const { readFile } = require('fs/promises'); +const { WASI } = require('wasi'); +const { argv, env } = require('process'); +const { join } = require('path'); + +const wasi = new WASI({ + args: ["demo.wasm", "/sandbox/input.txt", "/sandbox/output.txt"], + env, + version: 'preview1', +}); + +const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; +(async () => { + const wasm = await WebAssembly.compile( + await readFile(join(__dirname, 'demo.wasm')) + ); + const instance = await WebAssembly.instantiate(wasm, importObject); + + wasi.start(instance); +})(); diff --git a/tests/Sanity/rust-wasi-smoke-test/wasi_test_preopen.js b/tests/Sanity/rust-wasi-smoke-test/wasi_test_preopen.js new file mode 100644 index 0000000..0a8181f --- /dev/null +++ b/tests/Sanity/rust-wasi-smoke-test/wasi_test_preopen.js @@ -0,0 +1,26 @@ +// From nodejs doc https://nodejs.org/api/wasi.html + +'use strict'; +const { readFile } = require('fs/promises'); +const { WASI } = require('wasi'); +const { argv, env } = require('process'); +const { join } = require('path'); + +const wasi = new WASI({ + args: ["demo.wasm", "/sandbox/input.txt", "/sandbox/output.txt"], + env, + version: 'preview1', + preopens: { + '/sandbox': process.cwd(), + } +}); + +const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; +(async () => { + const wasm = await WebAssembly.compile( + await readFile(join(__dirname, 'demo.wasm')) + ); + const instance = await WebAssembly.instantiate(wasm, importObject); + + wasi.start(instance); +})();