Skip to content

Commit a35ed5d

Browse files
committed
Add tests to spin-core crate
Signed-off-by: Lann Martin <[email protected]>
1 parent c457018 commit a35ed5d

File tree

10 files changed

+360
-4
lines changed

10 files changed

+360
-4
lines changed

Cargo.lock

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build.rs

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ error: the `wasm32-wasi` target is not installed
3939

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

42+
build_wasm_test_program("core-wasi-test.wasm", "crates/core/tests/core-wasi-test");
4243
build_wasm_test_program("rust-http-test.wasm", "crates/http/tests/rust-http-test");
4344
build_wasm_test_program("redis-rust.wasm", "crates/redis/tests/rust");
4445
build_wasm_test_program("wagi-test.wasm", "crates/http/tests/wagi-test");

crates/core/Cargo.toml

+5-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,8 @@ async-trait = "0.1"
1010
wasi-cap-std-sync = "0.39"
1111
wasi-common = "0.39"
1212
wasmtime = "0.39"
13-
wasmtime-wasi = { version = "0.39", features = ["tokio"] }
13+
wasmtime-wasi = { version = "0.39", features = ["tokio"] }
14+
15+
[dev-dependencies]
16+
tempfile = "3"
17+
tokio = { version = "1", features = ["macros", "rt"] }

crates/core/src/host_component.rs

+41
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,44 @@ impl HostComponentsData {
174174
self.data[idx].get_or_insert_with(|| self.data_builders[idx]())
175175
}
176176
}
177+
178+
#[cfg(test)]
179+
mod tests {
180+
use super::*;
181+
182+
struct TestHC;
183+
184+
impl HostComponent for TestHC {
185+
type Data = u8;
186+
187+
fn add_to_linker<T: Send>(
188+
_linker: &mut Linker<T>,
189+
_get: impl Fn(&mut Data<T>) -> &mut Self::Data + Send + Sync + Copy + 'static,
190+
) -> Result<()> {
191+
Ok(())
192+
}
193+
194+
fn build_data(&self) -> Self::Data {
195+
0
196+
}
197+
}
198+
199+
#[test]
200+
fn host_components_data() {
201+
let engine = wasmtime::Engine::default();
202+
let mut linker: crate::Linker<()> = crate::Linker::new(&engine);
203+
204+
let mut builder = HostComponents::builder();
205+
let handle1 = builder
206+
.add_host_component(&mut linker, Arc::new(TestHC))
207+
.unwrap();
208+
let handle2 = builder.add_host_component(&mut linker, TestHC).unwrap();
209+
let host_components = builder.build();
210+
let mut hc_data = host_components.new_data();
211+
212+
assert_eq!(hc_data.get_or_insert(handle1), &0);
213+
214+
hc_data.set(handle2, 1);
215+
assert_eq!(hc_data.get_or_insert(handle2), &1);
216+
}
217+
}

crates/core/src/io.rs

+19
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,22 @@ impl OutputBuffer {
1616
WritePipe::from_shared(self.0.clone())
1717
}
1818
}
19+
20+
#[cfg(test)]
21+
mod tests {
22+
use std::io::IoSlice;
23+
24+
use wasi_common::WasiFile;
25+
26+
use super::*;
27+
28+
#[tokio::test]
29+
async fn take_what_you_write() {
30+
let mut buf = OutputBuffer::default();
31+
buf.writer()
32+
.write_vectored(&[IoSlice::new(b"foo")])
33+
.await
34+
.unwrap();
35+
assert_eq!(buf.take(), b"foo");
36+
}
37+
}

crates/core/src/store.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@ impl StoreBuilder {
108108
self.store_limits = StoreLimitsAsync::new(Some(max_memory_size), None);
109109
}
110110

111-
/// Inherit stdin, stdout, and stderr from the host process.
112-
pub fn inherit_stdio(&mut self) {
113-
self.with_wasi(|wasi| wasi.inherit_stdio());
111+
/// Inherit stdin from the host process.
112+
pub fn inherit_stdin(&mut self) {
113+
self.with_wasi(|wasi| wasi.inherit_stdin());
114114
}
115115

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

126+
/// Inherit stdin from the host process.
127+
pub fn inherit_stdout(&mut self) {
128+
self.with_wasi(|wasi| wasi.inherit_stdout());
129+
}
130+
126131
/// Sets the WASI `stdout` descriptor.
127132
pub fn stdout(&mut self, file: impl WasiFile + 'static) {
128133
self.with_wasi(|wasi| wasi.stdout(Box::new(file)))
@@ -140,6 +145,11 @@ impl StoreBuilder {
140145
buffer
141146
}
142147

148+
/// Inherit stdin from the host process.
149+
pub fn inherit_stderr(&mut self) {
150+
self.with_wasi(|wasi| wasi.inherit_stderr());
151+
}
152+
143153
/// Sets the WASI `stderr` descriptor.
144154
pub fn stderr(&mut self, file: impl WasiFile + 'static) {
145155
self.with_wasi(|wasi| wasi.stderr(Box::new(file)))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[build]
2+
target = "wasm32-wasi"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "core-wasi-test"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[profile.release]
7+
debug = true
8+
9+
[workspace]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//! This test program takes argument(s) that determine which WASI feature to
2+
//! exercise and returns an exit code of 0 for success, 1 for WASI interface
3+
//! failure (which is sometimes expected in a test), and some other code on
4+
//! invalid argument(s).
5+
6+
#[link(wasm_import_module = "multiplier")]
7+
extern "C" {
8+
fn multiply(n: i32) -> i32;
9+
}
10+
11+
type Result = std::result::Result<(), Box<dyn std::error::Error>>;
12+
13+
fn main() -> Result {
14+
let mut args = std::env::args();
15+
let cmd = args.next().expect("cmd");
16+
match cmd.as_str() {
17+
"noop" => (),
18+
"echo" => {
19+
eprintln!("echo");
20+
std::io::copy(&mut std::io::stdin(), &mut std::io::stdout())?;
21+
}
22+
"alloc" => {
23+
let size: usize = args.next().expect("size").parse().expect("size");
24+
eprintln!("alloc {size}");
25+
let layout = std::alloc::Layout::from_size_align(size, 8).expect("layout");
26+
unsafe {
27+
let p = std::alloc::alloc(layout);
28+
if p.is_null() {
29+
return Err("allocation failed".into());
30+
}
31+
// Force allocation to actually happen
32+
p.read_volatile();
33+
}
34+
}
35+
"read" => {
36+
let path = args.next().expect("path");
37+
eprintln!("read {path}");
38+
std::fs::read(path)?;
39+
}
40+
"write" => {
41+
let path = args.next().expect("path");
42+
eprintln!("write {path}");
43+
std::fs::write(path, "content")?;
44+
}
45+
"multiply" => {
46+
let input: i32 = args.next().expect("input").parse().expect("i32");
47+
eprintln!("multiply {input}");
48+
let output = unsafe { multiply(input) };
49+
println!("{output}");
50+
}
51+
"panic" => {
52+
eprintln!("panic");
53+
panic!("intentional panic");
54+
}
55+
cmd => panic!("unknown cmd {cmd}"),
56+
};
57+
Ok(())
58+
}

0 commit comments

Comments
 (0)