mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-07-22 01:46:44 +08:00
@@ -1,7 +1,7 @@
|
|||||||
use bat_adapters::official::yostar_jp::PatchPlatform;
|
use bat_adapters::official::yostar_jp::PatchPlatform;
|
||||||
use bat_infrastructure::{
|
use bat_infrastructure::{
|
||||||
OfficialServerInfoSource, OfficialUpdateConfig, OfficialUpdateProgress, OfficialUpdateReport,
|
OfficialServerInfoSource, OfficialUpdateConfig, OfficialUpdateProgress, OfficialUpdateReport,
|
||||||
OfficialUpdateService, OfficialUpdateStatus,
|
OfficialUpdateService, OfficialUpdateStatus, OfficialVerificationSummary,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::env;
|
use std::env;
|
||||||
@@ -1523,6 +1523,32 @@ fn print_list(label: &str, values: &[String], limit: usize) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_verification_summary(summary: &OfficialVerificationSummary) {
|
||||||
|
println!(" 校验摘要:");
|
||||||
|
for line in verification_summary_lines(summary) {
|
||||||
|
println!(" - {line}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn verification_summary_lines(summary: &OfficialVerificationSummary) -> Vec<String> {
|
||||||
|
vec![
|
||||||
|
format!(
|
||||||
|
"官方 .hash 强校验: {} 对 ({})",
|
||||||
|
summary.official_hash_verified_count, summary.official_hash_scope
|
||||||
|
),
|
||||||
|
format!(
|
||||||
|
"本地 BLAKE3 复用校验: {} 项通过, {} 项需修复 ({})",
|
||||||
|
summary.local_manifest_blake3_verified_count,
|
||||||
|
summary.local_manifest_repair_needed_count,
|
||||||
|
summary.local_manifest_blake3_scope
|
||||||
|
),
|
||||||
|
format!(
|
||||||
|
"ZIP 结构校验: {} 个 ZIP 通过 ({})",
|
||||||
|
summary.zip_structure_verified_count, summary.zip_structure_scope
|
||||||
|
),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
fn format_bool(value: bool) -> &'static str {
|
fn format_bool(value: bool) -> &'static str {
|
||||||
if value {
|
if value {
|
||||||
"yes"
|
"yes"
|
||||||
@@ -1590,6 +1616,7 @@ impl HumanReport for OfficialUpdateReport {
|
|||||||
print_field("本地校验通过", self.local_manifest_verified_count);
|
print_field("本地校验通过", self.local_manifest_verified_count);
|
||||||
print_field("需修复", self.local_manifest_repair_needed_count);
|
print_field("需修复", self.local_manifest_repair_needed_count);
|
||||||
print_field("官方 hash 校验", self.official_seed_hash_verified_count);
|
print_field("官方 hash 校验", self.official_seed_hash_verified_count);
|
||||||
|
print_verification_summary(&self.verification_summary);
|
||||||
print_field("catalog marker", self.addressables_marker_checked_count);
|
print_field("catalog marker", self.addressables_marker_checked_count);
|
||||||
print_list("变更 endpoint", &self.changed_endpoint_urls, 8);
|
print_list("变更 endpoint", &self.changed_endpoint_urls, 8);
|
||||||
print_list("计划 URL", &self.download_urls, 8);
|
print_list("计划 URL", &self.download_urls, 8);
|
||||||
@@ -1684,6 +1711,7 @@ impl HumanReport for VerifyCommandReport {
|
|||||||
print_field("本地失败数", self.local_manifest_failure_count);
|
print_field("本地失败数", self.local_manifest_failure_count);
|
||||||
print_field("官方 hash 对", self.official_hash_pair_count);
|
print_field("官方 hash 对", self.official_hash_pair_count);
|
||||||
print_field("官方 hash 通过", self.official_hash_verified_count);
|
print_field("官方 hash 通过", self.official_hash_verified_count);
|
||||||
|
print_verification_summary(&self.verification_summary);
|
||||||
if !self.official_hash_errors.is_empty() {
|
if !self.official_hash_errors.is_empty() {
|
||||||
print_list("官方 hash 错误", &self.official_hash_errors, 8);
|
print_list("官方 hash 错误", &self.official_hash_errors, 8);
|
||||||
}
|
}
|
||||||
@@ -1798,6 +1826,7 @@ struct VerifyCommandReport {
|
|||||||
local_manifest_failure_count: usize,
|
local_manifest_failure_count: usize,
|
||||||
official_hash_pair_count: usize,
|
official_hash_pair_count: usize,
|
||||||
official_hash_verified_count: usize,
|
official_hash_verified_count: usize,
|
||||||
|
verification_summary: OfficialVerificationSummary,
|
||||||
official_hash_errors: Vec<String>,
|
official_hash_errors: Vec<String>,
|
||||||
failures: Vec<VerificationItemReport>,
|
failures: Vec<VerificationItemReport>,
|
||||||
}
|
}
|
||||||
@@ -1837,6 +1866,12 @@ fn run_verify_command(options: &CliOptions) -> anyhow::Result<bool> {
|
|||||||
let healthy = update_report.update_status == OfficialUpdateStatus::UpToDate
|
let healthy = update_report.update_status == OfficialUpdateStatus::UpToDate
|
||||||
&& update_report.local_manifest_repair_needed_count == 0
|
&& update_report.local_manifest_repair_needed_count == 0
|
||||||
&& verification.is_clean();
|
&& verification.is_clean();
|
||||||
|
let verification_summary = OfficialVerificationSummary::new(
|
||||||
|
verification.manifest_blake3_verified_count(),
|
||||||
|
verification.failure_count(),
|
||||||
|
verification.official_hash_verified_count,
|
||||||
|
verification.zip_structure_verified_count(),
|
||||||
|
);
|
||||||
let report = VerifyCommandReport {
|
let report = VerifyCommandReport {
|
||||||
command: "verify",
|
command: "verify",
|
||||||
status: if healthy { "verified" } else { "failed" },
|
status: if healthy { "verified" } else { "failed" },
|
||||||
@@ -1854,6 +1889,7 @@ fn run_verify_command(options: &CliOptions) -> anyhow::Result<bool> {
|
|||||||
local_manifest_failure_count: verification.failure_count(),
|
local_manifest_failure_count: verification.failure_count(),
|
||||||
official_hash_pair_count: verification.official_hash_pair_count,
|
official_hash_pair_count: verification.official_hash_pair_count,
|
||||||
official_hash_verified_count: verification.official_hash_verified_count,
|
official_hash_verified_count: verification.official_hash_verified_count,
|
||||||
|
verification_summary,
|
||||||
official_hash_errors: verification.official_hash_errors,
|
official_hash_errors: verification.official_hash_errors,
|
||||||
failures,
|
failures,
|
||||||
};
|
};
|
||||||
@@ -3384,6 +3420,26 @@ mod tests {
|
|||||||
assert!(STARTUP_BANNER.contains("BlueArchiveToolkit"));
|
assert!(STARTUP_BANNER.contains("BlueArchiveToolkit"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn verification_summary_output_names_all_validation_types() {
|
||||||
|
let summary = OfficialVerificationSummary::new(7, 1, 2, 3);
|
||||||
|
let lines = verification_summary_lines(&summary);
|
||||||
|
|
||||||
|
assert_eq!(lines.len(), 3);
|
||||||
|
assert!(lines[0].contains("官方 .hash 强校验"));
|
||||||
|
assert!(lines[0].contains("xxHash32"));
|
||||||
|
assert!(lines[1].contains("本地 BLAKE3 复用校验"));
|
||||||
|
assert!(lines[1].contains("需修复"));
|
||||||
|
assert!(lines[2].contains("ZIP 结构校验"));
|
||||||
|
assert!(lines[2].contains("central directory"));
|
||||||
|
|
||||||
|
let json = serde_json::to_value(&summary).unwrap();
|
||||||
|
assert_eq!(json["official_hash_verified_count"], 2);
|
||||||
|
assert_eq!(json["local_manifest_blake3_verified_count"], 7);
|
||||||
|
assert_eq!(json["local_manifest_repair_needed_count"], 1);
|
||||||
|
assert_eq!(json["zip_structure_verified_count"], 3);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn daemon_socket_path_uses_state_dir() {
|
fn daemon_socket_path_uses_state_dir() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ pub use official_update::{
|
|||||||
GameMainConfigSnapshot, LauncherMetadataSnapshot, OfficialBootstrapCache,
|
GameMainConfigSnapshot, LauncherMetadataSnapshot, OfficialBootstrapCache,
|
||||||
OfficialEndpointMarkerRole, OfficialEndpointMarkerSnapshot, OfficialServerInfoSource,
|
OfficialEndpointMarkerRole, OfficialEndpointMarkerSnapshot, OfficialServerInfoSource,
|
||||||
OfficialUpdateConfig, OfficialUpdateProgress, OfficialUpdateReport, OfficialUpdateService,
|
OfficialUpdateConfig, OfficialUpdateProgress, OfficialUpdateReport, OfficialUpdateService,
|
||||||
OfficialUpdateSnapshot, OfficialUpdateStatus, ResolvedBootstrap,
|
OfficialUpdateSnapshot, OfficialUpdateStatus, OfficialVerificationSummary, ResolvedBootstrap,
|
||||||
};
|
};
|
||||||
pub use resources::{InMemoryResourceRepository, SqliteResourceRepository};
|
pub use resources::{InMemoryResourceRepository, SqliteResourceRepository};
|
||||||
|
|
||||||
|
|||||||
@@ -270,6 +270,8 @@ pub struct OfficialLocalManifestAuditItem {
|
|||||||
/// ZIP structure validation error, when the URL or destination is a ZIP
|
/// ZIP structure validation error, when the URL or destination is a ZIP
|
||||||
/// and the local file did not pass ZIP structure validation.
|
/// and the local file did not pass ZIP structure validation.
|
||||||
pub zip_error: Option<String>,
|
pub zip_error: Option<String>,
|
||||||
|
/// Whether this item required and passed ZIP structure validation.
|
||||||
|
pub zip_structure_verified: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Local download-manifest audit result for a pull plan.
|
/// Local download-manifest audit result for a pull plan.
|
||||||
@@ -297,6 +299,23 @@ impl OfficialLocalManifestAuditReport {
|
|||||||
pub fn repair_needed_count(&self) -> usize {
|
pub fn repair_needed_count(&self) -> usize {
|
||||||
self.items.len().saturating_sub(self.verified_count())
|
self.items.len().saturating_sub(self.verified_count())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the number of files that passed local manifest path, size, and
|
||||||
|
/// BLAKE3 validation.
|
||||||
|
pub fn manifest_blake3_verified_count(&self) -> usize {
|
||||||
|
self.items
|
||||||
|
.iter()
|
||||||
|
.filter(|item| item.status.is_verified())
|
||||||
|
.count()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the number of ZIP files that passed structural validation.
|
||||||
|
pub fn zip_structure_verified_count(&self) -> usize {
|
||||||
|
self.items
|
||||||
|
.iter()
|
||||||
|
.filter(|item| item.zip_structure_verified)
|
||||||
|
.count()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Full local verification report for all entries currently recorded in the
|
/// Full local verification report for all entries currently recorded in the
|
||||||
@@ -334,6 +353,23 @@ impl OfficialLocalVerificationReport {
|
|||||||
pub fn failure_count(&self) -> usize {
|
pub fn failure_count(&self) -> usize {
|
||||||
self.items.len().saturating_sub(self.verified_count())
|
self.items.len().saturating_sub(self.verified_count())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the number of local manifest entries that passed path, size,
|
||||||
|
/// and BLAKE3 validation.
|
||||||
|
pub fn manifest_blake3_verified_count(&self) -> usize {
|
||||||
|
self.items
|
||||||
|
.iter()
|
||||||
|
.filter(|item| item.status.is_verified())
|
||||||
|
.count()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the number of ZIP files that passed structural validation.
|
||||||
|
pub fn zip_structure_verified_count(&self) -> usize {
|
||||||
|
self.items
|
||||||
|
.iter()
|
||||||
|
.filter(|item| item.zip_structure_verified)
|
||||||
|
.count()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Existing local state for an official pull plan.
|
/// Existing local state for an official pull plan.
|
||||||
@@ -1018,6 +1054,7 @@ impl OfficialResourcePullService {
|
|||||||
expected_blake3: None,
|
expected_blake3: None,
|
||||||
actual_blake3: None,
|
actual_blake3: None,
|
||||||
zip_error: None,
|
zip_error: None,
|
||||||
|
zip_structure_verified: false,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1036,6 +1073,7 @@ impl OfficialResourcePullService {
|
|||||||
expected_blake3,
|
expected_blake3,
|
||||||
actual_blake3: None,
|
actual_blake3: None,
|
||||||
zip_error: None,
|
zip_error: None,
|
||||||
|
zip_structure_verified: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1051,6 +1089,7 @@ impl OfficialResourcePullService {
|
|||||||
expected_blake3,
|
expected_blake3,
|
||||||
actual_blake3: None,
|
actual_blake3: None,
|
||||||
zip_error: None,
|
zip_error: None,
|
||||||
|
zip_structure_verified: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1065,6 +1104,7 @@ impl OfficialResourcePullService {
|
|||||||
expected_blake3,
|
expected_blake3,
|
||||||
actual_blake3: None,
|
actual_blake3: None,
|
||||||
zip_error: None,
|
zip_error: None,
|
||||||
|
zip_structure_verified: false,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1079,6 +1119,7 @@ impl OfficialResourcePullService {
|
|||||||
expected_blake3,
|
expected_blake3,
|
||||||
actual_blake3: None,
|
actual_blake3: None,
|
||||||
zip_error: None,
|
zip_error: None,
|
||||||
|
zip_structure_verified: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1094,9 +1135,12 @@ impl OfficialResourcePullService {
|
|||||||
expected_blake3,
|
expected_blake3,
|
||||||
actual_blake3: Some(actual_blake3),
|
actual_blake3: Some(actual_blake3),
|
||||||
zip_error: None,
|
zip_error: None,
|
||||||
|
zip_structure_verified: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let zip_structure_required =
|
||||||
|
url_or_path_has_zip_extension(url) || path_has_zip_extension(&destination);
|
||||||
if let Err(error) = self.validate_zip_if_needed(url, &destination) {
|
if let Err(error) = self.validate_zip_if_needed(url, &destination) {
|
||||||
return Ok(OfficialLocalManifestAuditItem {
|
return Ok(OfficialLocalManifestAuditItem {
|
||||||
url: url.to_string(),
|
url: url.to_string(),
|
||||||
@@ -1108,6 +1152,7 @@ impl OfficialResourcePullService {
|
|||||||
expected_blake3,
|
expected_blake3,
|
||||||
actual_blake3: Some(actual_blake3),
|
actual_blake3: Some(actual_blake3),
|
||||||
zip_error: Some(error),
|
zip_error: Some(error),
|
||||||
|
zip_structure_verified: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1121,6 +1166,7 @@ impl OfficialResourcePullService {
|
|||||||
expected_blake3,
|
expected_blake3,
|
||||||
actual_blake3: Some(actual_blake3),
|
actual_blake3: Some(actual_blake3),
|
||||||
zip_error: None,
|
zip_error: None,
|
||||||
|
zip_structure_verified: zip_structure_required,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1841,6 +1887,8 @@ fi
|
|||||||
let clean_audit = service.audit_local_manifest(&plan).unwrap();
|
let clean_audit = service.audit_local_manifest(&plan).unwrap();
|
||||||
assert!(clean_audit.is_clean());
|
assert!(clean_audit.is_clean());
|
||||||
assert_eq!(clean_audit.verified_count(), first_report.items.len());
|
assert_eq!(clean_audit.verified_count(), first_report.items.len());
|
||||||
|
assert_eq!(clean_audit.manifest_blake3_verified_count(), 7);
|
||||||
|
assert_eq!(clean_audit.zip_structure_verified_count(), 4);
|
||||||
|
|
||||||
let corrupted = first_report
|
let corrupted = first_report
|
||||||
.items
|
.items
|
||||||
@@ -1879,6 +1927,8 @@ fi
|
|||||||
assert!(verification.is_clean());
|
assert!(verification.is_clean());
|
||||||
assert_eq!(verification.items.len(), 7);
|
assert_eq!(verification.items.len(), 7);
|
||||||
assert_eq!(verification.verified_count(), 7);
|
assert_eq!(verification.verified_count(), 7);
|
||||||
|
assert_eq!(verification.manifest_blake3_verified_count(), 7);
|
||||||
|
assert_eq!(verification.zip_structure_verified_count(), 4);
|
||||||
assert_eq!(verification.official_hash_pair_count, 1);
|
assert_eq!(verification.official_hash_pair_count, 1);
|
||||||
assert_eq!(verification.official_hash_verified_count, 1);
|
assert_eq!(verification.official_hash_verified_count, 1);
|
||||||
|
|
||||||
|
|||||||
@@ -314,6 +314,50 @@ impl ExtendedSnapshotDelta {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Structured verification summary for CLI and JSON reports.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct OfficialVerificationSummary {
|
||||||
|
/// Number of resources verified by the local download manifest's path,
|
||||||
|
/// byte size, and BLAKE3 digest.
|
||||||
|
pub local_manifest_blake3_verified_count: usize,
|
||||||
|
/// Number of resources that still need local repair after manifest audit.
|
||||||
|
pub local_manifest_repair_needed_count: usize,
|
||||||
|
/// Human-facing description of the local manifest validation boundary.
|
||||||
|
pub local_manifest_blake3_scope: String,
|
||||||
|
/// Number of official seed `.bytes`/`.hash` pairs verified by the official
|
||||||
|
/// decimal xxHash32 rule.
|
||||||
|
pub official_hash_verified_count: usize,
|
||||||
|
/// Human-facing description of the official hash validation boundary.
|
||||||
|
pub official_hash_scope: String,
|
||||||
|
/// Number of ZIP files that passed structural validation.
|
||||||
|
pub zip_structure_verified_count: usize,
|
||||||
|
/// Human-facing description of the ZIP structure validation boundary.
|
||||||
|
pub zip_structure_scope: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OfficialVerificationSummary {
|
||||||
|
/// Creates a verification summary from validation counters.
|
||||||
|
pub fn new(
|
||||||
|
local_manifest_blake3_verified_count: usize,
|
||||||
|
local_manifest_repair_needed_count: usize,
|
||||||
|
official_hash_verified_count: usize,
|
||||||
|
zip_structure_verified_count: usize,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
local_manifest_blake3_verified_count,
|
||||||
|
local_manifest_repair_needed_count,
|
||||||
|
local_manifest_blake3_scope:
|
||||||
|
"本地 download manifest 的 URL/path、size 和 BLAKE3 复用校验".to_string(),
|
||||||
|
official_hash_verified_count,
|
||||||
|
official_hash_scope: "官方 seed .bytes/.hash 对,按官方十进制 xxHash32(seed=0) 强校验"
|
||||||
|
.to_string(),
|
||||||
|
zip_structure_verified_count,
|
||||||
|
zip_structure_scope:
|
||||||
|
"所有 .zip 文件的 EOCD、central directory、local header 和边界结构校验".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Structured report returned by an official update run.
|
/// Structured report returned by an official update run.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct OfficialUpdateReport {
|
pub struct OfficialUpdateReport {
|
||||||
@@ -381,6 +425,8 @@ pub struct OfficialUpdateReport {
|
|||||||
pub transferred_bytes: u64,
|
pub transferred_bytes: u64,
|
||||||
/// Number of official seed hashes verified.
|
/// Number of official seed hashes verified.
|
||||||
pub official_seed_hash_verified_count: usize,
|
pub official_seed_hash_verified_count: usize,
|
||||||
|
/// Verification summary with explicit boundaries for each validation type.
|
||||||
|
pub verification_summary: OfficialVerificationSummary,
|
||||||
/// Download manifest path.
|
/// Download manifest path.
|
||||||
pub download_manifest: PathBuf,
|
pub download_manifest: PathBuf,
|
||||||
/// Snapshot path written after success.
|
/// Snapshot path written after success.
|
||||||
@@ -683,6 +729,14 @@ impl OfficialUpdateService {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|audit| audit.repair_needed_count())
|
.map(|audit| audit.repair_needed_count())
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
let local_manifest_blake3_verified_count = local_audit
|
||||||
|
.as_ref()
|
||||||
|
.map(|audit| audit.manifest_blake3_verified_count())
|
||||||
|
.unwrap_or(0);
|
||||||
|
let local_zip_structure_verified_count = local_audit
|
||||||
|
.as_ref()
|
||||||
|
.map(|audit| audit.zip_structure_verified_count())
|
||||||
|
.unwrap_or(0);
|
||||||
let repair_needed = config.repair
|
let repair_needed = config.repair
|
||||||
&& local_audit
|
&& local_audit
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -743,6 +797,12 @@ impl OfficialUpdateService {
|
|||||||
final_bytes: 0,
|
final_bytes: 0,
|
||||||
transferred_bytes: 0,
|
transferred_bytes: 0,
|
||||||
official_seed_hash_verified_count: 0,
|
official_seed_hash_verified_count: 0,
|
||||||
|
verification_summary: OfficialVerificationSummary::new(
|
||||||
|
local_manifest_blake3_verified_count,
|
||||||
|
local_manifest_repair_needed_count,
|
||||||
|
0,
|
||||||
|
local_zip_structure_verified_count,
|
||||||
|
),
|
||||||
download_manifest: fetcher.download_manifest_path(),
|
download_manifest: fetcher.download_manifest_path(),
|
||||||
snapshot_written: None,
|
snapshot_written: None,
|
||||||
};
|
};
|
||||||
@@ -830,6 +890,12 @@ impl OfficialUpdateService {
|
|||||||
report.official_seed_hash_verified_count = pull_report.official_hash_verified_count();
|
report.official_seed_hash_verified_count = pull_report.official_hash_verified_count();
|
||||||
report.local_manifest_verified_count = final_audit.verified_count();
|
report.local_manifest_verified_count = final_audit.verified_count();
|
||||||
report.local_manifest_repair_needed_count = final_audit.repair_needed_count();
|
report.local_manifest_repair_needed_count = final_audit.repair_needed_count();
|
||||||
|
report.verification_summary = OfficialVerificationSummary::new(
|
||||||
|
final_audit.manifest_blake3_verified_count(),
|
||||||
|
final_audit.repair_needed_count(),
|
||||||
|
pull_report.official_hash_verified_count(),
|
||||||
|
final_audit.zip_structure_verified_count(),
|
||||||
|
);
|
||||||
report.snapshot_written = Some(snapshot_path);
|
report.snapshot_written = Some(snapshot_path);
|
||||||
|
|
||||||
progress(OfficialUpdateProgress::new(
|
progress(OfficialUpdateProgress::new(
|
||||||
|
|||||||
@@ -200,6 +200,26 @@ fn official_update_first_run_pulls_without_pre_audit() {
|
|||||||
assert_eq!(report.downloaded_count, 19);
|
assert_eq!(report.downloaded_count, 19);
|
||||||
assert_eq!(report.skipped_count, 0);
|
assert_eq!(report.skipped_count, 0);
|
||||||
assert_eq!(report.local_manifest_repair_needed_count, 0);
|
assert_eq!(report.local_manifest_repair_needed_count, 0);
|
||||||
|
assert_eq!(
|
||||||
|
report
|
||||||
|
.verification_summary
|
||||||
|
.local_manifest_blake3_verified_count,
|
||||||
|
19
|
||||||
|
);
|
||||||
|
assert_eq!(report.verification_summary.official_hash_verified_count, 5);
|
||||||
|
assert_eq!(report.verification_summary.zip_structure_verified_count, 6);
|
||||||
|
assert!(report
|
||||||
|
.verification_summary
|
||||||
|
.official_hash_scope
|
||||||
|
.contains("xxHash32"));
|
||||||
|
assert!(report
|
||||||
|
.verification_summary
|
||||||
|
.local_manifest_blake3_scope
|
||||||
|
.contains("BLAKE3"));
|
||||||
|
assert!(report
|
||||||
|
.verification_summary
|
||||||
|
.zip_structure_scope
|
||||||
|
.contains("central directory"));
|
||||||
assert!(events.iter().any(|event| {
|
assert!(events.iter().any(|event| {
|
||||||
event.stage == "local-state" && event.message.contains("是否已有本地资源=false")
|
event.stage == "local-state" && event.message.contains("是否已有本地资源=false")
|
||||||
}));
|
}));
|
||||||
@@ -226,6 +246,13 @@ fn official_update_second_run_audits_existing_resources_before_reuse() {
|
|||||||
assert_eq!(report.downloaded_count, 0);
|
assert_eq!(report.downloaded_count, 0);
|
||||||
assert_eq!(report.local_manifest_verified_count, 19);
|
assert_eq!(report.local_manifest_verified_count, 19);
|
||||||
assert_eq!(report.local_manifest_repair_needed_count, 0);
|
assert_eq!(report.local_manifest_repair_needed_count, 0);
|
||||||
|
assert_eq!(
|
||||||
|
report
|
||||||
|
.verification_summary
|
||||||
|
.local_manifest_blake3_verified_count,
|
||||||
|
19
|
||||||
|
);
|
||||||
|
assert_eq!(report.verification_summary.zip_structure_verified_count, 6);
|
||||||
assert!(events.iter().any(|event| {
|
assert!(events.iter().any(|event| {
|
||||||
event.stage == "local-state" && event.message.contains("是否已有本地资源=true")
|
event.stage == "local-state" && event.message.contains("是否已有本地资源=true")
|
||||||
}));
|
}));
|
||||||
|
|||||||
Reference in New Issue
Block a user