CI / fmt (rustfmt --check) (push) Canceled after 0s
CI / clippy (ubuntu-latest) (push) Canceled after 0s
CI / clippy (windows-latest) (push) Canceled after 0s
CI / test (ubuntu-latest) (push) Canceled after 0s
CI / test (windows-latest) (push) Canceled after 0s
CI / build release (ubuntu-latest) (push) Canceled after 0s
CI / build release (windows-latest) (push) Canceled after 0s
Guards / core 零 UI 守门 (push) Canceled after 0s
Guards / 文件行数 ≤400 守门 (push) Canceled after 0s
Guards / 依赖许可与来源(cargo-deny) (push) Canceled after 0s
Rust 原生单文件 Minecraft 启动器:CLI 完整可用(install/launch/accounts/java/diagnose/agent), MCP server 接入外部 Agent 工具,GUI 开发中。
84 lines
3.1 KiB
Rust
84 lines
3.1 KiB
Rust
//! `core::diagnose` 集成测试。
|
||
//!
|
||
//! 结构对齐 HMCL 的 `CrashReportAnalyzerTest` + `resources/logs`(analyse/02 §7.9):
|
||
//! **每条规则一个样本**(`src/diagnose/rules.d/samples/`),断言「样本命中它自己」。
|
||
//! 规则库是数据不是代码,样本就是规则的验收标准——新增规则必须同时提交样本。
|
||
//!
|
||
//! 跑法:`cargo test -p unlucky-core --test diagnose`
|
||
|
||
mod collectors_probe;
|
||
mod engine_rank;
|
||
mod hs_err_parse;
|
||
mod loader_reload;
|
||
mod rules_samples;
|
||
|
||
/// 测试共用导入与辅助函数。
|
||
pub mod prelude {
|
||
use std::path::{Path, PathBuf};
|
||
|
||
pub use unlucky_core::diagnose::collectors::{
|
||
collect_all, CollectionContext, CrashReportCollector, EnvironmentCollector,
|
||
EnvironmentSnapshot, ExitCollector, ExitSignal, ExitType, HsErrCollector,
|
||
LatestLogCollector, LogBuffer, ModRecord, SignalBundle, SignalCollector, SignalKind,
|
||
SignalOrigin,
|
||
};
|
||
pub use unlucky_core::diagnose::engine::{
|
||
Diagnoser, DiagnosisInput, DiagnosisReport, Evidence, Finding, CONCLUSIVE_CONFIDENCE,
|
||
};
|
||
pub use unlucky_core::diagnose::hs_err::{self, FrameKind, HsErrKind, HsErrReport};
|
||
pub use unlucky_core::diagnose::loader::{ReloadOutcome, RuleLoader, RuleSet, EMBEDDED_RULES};
|
||
pub use unlucky_core::diagnose::rules::{
|
||
class_file_to_java_major, ComponentKind, FixAction, FixActionKind, GraphicsSetting,
|
||
JavaVendor, ModAction, RuleCategory, Severity,
|
||
};
|
||
|
||
/// 规则目录(`crates/core/src/diagnose/rules.d`)。
|
||
#[must_use]
|
||
pub fn rules_dir() -> PathBuf {
|
||
Path::new(env!("CARGO_MANIFEST_DIR")).join("src/diagnose/rules.d")
|
||
}
|
||
|
||
/// 读样本(路径相对 `rules.d/`)。
|
||
pub fn read_sample(relative: &str) -> String {
|
||
let path = rules_dir().join(relative);
|
||
std::fs::read_to_string(&path)
|
||
.unwrap_or_else(|error| panic!("样本 {} 读不到:{error}", path.display()))
|
||
}
|
||
|
||
/// 用内嵌规则库跑一段文本。
|
||
pub fn analyze_text(origin: SignalOrigin, text: &str) -> DiagnosisReport {
|
||
let mut input = DiagnosisInput::new();
|
||
input.push_text(origin, text);
|
||
diagnoser().analyze(&input)
|
||
}
|
||
|
||
/// 内嵌规则库构造的引擎。
|
||
#[must_use]
|
||
pub fn diagnoser() -> Diagnoser {
|
||
Diagnoser::new(RuleLoader::embedded().rules().to_vec())
|
||
}
|
||
|
||
/// 结论 id 列表(断言失败时打印用)。
|
||
#[must_use]
|
||
pub fn ids(report: &DiagnosisReport) -> Vec<&str> {
|
||
report
|
||
.findings
|
||
.iter()
|
||
.map(|finding| finding.rule_id.as_str())
|
||
.collect()
|
||
}
|
||
|
||
/// 临时目录(进程 id + 计数器,不引 tempfile 依赖)。
|
||
#[must_use]
|
||
pub fn temp_dir(tag: &str) -> PathBuf {
|
||
use std::sync::atomic::{AtomicU32, Ordering};
|
||
static COUNTER: AtomicU32 = AtomicU32::new(0);
|
||
let index = COUNTER.fetch_add(1, Ordering::Relaxed);
|
||
let dir =
|
||
std::env::temp_dir().join(format!("ull-diagnose-{}-{tag}-{index}", std::process::id()));
|
||
let _ = std::fs::remove_dir_all(&dir);
|
||
std::fs::create_dir_all(&dir).expect("创建临时目录");
|
||
dir
|
||
}
|
||
}
|