cargo.build, the WASI test runner, the console, and core.notify ordering
- cargo.build (native): one source copy, tests under WASI, release build to /state/cargo/builds/<n>/, process groups killed on cancel. The host writes the SDK copy to /plugins/cargo/sdk/ at start. - sausage test-runner: one instance per test, in parallel, with its own mount table (empty world, package folder at its path); answers core.lock, core.unlock, core.notify, core.log. - The console: rustyline, notifications while typing, ls/cat through the process view, methods, ps, log, activate, revert, stop, kill. - core.notify on stdout is handled in order, before the response.
This commit is contained in:
@@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
sausage-actor = "0.1"
|
||||
sausage-plugin = "0.1"
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1"
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
//! Adds two numbers with a C function: `{"type": "add", "a", "b"}` -> `{"type": "sum", "value"}`.
|
||||
use sausage_actor::{json, messages, reply};
|
||||
|
||||
//! SDK plugin linked to a WASI C function.
|
||||
unsafe extern "C" {
|
||||
fn c_add(a: i32, b: i32) -> i32;
|
||||
}
|
||||
|
||||
fn add(a: i32, b: i32) -> i32 {
|
||||
unsafe { c_add(a, b) }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for message in messages() {
|
||||
let (a, b) = (message.body["a"].as_i64().unwrap_or(0), message.body["b"].as_i64().unwrap_or(0));
|
||||
let _ = reply(&message, json!({"type": "sum", "value": add(a as i32, b as i32)}));
|
||||
struct Plugin;
|
||||
#[sausage_plugin::rpc]
|
||||
impl Plugin {
|
||||
/// Add two fixed numbers through C.
|
||||
fn sum(&self) -> sausage_plugin::Result<i32> {
|
||||
Ok(add(2, 3))
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
sausage_plugin::run(Plugin);
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn c_code_runs_on_the_host_target() {
|
||||
fn c_code_runs_under_wasi() {
|
||||
assert_eq!(super::add(2, 3), 5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "cargo-hang"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[workspace]
|
||||
@@ -0,0 +1,7 @@
|
||||
//! A build script descendant that stays alive until the native call ends.
|
||||
fn main() {
|
||||
std::process::Command::new("sh")
|
||||
.args(["-c", "echo $$ > child.pid; exec sleep 1000"])
|
||||
.status()
|
||||
.unwrap();
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
fn main() {}
|
||||
@@ -1,9 +1,13 @@
|
||||
//! A panic must not prevent the runner from executing another test.
|
||||
fn main() {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn deliberate_unit_test_failure() {
|
||||
assert_eq!(2 + 2, 5);
|
||||
fn a_panics() {
|
||||
panic!("deliberate WASI panic");
|
||||
}
|
||||
#[test]
|
||||
fn z_survives() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,4 +3,7 @@ name = "cargo-valid"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
sausage-plugin = "0.1"
|
||||
|
||||
[workspace]
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
fixture
|
||||
@@ -1,9 +1,74 @@
|
||||
fn main() {}
|
||||
|
||||
//! SDK plugin and tests for the native build pipeline.
|
||||
struct Plugin;
|
||||
#[sausage_plugin::rpc]
|
||||
impl Plugin {
|
||||
/// Return a greeting.
|
||||
fn hello(&self) -> sausage_plugin::Result<String> {
|
||||
Ok("hello".into())
|
||||
}
|
||||
}
|
||||
fn main() {
|
||||
sausage_plugin::run(Plugin);
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn unit_tests_run_on_the_host_target() {
|
||||
fn arithmetic() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
}
|
||||
#[test]
|
||||
fn fixture_at_manifest_path() {
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(concat!(env!("CARGO_MANIFEST_DIR"), "/fixture.txt")).unwrap(),
|
||||
"fixture\n"
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn current_directory() {
|
||||
println!(
|
||||
"WASI_CURRENT_DIR={}",
|
||||
std::env::current_dir().unwrap().display()
|
||||
);
|
||||
}
|
||||
#[sausage_plugin::test]
|
||||
async fn sdk_lock() {
|
||||
let guard = sausage_plugin::lock("/state/lock").await.unwrap();
|
||||
assert!(guard.held());
|
||||
let mut guard = Some(guard);
|
||||
let mut waiting = Box::pin(std::future::IntoFuture::into_future(sausage_plugin::lock(
|
||||
"/state/lock",
|
||||
)));
|
||||
let acquired = std::future::poll_fn(|context| {
|
||||
let result = std::future::Future::poll(waiting.as_mut(), context);
|
||||
if result.is_pending() {
|
||||
drop(guard.take());
|
||||
}
|
||||
result
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(acquired.held());
|
||||
let logs = sausage_plugin::call("core.log", sausage_plugin::serde_json::json!({}))
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(logs.is_array());
|
||||
sausage_plugin::call(
|
||||
"core.notify",
|
||||
sausage_plugin::serde_json::json!({"name":"progress","params":{}}),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
#[sausage_plugin::test]
|
||||
async fn other_plugin_fails() {
|
||||
let error = sausage_plugin::call("missing.method", sausage_plugin::serde_json::json!({}))
|
||||
.await
|
||||
.unwrap_err();
|
||||
assert!(error.to_string().contains("a test has no other plugins"));
|
||||
}
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn ignored_case() {
|
||||
assert_eq!(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user