Add save-slice-backed runtime fixtures
This commit is contained in:
parent
09b6514dbf
commit
8ca65cbbfb
12 changed files with 974 additions and 47 deletions
|
|
@ -16,13 +16,15 @@ use rrt_model::{
|
|||
};
|
||||
use rrt_runtime::{
|
||||
CAMPAIGN_SCENARIO_COUNT, CampaignExeInspectionReport, OBSERVED_CAMPAIGN_SCENARIO_NAMES,
|
||||
Pk4ExtractionReport, Pk4InspectionReport, RuntimeSnapshotDocument, RuntimeSnapshotSource,
|
||||
RuntimeSummary, SNAPSHOT_FORMAT_VERSION, SmpClassicPackedProfileBlock, SmpInspectionReport,
|
||||
SmpLoadedSaveSlice, SmpRt3105PackedProfileBlock, SmpSaveLoadSummary, WinInspectionReport,
|
||||
execute_step_command, extract_pk4_entry_file, inspect_campaign_exe_file, inspect_pk4_file,
|
||||
inspect_smp_file, inspect_win_file, load_runtime_snapshot_document, load_runtime_state_import,
|
||||
load_save_slice_file, project_save_slice_to_runtime_state_import,
|
||||
save_runtime_snapshot_document, validate_runtime_snapshot_document,
|
||||
Pk4ExtractionReport, Pk4InspectionReport, RuntimeSaveSliceDocument,
|
||||
RuntimeSaveSliceDocumentSource, RuntimeSnapshotDocument, RuntimeSnapshotSource, RuntimeSummary,
|
||||
SAVE_SLICE_DOCUMENT_FORMAT_VERSION, SNAPSHOT_FORMAT_VERSION, SmpClassicPackedProfileBlock,
|
||||
SmpInspectionReport, SmpLoadedSaveSlice, SmpRt3105PackedProfileBlock, SmpSaveLoadSummary,
|
||||
WinInspectionReport, execute_step_command, extract_pk4_entry_file, inspect_campaign_exe_file,
|
||||
inspect_pk4_file, inspect_smp_file, inspect_win_file, load_runtime_snapshot_document,
|
||||
load_runtime_state_import, load_save_slice_file, project_save_slice_to_runtime_state_import,
|
||||
save_runtime_save_slice_document, save_runtime_snapshot_document,
|
||||
validate_runtime_snapshot_document,
|
||||
};
|
||||
use serde::Serialize;
|
||||
use serde_json::Value;
|
||||
|
|
@ -122,6 +124,10 @@ enum Command {
|
|||
smp_path: PathBuf,
|
||||
output_path: PathBuf,
|
||||
},
|
||||
RuntimeExportSaveSlice {
|
||||
smp_path: PathBuf,
|
||||
output_path: PathBuf,
|
||||
},
|
||||
RuntimeInspectPk4 {
|
||||
pk4_path: PathBuf,
|
||||
},
|
||||
|
|
@ -237,6 +243,13 @@ struct RuntimeLoadedSaveSliceOutput {
|
|||
save_slice: SmpLoadedSaveSlice,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
struct RuntimeSaveSliceExportOutput {
|
||||
path: String,
|
||||
output_path: String,
|
||||
save_slice_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
struct RuntimePk4InspectionOutput {
|
||||
path: String,
|
||||
|
|
@ -770,6 +783,12 @@ fn real_main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
} => {
|
||||
run_runtime_import_save_state(&smp_path, &output_path)?;
|
||||
}
|
||||
Command::RuntimeExportSaveSlice {
|
||||
smp_path,
|
||||
output_path,
|
||||
} => {
|
||||
run_runtime_export_save_slice(&smp_path, &output_path)?;
|
||||
}
|
||||
Command::RuntimeInspectPk4 { pk4_path } => {
|
||||
run_runtime_inspect_pk4(&pk4_path)?;
|
||||
}
|
||||
|
|
@ -929,6 +948,14 @@ fn parse_command() -> Result<Command, Box<dyn std::error::Error>> {
|
|||
output_path: PathBuf::from(output_path),
|
||||
})
|
||||
}
|
||||
[command, subcommand, smp_path, output_path]
|
||||
if command == "runtime" && subcommand == "export-save-slice" =>
|
||||
{
|
||||
Ok(Command::RuntimeExportSaveSlice {
|
||||
smp_path: PathBuf::from(smp_path),
|
||||
output_path: PathBuf::from(output_path),
|
||||
})
|
||||
}
|
||||
[command, subcommand, path] if command == "runtime" && subcommand == "inspect-pk4" => {
|
||||
Ok(Command::RuntimeInspectPk4 {
|
||||
pk4_path: PathBuf::from(path),
|
||||
|
|
@ -1069,7 +1096,7 @@ fn parse_command() -> Result<Command, Box<dyn std::error::Error>> {
|
|||
})
|
||||
}
|
||||
_ => Err(
|
||||
"usage: rrt-cli [validate [repo-root] | finance eval <snapshot.json> | finance diff <left.json> <right.json> | runtime validate-fixture <fixture.json> | runtime summarize-fixture <fixture.json> | runtime export-fixture-state <fixture.json> <snapshot.json> | runtime diff-state <left.json> <right.json> | runtime summarize-state <snapshot.json> | runtime import-state <input.json> <snapshot.json> | runtime inspect-smp <file.smp> | runtime summarize-save-load <file.smp> | runtime load-save-slice <file.smp> | runtime import-save-state <file.smp> <snapshot.json> | runtime inspect-pk4 <file.pk4> | runtime inspect-win <file.win> | runtime extract-pk4-entry <file.pk4> <entry-name> <output-path> | runtime inspect-campaign-exe <RT3.exe> | runtime compare-classic-profile <save1.gms> <save2.gms> [saveN.gms...] | runtime compare-105-profile <save1.gms> <save2.gms> [saveN.gms...] | runtime compare-candidate-table <file1> <file2> [fileN...] | runtime compare-recipe-book-lines <file1> <file2> [fileN...] | runtime compare-setup-payload-core <file1> <file2> [fileN...] | runtime compare-setup-launch-payload <file1> <file2> [fileN...] | runtime compare-post-special-conditions-scalars <file1> <file2> [fileN...] | runtime scan-candidate-table-headers <root-dir> | runtime scan-special-conditions <root-dir> | runtime scan-aligned-runtime-rule-band <root-dir> | runtime scan-post-special-conditions-scalars <root-dir> | runtime scan-post-special-conditions-tail <root-dir> | runtime scan-recipe-book-lines <root-dir> | runtime export-profile-block <save.gms> <profile.json>]"
|
||||
"usage: rrt-cli [validate [repo-root] | finance eval <snapshot.json> | finance diff <left.json> <right.json> | runtime validate-fixture <fixture.json> | runtime summarize-fixture <fixture.json> | runtime export-fixture-state <fixture.json> <snapshot.json> | runtime diff-state <left.json> <right.json> | runtime summarize-state <snapshot.json> | runtime import-state <input.json> <snapshot.json> | runtime inspect-smp <file.smp> | runtime summarize-save-load <file.smp> | runtime load-save-slice <file.smp> | runtime import-save-state <file.smp> <snapshot.json> | runtime export-save-slice <file.smp> <save-slice.json> | runtime inspect-pk4 <file.pk4> | runtime inspect-win <file.win> | runtime extract-pk4-entry <file.pk4> <entry-name> <output-path> | runtime inspect-campaign-exe <RT3.exe> | runtime compare-classic-profile <save1.gms> <save2.gms> [saveN.gms...] | runtime compare-105-profile <save1.gms> <save2.gms> [saveN.gms...] | runtime compare-candidate-table <file1> <file2> [fileN...] | runtime compare-recipe-book-lines <file1> <file2> [fileN...] | runtime compare-setup-payload-core <file1> <file2> [fileN...] | runtime compare-setup-launch-payload <file1> <file2> [fileN...] | runtime compare-post-special-conditions-scalars <file1> <file2> [fileN...] | runtime scan-candidate-table-headers <root-dir> | runtime scan-special-conditions <root-dir> | runtime scan-aligned-runtime-rule-band <root-dir> | runtime scan-post-special-conditions-scalars <root-dir> | runtime scan-post-special-conditions-tail <root-dir> | runtime scan-recipe-book-lines <root-dir> | runtime export-profile-block <save.gms> <profile.json>]"
|
||||
.into(),
|
||||
),
|
||||
}
|
||||
|
|
@ -1326,6 +1353,50 @@ fn run_runtime_import_save_state(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn run_runtime_export_save_slice(
|
||||
smp_path: &Path,
|
||||
output_path: &Path,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let save_slice = load_save_slice_file(smp_path)?;
|
||||
let report = export_runtime_save_slice_document(smp_path, output_path, save_slice)?;
|
||||
println!("{}", serde_json::to_string_pretty(&report)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn export_runtime_save_slice_document(
|
||||
smp_path: &Path,
|
||||
output_path: &Path,
|
||||
save_slice: SmpLoadedSaveSlice,
|
||||
) -> Result<RuntimeSaveSliceExportOutput, Box<dyn std::error::Error>> {
|
||||
let document = RuntimeSaveSliceDocument {
|
||||
format_version: SAVE_SLICE_DOCUMENT_FORMAT_VERSION,
|
||||
save_slice_id: smp_path
|
||||
.file_stem()
|
||||
.and_then(|stem| stem.to_str())
|
||||
.unwrap_or("save-slice")
|
||||
.to_string(),
|
||||
source: RuntimeSaveSliceDocumentSource {
|
||||
description: Some(format!(
|
||||
"Exported loaded save slice from {}",
|
||||
smp_path.display()
|
||||
)),
|
||||
original_save_filename: smp_path
|
||||
.file_name()
|
||||
.and_then(|name| name.to_str())
|
||||
.map(ToString::to_string),
|
||||
original_save_sha256: None,
|
||||
notes: vec![],
|
||||
},
|
||||
save_slice,
|
||||
};
|
||||
save_runtime_save_slice_document(output_path, &document)?;
|
||||
Ok(RuntimeSaveSliceExportOutput {
|
||||
path: smp_path.display().to_string(),
|
||||
output_path: output_path.display().to_string(),
|
||||
save_slice_id: document.save_slice_id,
|
||||
})
|
||||
}
|
||||
|
||||
fn run_runtime_inspect_pk4(pk4_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let report = RuntimePk4InspectionOutput {
|
||||
path: pk4_path.display().to_string(),
|
||||
|
|
@ -4272,6 +4343,59 @@ mod tests {
|
|||
.expect("snapshot-backed imported packed-event fixture should summarize");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn summarizes_save_slice_backed_fixtures() {
|
||||
let parity_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../../fixtures/runtime/packed-event-parity-save-slice-fixture.json");
|
||||
let selective_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../../fixtures/runtime/packed-event-selective-import-save-slice-fixture.json");
|
||||
|
||||
run_runtime_summarize_fixture(&parity_fixture)
|
||||
.expect("save-slice-backed parity fixture should summarize");
|
||||
run_runtime_summarize_fixture(&selective_fixture)
|
||||
.expect("save-slice-backed selective-import fixture should summarize");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exports_runtime_save_slice_document_from_loaded_slice() {
|
||||
let nonce = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.expect("system time should be after epoch")
|
||||
.as_nanos();
|
||||
let output_path =
|
||||
std::env::temp_dir().join(format!("rrt-export-save-slice-test-{nonce}.json"));
|
||||
let smp_path = PathBuf::from("captured-test.gms");
|
||||
|
||||
let report = export_runtime_save_slice_document(
|
||||
&smp_path,
|
||||
&output_path,
|
||||
SmpLoadedSaveSlice {
|
||||
file_extension_hint: Some("gms".to_string()),
|
||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||
mechanism_family: "classic-save-rehydrate-v1".to_string(),
|
||||
mechanism_confidence: "grounded".to_string(),
|
||||
trailer_family: None,
|
||||
bridge_family: None,
|
||||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: None,
|
||||
notes: vec!["exported for test".to_string()],
|
||||
},
|
||||
)
|
||||
.expect("save slice export should succeed");
|
||||
|
||||
assert_eq!(report.save_slice_id, "captured-test");
|
||||
let document = rrt_runtime::load_runtime_save_slice_document(&output_path)
|
||||
.expect("exported save slice document should load");
|
||||
assert_eq!(document.save_slice_id, "captured-test");
|
||||
assert_eq!(
|
||||
document.source.original_save_filename.as_deref(),
|
||||
Some("captured-test.gms")
|
||||
);
|
||||
let _ = fs::remove_file(output_path);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diffs_runtime_states_with_packed_record_and_runtime_record_import_changes() {
|
||||
let left = serde_json::json!({
|
||||
|
|
@ -4412,6 +4536,25 @@ mod tests {
|
|||
let _ = fs::remove_file(right_path);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diffs_save_slice_backed_states_across_packed_event_boundaries() {
|
||||
let left_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../../fixtures/runtime/packed-event-parity-save-slice.json");
|
||||
let right_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../../fixtures/runtime/packed-event-selective-import-save-slice.json");
|
||||
|
||||
let left_state = load_normalized_runtime_state(&left_path)
|
||||
.expect("left save-slice-backed state should load");
|
||||
let right_state = load_normalized_runtime_state(&right_path)
|
||||
.expect("right save-slice-backed state should load");
|
||||
let differences = diff_json_values(&left_state, &right_state);
|
||||
|
||||
assert!(differences.iter().any(|entry| {
|
||||
entry.path == "$.packed_event_collection.imported_runtime_record_count"
|
||||
|| entry.path == "$.packed_event_collection.records[0].decode_status"
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diffs_classic_profile_samples_across_multiple_files() {
|
||||
let sample_a = RuntimeClassicProfileSample {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue