73 lines
2.7 KiB
Rust
73 lines
2.7 KiB
Rust
// file: crates/ksp-job-api/tests/security_hardening.rs
|
|
// version: 1
|
|
|
|
//! Adversarial lifecycle, cancellation and redaction canaries.
|
|
|
|
const HOSTILE_MARKER: &str = "JOB-IDENTITY-SECRET-CANARY";
|
|
|
|
#[test]
|
|
fn pre_002_job_id_and_lifecycle_debug_redact_caller_identity() {
|
|
let id = ksp_job_api::JobId::new(HOSTILE_MARKER);
|
|
let kind = ksp_job_api::JobKindCode::new("backfill_raw");
|
|
assert!(id.is_ok());
|
|
assert!(kind.is_ok());
|
|
let id = match id {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
let kind = match kind {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
assert_eq!(std::format!("{id:?}"), "JobId(..)");
|
|
let lifecycle = ksp_job_api::JobLifecycle::new(id, kind);
|
|
let debug = std::format!("{lifecycle:?}");
|
|
assert!(debug.contains("JobLifecycle"));
|
|
assert!(debug.contains("backfill_raw"));
|
|
assert!(debug.contains("Created"));
|
|
assert!(!debug.contains(HOSTILE_MARKER));
|
|
return;
|
|
}
|
|
|
|
#[test]
|
|
fn pre_002_terminal_states_are_immutable_under_all_public_mutators() {
|
|
let id = ksp_job_api::JobId::new("terminal-job");
|
|
let kind = ksp_job_api::JobKindCode::new("test_job");
|
|
assert!(id.is_ok());
|
|
assert!(kind.is_ok());
|
|
let id = match id {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
let kind = match kind {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
let mut lifecycle = ksp_job_api::JobLifecycle::new(id, kind);
|
|
assert!(lifecycle.start().is_ok());
|
|
assert!(lifecycle.complete(ksp_job_api::JobCompletion::Complete).is_ok());
|
|
assert!(lifecycle.start().is_err());
|
|
assert!(lifecycle.mark_cancelling().is_err());
|
|
assert!(lifecycle.complete(ksp_job_api::JobCompletion::Partial).is_err());
|
|
assert!(lifecycle.mark_cancelled().is_err());
|
|
assert!(lifecycle.fail().is_err());
|
|
assert_eq!(lifecycle.state(), ksp_job_api::JobState::Completed(ksp_job_api::JobCompletion::Complete));
|
|
return;
|
|
}
|
|
|
|
#[test]
|
|
fn pre_002_cancellation_token_is_send_sync_and_cross_thread_visible() {
|
|
fn require_send_sync<T: std::marker::Send + std::marker::Sync>() {}
|
|
require_send_sync::<ksp_job_api::JobCancellationToken>();
|
|
let token = ksp_job_api::JobCancellationToken::new();
|
|
let worker_token = token.clone();
|
|
let thread = std::thread::spawn(move || return worker_token.cancel());
|
|
let request = match thread.join() {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(_) => return,
|
|
};
|
|
assert!(request);
|
|
assert!(token.is_cancellation_requested());
|
|
return;
|
|
}
|