139 lines
4.5 KiB
Rust
139 lines
4.5 KiB
Rust
use std::fs;
|
|
|
|
use serde::Deserialize;
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct SceneLedgerSnapshot {
|
|
#[serde(rename = "snapshotDate")]
|
|
snapshot_date: String,
|
|
#[serde(rename = "sourceWorkbook")]
|
|
source_workbook: String,
|
|
#[serde(rename = "generatedAt")]
|
|
generated_at: String,
|
|
summary: LedgerSummary,
|
|
#[serde(rename = "groupingResultCounts")]
|
|
grouping_result_counts: std::collections::BTreeMap<String, u32>,
|
|
#[serde(rename = "familyJudgementCounts")]
|
|
family_judgement_counts: std::collections::BTreeMap<String, u32>,
|
|
#[serde(rename = "validatedEntries")]
|
|
validated_entries: Vec<ValidatedEntry>,
|
|
#[serde(rename = "alignmentNotes")]
|
|
alignment_notes: Vec<String>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct LedgerSummary {
|
|
#[serde(rename = "totalScenes")]
|
|
total_scenes: u32,
|
|
#[serde(rename = "validatedScenes")]
|
|
validated_scenes: u32,
|
|
#[serde(rename = "notYetValidatedScenes")]
|
|
not_yet_validated_scenes: u32,
|
|
#[serde(rename = "passedRealSample")]
|
|
passed_real_sample: u32,
|
|
#[serde(rename = "failedRealSample")]
|
|
failed_real_sample: u32,
|
|
#[serde(rename = "failClosedScenes")]
|
|
fail_closed_scenes: u32,
|
|
#[serde(rename = "reassignedBoundaryScenes")]
|
|
reassigned_boundary_scenes: u32,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct ValidatedEntry {
|
|
#[serde(rename = "sceneName")]
|
|
scene_name: String,
|
|
#[serde(rename = "targetFamily")]
|
|
target_family: String,
|
|
#[serde(rename = "groupingResult")]
|
|
grouping_result: String,
|
|
#[serde(rename = "validationStatus")]
|
|
validation_status: String,
|
|
#[serde(rename = "validationResult")]
|
|
validation_result: String,
|
|
}
|
|
|
|
#[test]
|
|
fn scene_ledger_snapshot_is_actionable() {
|
|
let snapshot = load_snapshot();
|
|
|
|
assert_eq!(snapshot.snapshot_date, "2026-04-18");
|
|
assert!(snapshot.source_workbook.ends_with(".xlsx"));
|
|
assert_eq!(snapshot.generated_at, "2026-04-18 16:48:05");
|
|
assert_eq!(snapshot.summary.total_scenes, 102);
|
|
assert_eq!(
|
|
snapshot.summary.validated_scenes + snapshot.summary.not_yet_validated_scenes,
|
|
snapshot.summary.total_scenes
|
|
);
|
|
assert_eq!(snapshot.summary.passed_real_sample, 1);
|
|
assert_eq!(snapshot.summary.failed_real_sample, 3);
|
|
assert_eq!(snapshot.summary.fail_closed_scenes, 2);
|
|
assert_eq!(snapshot.summary.reassigned_boundary_scenes, 3);
|
|
assert_eq!(
|
|
snapshot.validated_entries.len() as u32,
|
|
snapshot.summary.validated_scenes
|
|
);
|
|
assert!(snapshot
|
|
.grouping_result_counts
|
|
.contains_key("95598/工单家族候选"));
|
|
assert!(snapshot.family_judgement_counts.contains_key("待分组"));
|
|
assert!(!snapshot.alignment_notes.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn scene_ledger_snapshot_matches_current_family_asset_baseline() {
|
|
let snapshot = load_snapshot();
|
|
|
|
let has_g1e_pass = snapshot.validated_entries.iter().any(|item| {
|
|
item.scene_name == "高低压新增报装容量月度统计表"
|
|
&& item.target_family == "G1-E"
|
|
&& item.validation_result == "通过"
|
|
});
|
|
assert!(has_g1e_pass);
|
|
|
|
let has_g6_boundary = snapshot.validated_entries.iter().any(|item| {
|
|
item.scene_name == "电能表现场检验完成率指标报表"
|
|
&& item.target_family == "G6"
|
|
&& item.validation_result == "已重分组"
|
|
});
|
|
assert!(has_g6_boundary);
|
|
|
|
let has_g7_boundary = snapshot.validated_entries.iter().any(|item| {
|
|
item.scene_name == "计量资产库存统计"
|
|
&& item.target_family == "G7"
|
|
&& item.validation_result == "已重分组"
|
|
});
|
|
assert!(has_g7_boundary);
|
|
|
|
let has_g8_boundary = snapshot.validated_entries.iter().any(|item| {
|
|
item.scene_name == "95598供电服务月报"
|
|
&& item.target_family == "G8"
|
|
&& item.validation_result == "已重分组"
|
|
});
|
|
assert!(has_g8_boundary);
|
|
|
|
let g2_validated = snapshot
|
|
.validated_entries
|
|
.iter()
|
|
.filter(|item| item.target_family == "G2")
|
|
.count();
|
|
assert_eq!(g2_validated, 3);
|
|
|
|
let g1e_fail_closed = snapshot
|
|
.validated_entries
|
|
.iter()
|
|
.filter(|item| {
|
|
item.target_family.contains("G1-E") && item.validation_result == "Fail-closed"
|
|
})
|
|
.count();
|
|
assert_eq!(g1e_fail_closed, 2);
|
|
}
|
|
|
|
fn load_snapshot() -> SceneLedgerSnapshot {
|
|
serde_json::from_str(
|
|
&fs::read_to_string("tests/fixtures/generated_scene/scene_ledger_snapshot_2026-04-18.json")
|
|
.unwrap(),
|
|
)
|
|
.unwrap()
|
|
}
|