use aion_proto::generated;
#[path = "test_support/grpc_admission.rs"]
mod grpc_admission;
use grpc_admission::{
TestResult, descriptor_for, mismatched_fetch, register, register_on_node, state_from,
state_with_contract,
};
const PARTITIONED_SOURCE: &str = "//! Node-partitioned registration fixture.\nworkflow partitioned_registration\n input url: String\n outcome done: type Result, route success\n\ntype Result { ok: Bool }\n\nworker typed_queue\n action fetch(url: String) -> Result\n node netbox\n action grade(url: String) -> Result\n node shell\n\nstep call\n fetch(url: url) -> fetched\n grade(url: url) -> graded\n route done(ok: fetched.ok and graded.ok)\n";
fn action_named(
actions: &[aion_package::ActionContract],
name: &str,
) -> TestResult<aion_package::ActionContract> {
actions
.iter()
.find(|action| action.name == name)
.cloned()
.ok_or_else(|| format!("the fixture declared no action `{name}`").into())
}
#[tokio::test]
async fn mismatched_worker_is_refused_with_field_level_diff() -> TestResult {
let (state, action) = state_with_contract().await?;
let result = register(state, mismatched_fetch(&action)).await?;
let status = result.err().ok_or("mismatched registration was accepted")?;
assert_eq!(status.code(), tonic::Code::FailedPrecondition);
assert!(status.message().contains("WORKER_CONTRACT_MISMATCH"));
assert!(status.message().contains("input_schema"));
assert!(status.message().contains("expected"));
assert!(status.message().contains("worker advertised"));
Ok(())
}
#[tokio::test]
async fn a_connection_serving_one_node_is_admitted_without_the_other_nodes_action() -> TestResult {
let (state, actions) = state_from(PARTITIONED_SOURCE).await?;
let fetch = action_named(&actions, "fetch")?;
let result = register_on_node(state, "netbox".to_owned(), vec![descriptor_for(&fetch)]).await?;
assert!(
result.is_ok(),
"the netbox connection serves its whole job and must be admitted without \
advertising the shell node's action: {:?}",
result.err().map(|status| status.message().to_owned())
);
Ok(())
}
#[tokio::test]
async fn a_connection_omitting_its_own_nodes_action_is_still_refused() -> TestResult {
let (state, actions) = state_from(PARTITIONED_SOURCE).await?;
let fetch = action_named(&actions, "fetch")?;
let result = register_on_node(state, "shell".to_owned(), vec![descriptor_for(&fetch)]).await?;
let status = result
.err()
.ok_or("a connection omitting its own node's action was accepted")?;
assert_eq!(status.code(), tonic::Code::FailedPrecondition);
assert!(status.message().contains("WORKER_CONTRACT_MISMATCH"));
assert!(
status.message().contains("grade"),
"the refusal must name the unserved action: {}",
status.message()
);
assert!(
status.message().contains("pinned to node `shell`"),
"the refusal must name the node that owed the action: {}",
status.message()
);
Ok(())
}
#[tokio::test]
async fn matching_worker_receives_register_ack() -> TestResult {
let (state, action) = state_with_contract().await?;
let result = register(
state,
generated::ActivityDescriptor {
name: action.name,
input_schema_json: action.input_schema.to_string(),
output_schema_json: action.output_schema.to_string(),
},
)
.await?;
assert!(result.is_ok());
Ok(())
}