Files
sausage/sdk/tests/sdk.rs
T

140 lines
3.7 KiB
Rust

//! Native checks for generated schemas, dispatch, and missing core transports.
use sausage_plugin::serde_json::json;
use sausage_plugin::{Ctx, Interface, Result, rpc, schema};
/// The addition parameters.
#[schema]
struct Add {
/// The first integer.
a: i32,
/// The second integer.
b: i32,
}
/// A type with different serialize and deserialize contracts.
#[schema]
struct Defaulted {
/// A value which the provider defaults.
#[serde(default)]
value: String,
}
/// A documented string enum.
#[schema]
enum Choice {
/// The first choice.
First,
/// The second choice.
Second,
}
struct Plugin;
#[rpc(endpoints(control=Plugin))]
impl Plugin {
/// Return the same named object without a contract change.
fn identity(&self, p: Add) -> Result<Add> {
Ok(p)
}
/// Choose the first value.
fn choice(&self) -> Result<Choice> {
Ok(Choice::First)
}
/// Round-trip the defaulted object.
fn defaults(&self, p: Defaulted) -> Result<Defaulted> {
Ok(p)
}
/// Add integers.
///
/// Return their sum.
fn add(&self, p: Add) -> Result<i32> {
Ok(p.a + p.b)
}
}
#[test]
fn discovery_and_dispatch() {
let doc = Plugin.discover();
assert!(doc["components"]["schemas"].get("Empty").is_none());
let choice = doc["methods"]
.as_array()
.unwrap()
.iter()
.find(|m| m["name"] == "choice")
.unwrap();
assert!(choice.get("x-sausage-params").is_none());
assert!(
doc["x-sausage-endpoints"]["control"]["methods"]
.as_array()
.unwrap()
.iter()
.any(|m| m["name"] == "add")
);
assert!(doc["components"]["schemas"].get("AddResult").is_none());
assert_eq!(
doc["methods"]
.as_array()
.unwrap()
.iter()
.find(|m| m["name"] == "identity")
.unwrap()["result"]["schema"]["$ref"],
"#/components/schemas/Add"
);
assert!(
doc["components"]["schemas"]["Defaulted"]
.get("required")
.is_none()
);
assert_eq!(
doc["components"]["schemas"]["DefaultedResult"]["required"],
json!(["value"])
);
assert_eq!(
doc["components"]["schemas"]["Choice"]["oneOf"][0]["description"],
json!("The first choice.")
);
let add = doc["methods"]
.as_array()
.unwrap()
.iter()
.find(|m| m["name"] == "add")
.unwrap();
assert_eq!(add["summary"], "Add integers.");
assert_eq!(
doc["components"]["schemas"]["Add"]["description"],
"The addition parameters."
);
assert_eq!(add["params"][0]["description"], "The first integer.");
eprintln!("DISCOVER={doc}");
assert_eq!(
sausage_plugin::block_on(Plugin.dispatch("add", json!({"a":2,"b":3}), &Ctx::default()))
.unwrap(),
5
);
assert_eq!(
sausage_plugin::block_on(Plugin.dispatch("add", json!({}), &Ctx::default()))
.unwrap_err()
.code,
-32602
);
let internal: sausage_plugin::Error = sausage_plugin::serde_json::from_str::<i32>("bad")
.unwrap_err()
.into();
assert_eq!(internal.code, -32603);
}
#[sausage_plugin::test]
async fn missing_core_fails_without_wait() {
assert!(
Ctx::default()
.notify("progress", json!({}))
.unwrap_err()
.message
.contains("no core transport")
);
assert!(
sausage_plugin::call("core.lock", json!({}))
.await
.unwrap_err()
.message
.contains("no core transport")
);
}
#[test]
fn compile_fail() {
trybuild::TestCases::new().compile_fail("tests/ui/*.rs");
}