diff --git a/Cargo.lock b/Cargo.lock index aa517b5f0..bc4e8ec7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -184,6 +184,7 @@ dependencies = [ "tempdir", "vdso", "walkdir", + "wat", "x86_64", ] @@ -325,6 +326,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "leb128" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3576a87f2ba00f6f106fdfcd16db1d698d648a26ad8e0573cad8537c3c362d2a" + [[package]] name = "libc" version = "0.2.103" @@ -870,6 +877,24 @@ version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +[[package]] +name = "wast" +version = "38.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae0d7b256bef26c898fa7344a2d627e8499f5a749432ce0a05eae1a64ff0c271" +dependencies = [ + "leb128", +] + +[[package]] +name = "wat" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcfaeb27e2578d2c6271a45609f4a055e6d7ba3a12eff35b1fd5ba147bdf046" +dependencies = [ + "wast", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index ed4842971..318e73598 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,7 @@ vdso = "0.1" [build-dependencies] cc = "1.0" +wat = "1.0" walkdir = "2" protobuf-codegen-pure = "2.25" sallyport = { git = "https://github.com/enarx/sallyport", rev = "a567a22665c7e5ba88a8c4acd64ab43ee32b4681", features = [ "asm" ] } diff --git a/build.rs b/build.rs index a6adff48d..a76c92597 100644 --- a/build.rs +++ b/build.rs @@ -107,6 +107,19 @@ fn build_cc_tests(in_path: &Path, out_path: &Path) { } } +use wat; + +fn build_wasm_tests(in_path: &Path, out_path: &Path) { + for wat in find_files_with_extensions(&["wat"], &in_path) { + let wasm = out_path.join(wat.file_stem().unwrap()).with_extension("wasm"); + let bin = wat::parse_file(&wat) + .unwrap_or_else(|_| panic!("failed to compile {:?}", &wat)); + std::fs::write(&wasm, &bin) + .unwrap_or_else(|_| panic!("failed to write {:?}", &wasm)); + println!("cargo:rerun-if-changed={}", &wat.display()); + } +} + // Build a binary named `bin_name` from the crate located at `in_dir`, // targeting `target_name`, then strip the resulting binary and place it // at `out_dir`/bin/`bin_name`. @@ -235,6 +248,7 @@ fn main() -> Result<(), Box> { build_cc_tests(&Path::new(CRATE).join(TEST_BINS_IN), &out_dir_bin); build_rs_tests(&Path::new(CRATE).join(TEST_BINS_IN), &out_dir_bin); + build_wasm_tests(&Path::new(CRATE).join("tests/wasm"), &out_dir_bin); let target = "x86_64-unknown-linux-musl"; @@ -257,8 +271,8 @@ fn main() -> Result<(), Box> { #[cfg(feature = "wasmldr")] "wasmldr" => cargo_build_bin(&path, &out_dir, target, "wasmldr")?, - #[cfg(feature = "backend-kvm")] - "shim-sev" => cargo_build_bin(&path, &out_dir, target, "shim-sev")?, + //#[cfg(feature = "backend-kvm")] + //"shim-sev" => cargo_build_bin(&path, &out_dir, target, "shim-sev")?, #[cfg(feature = "backend-sgx")] "shim-sgx" => cargo_build_bin(&path, &out_dir, target, "shim-sgx")?, diff --git a/internal/wasmldr/build.rs b/internal/wasmldr/build.rs deleted file mode 100644 index a70310fc4..000000000 --- a/internal/wasmldr/build.rs +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -use std::path::Path; - -fn main() { - let in_dir = Path::new("fixtures"); - let out_dir = - std::env::var_os("OUT_DIR").expect("The OUT_DIR environment variable must be set"); - let out_dir = Path::new(&out_dir).join("fixtures"); - std::fs::create_dir_all(&out_dir).expect("Can't create output directory"); - - for entry in in_dir.read_dir().unwrap().flatten() { - let wat = entry.path(); - match wat.extension() { - Some(ext) if ext == "wat" => { - let wasm = out_dir - .join(wat.file_name().unwrap()) - .with_extension("wasm"); - let binary = wat::parse_file(&wat).expect("Can't parse wat file"); - std::fs::write(&wasm, &binary).expect("Can't write wasm file"); - println!("cargo:rerun-if-changed={}", &wat.display()); - } - _ => {} - } - } -} diff --git a/internal/wasmldr/fixtures/bundle/config.yaml b/internal/wasmldr/fixtures/bundle/config.yaml deleted file mode 100644 index 6b4695fb7..000000000 --- a/internal/wasmldr/fixtures/bundle/config.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -stdio: - stdin: - bundle: stdin.txt - stdout: - file: stdout.txt - stderr: - file: stderr.txt diff --git a/internal/wasmldr/fixtures/bundle/stdin.txt b/internal/wasmldr/fixtures/bundle/stdin.txt deleted file mode 100644 index cd0875583..000000000 --- a/internal/wasmldr/fixtures/bundle/stdin.txt +++ /dev/null @@ -1 +0,0 @@ -Hello world! diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 000000000..f332abfb5 --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +nightly-2021-09-30 diff --git a/src/main.rs b/src/main.rs index a43479e6d..06bf663ac 100644 --- a/src/main.rs +++ b/src/main.rs @@ -81,6 +81,19 @@ struct Info {} struct Exec { /// The payload to run inside the keep code: Option, + + /* + /// Provide a "shim" binary to set up the keep + #[structopt(long)] + shim: Option, + + /// Provide a "workldr" binary to load & execute the workload + #[structopt(long)] + workldr: Option, + + /// Path to the workload to execute inside the keep + workload: Option, + */ } #[derive(StructOpt)] diff --git a/tests/common.rs b/tests/common.rs new file mode 100644 index 000000000..d9cecf6fe --- /dev/null +++ b/tests/common.rs @@ -0,0 +1,6 @@ +pub const CRATE: &str = env!("CARGO_MANIFEST_DIR"); +pub const KEEP_BIN: &str = env!("CARGO_BIN_EXE_enarx-keepldr"); +pub const OUT_DIR: &str = env!("OUT_DIR"); +pub const TEST_BINS_OUT: &str = "bin"; +pub const TIMEOUT_SECS: u64 = 10; +pub const MAX_ASSERT_ELEMENTS: usize = 100; diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 41465408f..8211c653b 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -17,12 +17,8 @@ use serial_test::serial; use std::sync::Arc; use tempdir::TempDir; -const CRATE: &str = env!("CARGO_MANIFEST_DIR"); -const KEEP_BIN: &str = env!("CARGO_BIN_EXE_enarx-keepldr"); -const OUT_DIR: &str = env!("OUT_DIR"); -const TEST_BINS_OUT: &str = "bin"; -const TIMEOUT_SECS: u64 = 10; -const MAX_ASSERT_ELEMENTS: usize = 100; +mod common; +use common::*; fn assert_eq_slices(expected_output: &[u8], output: &[u8], what: &str) { let max_len = usize::min(output.len(), expected_output.len()); diff --git a/internal/wasmldr/fixtures/hello_wasi_snapshot1.wat b/tests/wasm/hello_wasi_snapshot1.wat similarity index 100% rename from internal/wasmldr/fixtures/hello_wasi_snapshot1.wat rename to tests/wasm/hello_wasi_snapshot1.wat diff --git a/internal/wasmldr/fixtures/no_export.wat b/tests/wasm/no_export.wat similarity index 100% rename from internal/wasmldr/fixtures/no_export.wat rename to tests/wasm/no_export.wat diff --git a/internal/wasmldr/fixtures/return_1.wat b/tests/wasm/return_1.wat similarity index 100% rename from internal/wasmldr/fixtures/return_1.wat rename to tests/wasm/return_1.wat diff --git a/internal/wasmldr/fixtures/wasi_snapshot1.wat b/tests/wasm/wasi_snapshot1.wat similarity index 100% rename from internal/wasmldr/fixtures/wasi_snapshot1.wat rename to tests/wasm/wasi_snapshot1.wat diff --git a/tests/wasmldr_tests.rs b/tests/wasmldr_tests.rs new file mode 100644 index 000000000..bf68893f4 --- /dev/null +++ b/tests/wasmldr_tests.rs @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: Apache-2.0 + +use std::fs::File; +use std::path::Path; +use std::process::{Command, Stdio}; +//use std::os::unix::process::CommandExt; +use std::os::unix::io::{RawFd, FromRawFd, IntoRawFd}; +use std::io; +use std::time::Duration; +use process_control::{ChildExt, Output, Timeout}; + +extern crate libc; +use libc::c_int; + +mod common; +use common::{CRATE, OUT_DIR, TEST_BINS_OUT, KEEP_BIN, TIMEOUT_SECS}; + +use serial_test::serial; +//use anyhow::Result; + +const MODULE_FD: RawFd = 3; + +// wrap a libc call to return io::Result +fn cvt(rv: c_int) -> io::Result { + if rv == -1 { Err(io::Error::last_os_error()) } else { Ok(rv) } +} + +fn open_module(path: &Path) -> io::Result { + let mut file = File::open(path)?; + let fd = file.into_raw_fd(); + unsafe { + file = File::from_raw_fd(cvt(libc::dup2(fd, MODULE_FD))?) + } + Ok(file) +} + +fn run_test(wasm: &str) -> Output { + let path = Path::new(CRATE).join(OUT_DIR).join(TEST_BINS_OUT).join(wasm); + let _fd3 = open_module(&path).unwrap(); + let child = Command::new(KEEP_BIN) + .arg("exec") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .unwrap_or_else(|e| panic!("failed to run `{:?}`: {:#?}", wasm, e)); + 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)); + + let _exit_status = output.status.code().unwrap_or_else(|| { + panic!("process `{}` terminated by signal {:?}", wasm, output.status.signal()) + }); + + // TODO: compare output.stdout, output.stderr, etc. + + output +} + +#[test] +#[serial] +fn hello_wasi_snapshot1() { + let out = run_test("hello_wasi_snapshot1.wasm"); + assert_eq!(out.stdout, &b"Hello, world!\n"[..]); +}