use serde_json::{Value, json};
pub(crate) fn uuid_property(description: &str) -> Value {
json!({
"type": "string",
"description": description,
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",
})
}
pub(crate) fn namespace_property() -> Value {
json!({
"type": "string",
"minLength": 1,
"description":
"The namespace the workflow runs under. This is the authorization scope of the \
call, not a label: a namespace you do not hold is answered as not-found. Read it \
off a previous describe_run or list_runs result; never guess it.",
})
}
pub(crate) fn cursor_property(description: &str) -> Value {
json!({
"type": "integer",
"minimum": 0,
"description": description,
})
}
pub(crate) fn limit_property(description: &str) -> Value {
json!({
"type": "integer",
"minimum": 1,
"description": description,
})
}
pub(crate) fn status_values() -> Value {
json!([
"Running",
"Completed",
"Failed",
"Cancelled",
"TimedOut",
"ContinuedAsNew",
"Paused",
])
}
pub(crate) fn object_schema(properties: Value, required: &[&str]) -> Value {
let mut schema = serde_json::Map::new();
drop(schema.insert("type".to_owned(), json!("object")));
drop(schema.insert("properties".to_owned(), properties));
drop(schema.insert("required".to_owned(), json!(required)));
drop(schema.insert("additionalProperties".to_owned(), json!(false)));
Value::Object(schema)
}
pub(crate) fn output_schema(properties: Value, required: &[&str]) -> Value {
object_schema(properties, required)
}
#[cfg(test)]
mod tests {
use serde_json::json;
use super::{namespace_property, object_schema, status_values, uuid_property};
#[test]
fn an_object_schema_is_closed() {
let schema = object_schema(json!({ "a": { "type": "string" } }), &["a"]);
assert_eq!(schema["type"], "object");
assert_eq!(schema["additionalProperties"], false);
assert_eq!(schema["required"][0], "a");
}
#[test]
fn the_uuid_pattern_accepts_a_uuid_and_rejects_prose() -> Result<(), Box<dyn std::error::Error>>
{
let schema = uuid_property("an id");
let validator = jsonschema::validator_for(&schema)?;
assert!(validator.is_valid(&json!("f81d4fae-7dec-11d0-a765-00a0c91e6bf6")));
assert!(!validator.is_valid(&json!("the latest run")));
Ok(())
}
#[test]
fn the_namespace_property_requires_a_non_empty_string() -> Result<(), Box<dyn std::error::Error>>
{
let validator = jsonschema::validator_for(&namespace_property())?;
assert!(validator.is_valid(&json!("default")));
assert!(!validator.is_valid(&json!("")));
Ok(())
}
#[test]
fn the_status_enumeration_matches_the_projection() -> Result<(), serde_json::Error> {
let projected: Vec<serde_json::Value> = [
aion_core::WorkflowStatus::Running,
aion_core::WorkflowStatus::Completed,
aion_core::WorkflowStatus::Failed,
aion_core::WorkflowStatus::Cancelled,
aion_core::WorkflowStatus::TimedOut,
aion_core::WorkflowStatus::ContinuedAsNew,
aion_core::WorkflowStatus::Paused,
]
.into_iter()
.map(serde_json::to_value)
.collect::<Result<_, _>>()?;
assert_eq!(status_values(), serde_json::Value::Array(projected));
Ok(())
}
}