test(inspection): cover archive diagnostic span context

This commit is contained in:
2026-06-30 02:47:24 +04:00
parent c0116d32be
commit c7a9c43b5b
2 changed files with 19 additions and 5 deletions
+18 -4
View File
@@ -21,7 +21,7 @@
//! Shared inspection helpers for format-backed tooling. //! Shared inspection helpers for format-backed tooling.
use fparkan_diagnostics::{ use fparkan_diagnostics::{
diagnostic, render_human, Diagnostic, DiagnosticCode, DiagnosticContext, Phase, diagnostic, render_human, Diagnostic, DiagnosticCode, DiagnosticContext, Phase, SourceSpan,
}; };
use fparkan_msh::{decode_msh, validate_msh, ModelAsset}; use fparkan_msh::{decode_msh, validate_msh, ModelAsset};
use fparkan_nres::{decode as decode_nres, NresDocument, ReadProfile}; use fparkan_nres::{decode as decode_nres, NresDocument, ReadProfile};
@@ -215,7 +215,7 @@ fn inspect_archive_bytes(
Arc::from(bytes.to_vec().into_boxed_slice()), Arc::from(bytes.to_vec().into_boxed_slice()),
ReadProfile::Compatible, ReadProfile::Compatible,
) )
.map_err(|err| archive_parse_diagnostic("S1.NRES.DECODE", source, err.to_string()))?; .map_err(|err| archive_parse_diagnostic("S1.NRES.DECODE", source, bytes, err.to_string()))?;
let mut sample = Vec::new(); let mut sample = Vec::new();
for entry in document.entries().iter().take(sample_limit) { for entry in document.entries().iter().take(sample_limit) {
sample.push(NresEntrySummary { sample.push(NresEntrySummary {
@@ -234,7 +234,7 @@ fn inspect_archive_bytes(
Arc::from(bytes.to_vec().into_boxed_slice()), Arc::from(bytes.to_vec().into_boxed_slice()),
fparkan_rsli::ReadProfile::Compatible, fparkan_rsli::ReadProfile::Compatible,
) )
.map_err(|err| archive_parse_diagnostic("S1.RSLI.DECODE", source, err.to_string()))?; .map_err(|err| archive_parse_diagnostic("S1.RSLI.DECODE", source, bytes, err.to_string()))?;
Ok(ArchiveInspection::Rsli { Ok(ArchiveInspection::Rsli {
entries: document.entries().len(), entries: document.entries().len(),
}) })
@@ -242,6 +242,7 @@ fn inspect_archive_bytes(
Err(archive_parse_diagnostic( Err(archive_parse_diagnostic(
"S1.RESOURCE.UNSUPPORTED_ARCHIVE", "S1.RESOURCE.UNSUPPORTED_ARCHIVE",
source, source,
bytes,
"unsupported archive magic".to_string(), "unsupported archive magic".to_string(),
)) ))
} }
@@ -386,11 +387,16 @@ fn load_model_document_from_root(
fn archive_parse_diagnostic( fn archive_parse_diagnostic(
code: &'static str, code: &'static str,
source: Option<&Path>, source: Option<&Path>,
bytes: &[u8],
message: String, message: String,
) -> Diagnostic { ) -> Diagnostic {
diagnostic(DiagnosticCode(code), message).with_context(DiagnosticContext { diagnostic(DiagnosticCode(code), message).with_context(DiagnosticContext {
phase: Some(Phase::Parse), phase: Some(Phase::Parse),
path: source.map(|path| path.display().to_string()), path: source.map(|path| path.display().to_string()),
span: Some(SourceSpan {
offset: 0,
length: u64::try_from(bytes.len().min(4)).unwrap_or(4),
}),
..DiagnosticContext::default() ..DiagnosticContext::default()
}) })
} }
@@ -414,7 +420,7 @@ mod tests {
} }
#[test] #[test]
fn archive_diagnostic_preserves_source_path() { fn archive_diagnostic_preserves_source_path_phase_and_span() {
let dir = temp_dir("inspect-diagnostic"); let dir = temp_dir("inspect-diagnostic");
let path = dir.join("broken.nres"); let path = dir.join("broken.nres");
fs::write(&path, b"NRes").expect("broken nres"); fs::write(&path, b"NRes").expect("broken nres");
@@ -428,6 +434,14 @@ mod tests {
diagnostic.context.path.as_deref(), diagnostic.context.path.as_deref(),
Some(expected_path.as_str()) Some(expected_path.as_str())
); );
assert_eq!(diagnostic.context.phase, Some(Phase::Parse));
assert_eq!(
diagnostic.context.span,
Some(SourceSpan {
offset: 0,
length: 4
})
);
} }
#[test] #[test]
+1 -1
View File
@@ -154,7 +154,7 @@ S1-RES-004 covered cargo test -p fparkan-resource --offline entry_read_error_car
S1-RES-005 covered cargo test -p fparkan-resource --offline archive_cache_evicts_by_byte_budget S1-RES-005 covered cargo test -p fparkan-resource --offline archive_cache_evicts_by_byte_budget
S1-RES-006 covered cargo test -p fparkan-resource --offline archive_cache_eviction_makes_old_handles_stale S1-RES-006 covered cargo test -p fparkan-resource --offline archive_cache_eviction_makes_old_handles_stale
S1-RES-007 covered cargo test -p fparkan-resource --offline lossy_equivalent_archive_paths_remain_distinct S1-RES-007 covered cargo test -p fparkan-resource --offline lossy_equivalent_archive_paths_remain_distinct
S1-DIAG-001 partial cargo test -p fparkan-inspection --offline archive_diagnostic_preserves_source_path; entry/span coverage is still missing S1-DIAG-001 partial cargo test -p fparkan-inspection --offline archive_diagnostic_preserves_source_path_phase_and_span; archive_entry coverage is still missing
S1-VFS-001 covered cargo test -p fparkan-vfs --offline memory_vfs_uses_exact_lookup S1-VFS-001 covered cargo test -p fparkan-vfs --offline memory_vfs_uses_exact_lookup
S1-VFS-002 covered cargo test -p fparkan-vfs --offline overlay_vfs_uses_first_matching_layer S1-VFS-002 covered cargo test -p fparkan-vfs --offline overlay_vfs_uses_first_matching_layer
S1-VFS-003 covered cargo test -p fparkan-vfs --offline directory_vfs_resolves_ascii_casefolded_segments S1-VFS-003 covered cargo test -p fparkan-vfs --offline directory_vfs_resolves_ascii_casefolded_segments
1 # Acceptance coverage manifest.
154 S1-RES-005
155 S1-RES-006
156 S1-RES-007
157 S1-DIAG-001
158 S1-VFS-001
159 S1-VFS-002
160 S1-VFS-003