use cellos_core::{
lifecycle_destroyed_data_v1, ExecutionCellSpec, LifecycleDestroyOutcome,
LifecycleTerminalState, Lifetime,
};
fn forced_destroyed_spec() -> ExecutionCellSpec {
ExecutionCellSpec {
id: "fc23-forced".into(),
correlation: None,
ingress: None,
environment: None,
placement: None,
policy: None,
identity: None,
run: None,
authority: Default::default(),
lifetime: Lifetime { ttl_seconds: 30 },
export: None,
telemetry: None,
}
}
#[test]
fn forced_terminal_state_payload_has_no_exit_code_field() {
let spec = forced_destroyed_spec();
let data = lifecycle_destroyed_data_v1(
&spec,
"cell-fc23",
Some("run-fc23"),
LifecycleDestroyOutcome::Failed,
Some("in-VM exit bridge: vsock closed before exit code"),
Some(LifecycleTerminalState::Forced),
None,
None,
)
.expect("constructor builds destroyed payload");
let obj = data.as_object().expect("destroyed data is a JSON object");
assert_eq!(
obj.get("terminalState").and_then(|v| v.as_str()),
Some("forced")
);
assert!(
!obj.contains_key("exitCode"),
"FC-23: forced terminal state must not carry an exitCode field; got {data}"
);
assert!(
!obj.contains_key("exit_code"),
"FC-23: snake_case exit_code must also be absent on forced events"
);
}
#[test]
fn forced_terminal_normalizes_exit_code_to_null_even_on_success_outcome() {
let spec = forced_destroyed_spec();
let data = lifecycle_destroyed_data_v1(
&spec,
"cell-fc23-ok",
None,
LifecycleDestroyOutcome::Succeeded,
None,
Some(LifecycleTerminalState::Forced),
None,
None,
)
.expect("constructor builds destroyed payload");
let obj = data.as_object().expect("destroyed data is a JSON object");
assert_eq!(
obj.get("terminalState").and_then(|v| v.as_str()),
Some("forced")
);
assert!(
!obj.contains_key("exitCode"),
"FC-23: forced terminalState must never carry exitCode regardless of outcome"
);
}
#[test]
fn clean_terminal_state_payload_also_has_no_exit_code_field() {
let spec = forced_destroyed_spec();
let data = lifecycle_destroyed_data_v1(
&spec,
"cell-fc23-clean",
None,
LifecycleDestroyOutcome::Succeeded,
None,
Some(LifecycleTerminalState::Clean),
None,
None,
)
.expect("constructor builds destroyed payload");
let obj = data.as_object().expect("destroyed data is a JSON object");
assert_eq!(
obj.get("terminalState").and_then(|v| v.as_str()),
Some("clean")
);
assert!(
!obj.contains_key("exitCode"),
"destroyed payload must not carry exitCode on any path; \
authenticated codes ride on cell.command.v1.completed"
);
}