sausage-plugin part 2: import! with typed clients (sausage_interface::client_rs), TCP endpoints with rpc.endpoint, examples
Part 1 fixes: complete stdout writes, buffered stdin, Rust type names in schemas, enum variant docs, -32603 for serde errors in handlers, crate docs and modules. End-to-end check of a generated consumer through a fake core.
This commit is contained in:
+101
-3
@@ -34,7 +34,16 @@ impl Process {
|
||||
}
|
||||
fn start(wasm: &Path, dir: &Path) -> Process {
|
||||
let mut child = Command::new("wasmtime")
|
||||
.args(["run", "--dir"])
|
||||
.args([
|
||||
"run",
|
||||
"-S",
|
||||
"inherit-network=y",
|
||||
"--env",
|
||||
"SAUSAGE_PID=probe-00000000-0000-7000-8000-000000000000",
|
||||
"--env",
|
||||
"SAUSAGE_PLUGIN=probe",
|
||||
"--dir",
|
||||
])
|
||||
.arg(format!("{}::/", dir.display()))
|
||||
.arg(wasm)
|
||||
.stdin(Stdio::piped())
|
||||
@@ -72,7 +81,12 @@ fn protocol() {
|
||||
let d = p.read();
|
||||
assert_eq!(d["result"]["x-sausage-grace"], 12);
|
||||
assert_eq!(
|
||||
d["result"]["methods"][0]["description"],
|
||||
d["result"]["methods"]
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|m| m["name"] == "add")
|
||||
.unwrap()["description"],
|
||||
"Add two numbers.\n\nThe result is their sum."
|
||||
);
|
||||
assert!(p.child.wait().unwrap().success());
|
||||
@@ -81,6 +95,18 @@ fn protocol() {
|
||||
assert_eq!(p.read()["result"], 6);
|
||||
assert!(p.child.wait().unwrap().success());
|
||||
let mut p = start(&wasm, &dir);
|
||||
p.request("echo", json!({"text":"x".repeat(70_000)}));
|
||||
assert_eq!(p.read()["result"], "x".repeat(70_000));
|
||||
assert!(p.child.wait().unwrap().success());
|
||||
let mut p = start(&wasm, &dir);
|
||||
p.request("echo", json!({"text":5}));
|
||||
assert_eq!(p.read()["error"]["code"], -32602);
|
||||
assert!(p.child.wait().unwrap().success());
|
||||
let mut p = start(&wasm, &dir);
|
||||
p.request("serde_error", json!({}));
|
||||
assert_eq!(p.read()["error"]["code"], -32603);
|
||||
assert!(p.child.wait().unwrap().success());
|
||||
let mut p = start(&wasm, &dir);
|
||||
p.request("fail", json!({}));
|
||||
assert_eq!(p.read()["error"]["code"], -32010);
|
||||
assert!(p.child.wait().unwrap().success());
|
||||
@@ -107,7 +133,7 @@ fn protocol() {
|
||||
assert!(p.child.wait().unwrap().success());
|
||||
let mut err = String::new();
|
||||
std::io::Read::read_to_string(p.child.stderr.as_mut().unwrap(), &mut err).unwrap();
|
||||
assert!(err.contains("unknown ID"));
|
||||
assert!(err.contains("unknown ID 9876"));
|
||||
assert!(err.contains("notification: tick"));
|
||||
let mut p = start(&wasm, &dir);
|
||||
p.request("rpc.retired", json!({"previous":"hash"}));
|
||||
@@ -143,5 +169,77 @@ fn protocol() {
|
||||
assert_eq!(outgoing["method"], "other.background");
|
||||
p.answer(&outgoing, json!({}));
|
||||
assert!(p.child.wait().unwrap().success());
|
||||
let provider_doc = &d["result"];
|
||||
let imports = root.join("tests/plugins/consumer/imports");
|
||||
std::fs::create_dir_all(&imports).unwrap();
|
||||
std::fs::write(
|
||||
imports.join("probe.json"),
|
||||
sausage_plugin::serde_json::to_vec_pretty(provider_doc).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let generated = sausage_interface::client_rs("probe", provider_doc).unwrap();
|
||||
std::fs::write(target.join("client.rs"), generated).unwrap();
|
||||
assert!(
|
||||
Command::new("cargo")
|
||||
.env("CARGO_TARGET_DIR", &target)
|
||||
.args(["build", "--offline", "--manifest-path"])
|
||||
.arg(root.join("tests/plugins/consumer/Cargo.toml"))
|
||||
.args(["--target", "wasm32-wasip2"])
|
||||
.status()
|
||||
.unwrap()
|
||||
.success()
|
||||
);
|
||||
let consumer = target.join("wasm32-wasip2/debug/sdk-consumer.wasm");
|
||||
let mut client = start(&consumer, &dir);
|
||||
client.request("rpc.discover", json!({}));
|
||||
let consumer_doc = client.read()["result"].clone();
|
||||
assert!(client.child.wait().unwrap().success());
|
||||
let imported = &consumer_doc["x-sausage-imports"]["probe"];
|
||||
assert!(sausage_interface::compat::check(imported, provider_doc).is_empty());
|
||||
let mut broken = provider_doc.clone();
|
||||
broken["methods"]
|
||||
.as_array_mut()
|
||||
.unwrap()
|
||||
.retain(|m| m["name"] != "add");
|
||||
assert!(!sausage_interface::compat::check(imported, &broken).is_empty());
|
||||
let mut client = start(&consumer, &dir);
|
||||
client.request("run", json!({}));
|
||||
let outgoing = client.read();
|
||||
assert_eq!(outgoing["method"], "core.call");
|
||||
assert_eq!(outgoing["params"]["method"], "probe.add");
|
||||
let mut provider = start(&wasm, &dir);
|
||||
provider.request("add", outgoing["params"]["params"].clone());
|
||||
let reply = provider.read();
|
||||
assert!(provider.child.wait().unwrap().success());
|
||||
client.send(json!({"jsonrpc":"2.0","method":"core.notify","params":{"call":outgoing["id"],"name":"typed","params":{}}}));
|
||||
client.answer(&outgoing, reply["result"].clone());
|
||||
assert_eq!(client.read()["result"], 5);
|
||||
assert!(client.child.wait().unwrap().success());
|
||||
let mut provider = start(&wasm, &dir);
|
||||
provider.request("serve", json!({}));
|
||||
assert_eq!(provider.read()["result"], Value::Null);
|
||||
let mut client = start(&consumer, &dir);
|
||||
client.request("endpoint", json!({}));
|
||||
assert_eq!(client.read()["result"], 7);
|
||||
assert!(client.child.wait().unwrap().success());
|
||||
let mut stderr = String::new();
|
||||
std::io::Read::read_to_string(client.child.stderr.as_mut().unwrap(), &mut stderr).unwrap();
|
||||
assert!(stderr.contains("endpoint notification: endpoint-progress"));
|
||||
let path = dir.join("endpoint");
|
||||
let original = std::fs::read_to_string(&path).unwrap();
|
||||
std::fs::write(&path, original.replace("probe-00000000", "probe-11111111")).unwrap();
|
||||
let mut client = start(&consumer, &dir);
|
||||
client.request("endpoint", json!({}));
|
||||
assert!(
|
||||
client.read()["error"]["message"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.contains("identity mismatch")
|
||||
);
|
||||
assert!(client.child.wait().unwrap().success());
|
||||
std::fs::write(path, original).unwrap();
|
||||
drop(provider.input.take());
|
||||
assert_eq!(provider.read()["params"]["name"], "stopped");
|
||||
assert!(provider.child.wait().unwrap().success());
|
||||
std::fs::remove_dir_all(dir).unwrap();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user