use super::*;
use saddle_boundary::ingress::{CodecError, ManagedIngressError};
#[test]
fn cross_crate_codec_classification_preserves_other_branches() {
let codec = |status, code| ManagedIngressError::Codec(CodecError { http_status: status, code });
assert!(envelope_rejection_facts(&codec(400, "INVALID_JSON_ENVELOPE")).is_some());
for error in [codec(503, "INVALID_JSON_ENVELOPE"), codec(400, "OTHER"),
ManagedIngressError::Storage(saddle_admission::AdmissionError::AllocationFailed)] {
assert!(envelope_rejection_facts(&error).is_none());
}
}
#[test]
fn codec_borrowed_written_original_is_single_and_missing_writer_unconfirmed() {
use saddle_core::{ContextFact, ContextLabel, RequestLocalFacts, RequestRootPublisher, RequestViewPhase};
use saddle_observability::{EmergencyDiagnostics, FileLoggingConfig, Rotation, RootDiagnosticScope};
let directory = std::env::temp_dir().join(format!("codec-classification-{}-{}", std::process::id(),
std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_nanos()));
std::fs::create_dir(&directory).unwrap();
let mut writer = EmergencyDiagnostics::start(&FileLoggingConfig::new(&directory, Rotation::Daily)).unwrap();
let handle = writer.handle();
let root = RequestRootPublisher::create(ContextLabel::checked("codec-control").unwrap(), ContextFact::NotEstablished).unwrap();
let view = root.reference().view(RequestLocalFacts::new(RequestViewPhase::Reading));
let error = ManagedIngressError::Codec(CodecError { http_status: 400, code: "INVALID_JSON_ENVELOPE" });
let before = format!("{error:?}");
let (facts, code) = envelope_rejection_facts(&error).unwrap();
let recorded = RootDiagnosticScope::new(&view, Some(&handle)).source_borrowed_error_with_facts_written(
&error, facts, code, RootRequestEvent::Ingress, Default::default());
assert!(recorded.is_ok());
assert_eq!(confirmed_ingress_status(&error, &recorded), 400);
let raw = std::fs::read_to_string(writer.target()).unwrap();
let rows: Vec<serde_json::Value> = raw.lines().map(|line| serde_json::from_str(line).unwrap()).collect();
let original: Vec<_> = rows.iter().filter(|row| row["event"] == "request_error_original").collect();
assert!(!original.is_empty());
let id = &original[0]["occurrence"]["diagnostic_id"];
assert!(original.iter().all(|row| &row["occurrence"]["diagnostic_id"] == id));
let contexts: Vec<_> = original.iter().filter(|row| row["channel"] == "context").collect();
assert_eq!(contexts.len(), 1);
assert_eq!(original.iter().filter(|row| row["channel"] == "terminal").count(), 1);
assert!(raw.contains("framework.ingress.invalid_json_envelope"));
assert!(raw.contains("INVALID_JSON_ENVELOPE"));
assert_eq!(format!("{error:?}"), before);
let (facts, code) = envelope_rejection_facts(&error).unwrap();
let missing = RootDiagnosticScope::new(&view, None).source_borrowed_error_with_facts_written(
&error, facts, code, RootRequestEvent::Ingress, Default::default());
assert!(missing.is_err());
assert_eq!(confirmed_ingress_status(&error, &missing), 503);
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(5);
while writer.shutdown() == saddle_observability::DiagnosticShutdown::Pending && std::time::Instant::now() < deadline {
std::thread::yield_now();
}
assert_eq!(writer.shutdown(), saddle_observability::DiagnosticShutdown::Finished);
println!("codec original={}", writer.target().display());
}