Skip to content

Commit

Permalink
Add tests to spin-core crate
Browse files Browse the repository at this point in the history
Signed-off-by: Lann Martin <[email protected]>
  • Loading branch information
lann committed Sep 20, 2022
1 parent c457018 commit a35ed5d
Show file tree
Hide file tree
Showing 10 changed files with 360 additions and 4 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ error: the `wasm32-wasi` target is not installed

std::fs::create_dir_all("target/test-programs").unwrap();

build_wasm_test_program("core-wasi-test.wasm", "crates/core/tests/core-wasi-test");
build_wasm_test_program("rust-http-test.wasm", "crates/http/tests/rust-http-test");
build_wasm_test_program("redis-rust.wasm", "crates/redis/tests/rust");
build_wasm_test_program("wagi-test.wasm", "crates/http/tests/wagi-test");
Expand Down
6 changes: 5 additions & 1 deletion crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ async-trait = "0.1"
wasi-cap-std-sync = "0.39"
wasi-common = "0.39"
wasmtime = "0.39"
wasmtime-wasi = { version = "0.39", features = ["tokio"] }
wasmtime-wasi = { version = "0.39", features = ["tokio"] }

[dev-dependencies]
tempfile = "3"
tokio = { version = "1", features = ["macros", "rt"] }
41 changes: 41 additions & 0 deletions crates/core/src/host_component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,44 @@ impl HostComponentsData {
self.data[idx].get_or_insert_with(|| self.data_builders[idx]())
}
}

#[cfg(test)]
mod tests {
use super::*;

struct TestHC;

impl HostComponent for TestHC {
type Data = u8;

fn add_to_linker<T: Send>(
_linker: &mut Linker<T>,
_get: impl Fn(&mut Data<T>) -> &mut Self::Data + Send + Sync + Copy + 'static,
) -> Result<()> {
Ok(())
}

fn build_data(&self) -> Self::Data {
0
}
}

#[test]
fn host_components_data() {
let engine = wasmtime::Engine::default();
let mut linker: crate::Linker<()> = crate::Linker::new(&engine);

let mut builder = HostComponents::builder();
let handle1 = builder
.add_host_component(&mut linker, Arc::new(TestHC))
.unwrap();
let handle2 = builder.add_host_component(&mut linker, TestHC).unwrap();
let host_components = builder.build();
let mut hc_data = host_components.new_data();

assert_eq!(hc_data.get_or_insert(handle1), &0);

hc_data.set(handle2, 1);
assert_eq!(hc_data.get_or_insert(handle2), &1);
}
}
19 changes: 19 additions & 0 deletions crates/core/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,22 @@ impl OutputBuffer {
WritePipe::from_shared(self.0.clone())
}
}

#[cfg(test)]
mod tests {
use std::io::IoSlice;

use wasi_common::WasiFile;

use super::*;

#[tokio::test]
async fn take_what_you_write() {
let mut buf = OutputBuffer::default();
buf.writer()
.write_vectored(&[IoSlice::new(b"foo")])
.await
.unwrap();
assert_eq!(buf.take(), b"foo");
}
}
16 changes: 13 additions & 3 deletions crates/core/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ impl StoreBuilder {
self.store_limits = StoreLimitsAsync::new(Some(max_memory_size), None);
}

/// Inherit stdin, stdout, and stderr from the host process.
pub fn inherit_stdio(&mut self) {
self.with_wasi(|wasi| wasi.inherit_stdio());
/// Inherit stdin from the host process.
pub fn inherit_stdin(&mut self) {
self.with_wasi(|wasi| wasi.inherit_stdin());
}

/// Sets the WASI `stdin` descriptor.
Expand All @@ -123,6 +123,11 @@ impl StoreBuilder {
self.stdin(ReadPipe::new(r))
}

/// Inherit stdin from the host process.
pub fn inherit_stdout(&mut self) {
self.with_wasi(|wasi| wasi.inherit_stdout());
}

/// Sets the WASI `stdout` descriptor.
pub fn stdout(&mut self, file: impl WasiFile + 'static) {
self.with_wasi(|wasi| wasi.stdout(Box::new(file)))
Expand All @@ -140,6 +145,11 @@ impl StoreBuilder {
buffer
}

/// Inherit stdin from the host process.
pub fn inherit_stderr(&mut self) {
self.with_wasi(|wasi| wasi.inherit_stderr());
}

/// Sets the WASI `stderr` descriptor.
pub fn stderr(&mut self, file: impl WasiFile + 'static) {
self.with_wasi(|wasi| wasi.stderr(Box::new(file)))
Expand Down
2 changes: 2 additions & 0 deletions crates/core/tests/core-wasi-test/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
target = "wasm32-wasi"
9 changes: 9 additions & 0 deletions crates/core/tests/core-wasi-test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "core-wasi-test"
version = "0.1.0"
edition = "2021"

[profile.release]
debug = true

[workspace]
58 changes: 58 additions & 0 deletions crates/core/tests/core-wasi-test/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//! This test program takes argument(s) that determine which WASI feature to
//! exercise and returns an exit code of 0 for success, 1 for WASI interface
//! failure (which is sometimes expected in a test), and some other code on
//! invalid argument(s).

#[link(wasm_import_module = "multiplier")]
extern "C" {
fn multiply(n: i32) -> i32;
}

type Result = std::result::Result<(), Box<dyn std::error::Error>>;

fn main() -> Result {
let mut args = std::env::args();
let cmd = args.next().expect("cmd");
match cmd.as_str() {
"noop" => (),
"echo" => {
eprintln!("echo");
std::io::copy(&mut std::io::stdin(), &mut std::io::stdout())?;
}
"alloc" => {
let size: usize = args.next().expect("size").parse().expect("size");
eprintln!("alloc {size}");
let layout = std::alloc::Layout::from_size_align(size, 8).expect("layout");
unsafe {
let p = std::alloc::alloc(layout);
if p.is_null() {
return Err("allocation failed".into());
}
// Force allocation to actually happen
p.read_volatile();
}
}
"read" => {
let path = args.next().expect("path");
eprintln!("read {path}");
std::fs::read(path)?;
}
"write" => {
let path = args.next().expect("path");
eprintln!("write {path}");
std::fs::write(path, "content")?;
}
"multiply" => {
let input: i32 = args.next().expect("input").parse().expect("i32");
eprintln!("multiply {input}");
let output = unsafe { multiply(input) };
println!("{output}");
}
"panic" => {
eprintln!("panic");
panic!("intentional panic");
}
cmd => panic!("unknown cmd {cmd}"),
};
Ok(())
}
Loading

0 comments on commit a35ed5d

Please sign in to comment.