// SPDX-License-Identifier: Apache-2.0 #![cfg(feature = "wasmldr")] use process_control::{ChildExt, Output, Timeout}; use std::path::Path; use std::process::{Command, Stdio}; use std::io::Write; use std::time::Duration; pub mod common; use common::{check_output, CRATE, KEEP_BIN, OUT_DIR, TEST_BINS_OUT, TIMEOUT_SECS}; use serial_test::serial; pub fn enarx_run<'a>(wasm: &str, input: impl Into>) -> Output { let wasm_path = Path::new(CRATE) .join(OUT_DIR) .join(TEST_BINS_OUT) .join(wasm); let mut child = Command::new(&String::from(KEEP_BIN)) .current_dir(CRATE) .arg("run") .arg(wasm_path) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() .unwrap_or_else(|e| panic!("failed to run `{}`: {:#?}", wasm, e)); if let Some(input) = input.into() { child .stdin .as_mut() .unwrap() .write_all(input) .expect("failed to write stdin to child"); drop(child.stdin.take()); } let output = child .with_output_timeout(Duration::from_secs(TIMEOUT_SECS)) .terminating() .wait() .unwrap_or_else(|e| panic!("failed to run `{}`: {:#?}", wasm, e)) .unwrap_or_else(|| panic!("process `{}` timed out", wasm)); assert!( output.status.code().is_some(), "process `{}` terminated by signal {:?}", wasm, output.status.signal() ); output } fn run_wasm_test<'a>( wasm: &str, status: i32, input: impl Into>, expected_stdout: impl Into>, expected_stderr: impl Into>, ) -> Output { let output = enarx_run(wasm, input); check_output(&output, status, expected_stdout, expected_stderr); output } #[test] #[serial] fn return_1() { // This module does, in fact, return 1. But function return values // are separate from setting the process exit status code, so // we still expect a return code of '0' here. run_wasm_test("return_1.wasm", 0, None, None, None); } #[test] #[serial] fn wasi_snapshot1() { // This module uses WASI to return the number of commandline args. // Since we don't currently do anything with the function return value, // we don't get any output here, and we expect '0', as above. run_wasm_test("wasi_snapshot1.wasm", 0, None, None, None); } #[test] #[serial] fn hello_wasi_snapshot1() { // This module just prints "Hello, world!" to stdout. Hooray! run_wasm_test( "hello_wasi_snapshot1.wasm", 0, None, &b"Hello, world!\n"[..], None, ); } #[test] #[serial] fn no_export() { // This module has no exported functions, so we get Error::ExportNotFound, // which wasmldr maps to EX_DATAERR (65) at process exit. run_wasm_test("no_export.wasm", 65, None, None, None); }