feat: complete Epic 1 production foundation
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
use crank_core::{
|
||||
AgentId, CorrelationContext, ExecutionErrorCode, ExecutionFailure, ExecutionOrigin,
|
||||
ExecutionStage, OutcomeCertainty, Retryability,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn frozen_execution_taxonomy_is_closed_and_consistent() {
|
||||
let cases = [
|
||||
(
|
||||
ExecutionErrorCode::AuthorizationDenied,
|
||||
ExecutionStage::Authorization,
|
||||
Retryability::Never,
|
||||
OutcomeCertainty::Certain,
|
||||
),
|
||||
(
|
||||
ExecutionErrorCode::InputSchemaInvalid,
|
||||
ExecutionStage::InputSchema,
|
||||
Retryability::Never,
|
||||
OutcomeCertainty::Certain,
|
||||
),
|
||||
(
|
||||
ExecutionErrorCode::ExecutionOverloaded,
|
||||
ExecutionStage::Admission,
|
||||
Retryability::AfterDelay,
|
||||
OutcomeCertainty::Certain,
|
||||
),
|
||||
(
|
||||
ExecutionErrorCode::ConfirmationRequired,
|
||||
ExecutionStage::Admission,
|
||||
Retryability::RequiresConfirmation,
|
||||
OutcomeCertainty::Certain,
|
||||
),
|
||||
(
|
||||
ExecutionErrorCode::IdempotencyOutcomeUnknown,
|
||||
ExecutionStage::Admission,
|
||||
Retryability::ManualReconcile,
|
||||
OutcomeCertainty::OutcomeUnknown,
|
||||
),
|
||||
(
|
||||
ExecutionErrorCode::RuntimeInternal,
|
||||
ExecutionStage::Runtime,
|
||||
Retryability::Never,
|
||||
OutcomeCertainty::Certain,
|
||||
),
|
||||
];
|
||||
|
||||
for (code, stage, retryability, certainty) in cases {
|
||||
let descriptor = ExecutionFailure::new(code, CorrelationContext::generate());
|
||||
assert_eq!(descriptor.stage(), stage);
|
||||
assert_eq!(descriptor.retryability(), retryability);
|
||||
assert_eq!(descriptor.outcome_certainty(), certainty);
|
||||
assert_eq!(descriptor.error_code(), code);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn execution_origin_enforces_agent_scope() {
|
||||
let agent_id = AgentId::new("agent_01");
|
||||
assert!(ExecutionOrigin::AdminDraft.validate_agent(None).is_ok());
|
||||
assert!(
|
||||
ExecutionOrigin::AdminDraft
|
||||
.validate_agent(Some(&agent_id))
|
||||
.is_err()
|
||||
);
|
||||
assert!(
|
||||
ExecutionOrigin::AgentSnapshot
|
||||
.validate_agent(Some(&agent_id))
|
||||
.is_ok()
|
||||
);
|
||||
assert!(ExecutionOrigin::AgentSnapshot.validate_agent(None).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dispatch_uncertainty_is_allowed_only_for_ambiguous_codes() {
|
||||
let correlation = CorrelationContext::generate();
|
||||
let timeout = ExecutionFailure::new(ExecutionErrorCode::UpstreamTimeout, correlation.clone())
|
||||
.with_dispatch_uncertainty();
|
||||
assert_eq!(timeout.retryability(), Retryability::ManualReconcile);
|
||||
assert_eq!(
|
||||
timeout.outcome_certainty(),
|
||||
OutcomeCertainty::OutcomeUnknown
|
||||
);
|
||||
|
||||
let validation = ExecutionFailure::new(ExecutionErrorCode::InputSchemaInvalid, correlation)
|
||||
.with_dispatch_uncertainty();
|
||||
assert_eq!(validation.retryability(), Retryability::Never);
|
||||
assert_eq!(validation.outcome_certainty(), OutcomeCertainty::Certain);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn failure_metadata_is_code_specific_and_bounded() {
|
||||
let correlation = CorrelationContext::generate();
|
||||
assert!(
|
||||
ExecutionFailure::new(ExecutionErrorCode::InputSchemaInvalid, correlation.clone())
|
||||
.try_with_retry_after_ms(1)
|
||||
.is_err()
|
||||
);
|
||||
assert!(
|
||||
ExecutionFailure::new(ExecutionErrorCode::UpstreamRateLimited, correlation.clone())
|
||||
.try_with_retry_after_ms(3_600_001)
|
||||
.is_err()
|
||||
);
|
||||
assert!(
|
||||
ExecutionFailure::new(ExecutionErrorCode::RuntimeInternal, correlation.clone())
|
||||
.try_with_confirmation("token", 1)
|
||||
.is_err()
|
||||
);
|
||||
assert!(
|
||||
ExecutionFailure::new(
|
||||
ExecutionErrorCode::ConfirmationRequired,
|
||||
correlation.clone()
|
||||
)
|
||||
.try_with_confirmation("x".repeat(4_097), 1)
|
||||
.is_err()
|
||||
);
|
||||
let challenge = ExecutionFailure::new(ExecutionErrorCode::ConfirmationRequired, correlation)
|
||||
.try_with_confirmation("secret-canary", 1_000)
|
||||
.expect("bounded confirmation");
|
||||
assert!(!format!("{challenge:?}").contains("secret-canary"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown_taxonomy_values_are_rejected_by_serde() {
|
||||
assert!(serde_json::from_str::<ExecutionStage>("\"unknown\"").is_err());
|
||||
assert!(serde_json::from_str::<ExecutionErrorCode>("\"unknown\"").is_err());
|
||||
assert!(serde_json::from_str::<Retryability>("\"automatic\"").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_published_code_has_stable_wire_value_stage_and_localized_messages() {
|
||||
let mut wire_values = std::collections::BTreeSet::new();
|
||||
for code in ExecutionErrorCode::ALL {
|
||||
assert!(wire_values.insert(code.as_str()));
|
||||
assert_eq!(serde_json::to_value(code).unwrap(), code.as_str());
|
||||
assert!(!code.message(crank_core::ExecutionLocale::Ru).is_empty());
|
||||
assert!(!code.message(crank_core::ExecutionLocale::En).is_empty());
|
||||
assert!(!code.stage().as_str().is_empty());
|
||||
assert!(!code.retryability().as_str().is_empty());
|
||||
assert!(!code.outcome_certainty().as_str().is_empty());
|
||||
}
|
||||
assert_eq!(wire_values.len(), ExecutionErrorCode::ALL.len());
|
||||
}
|
||||
Reference in New Issue
Block a user