Files
Unlucky-Launcher/crates/core/tests/game/java_discover.rs
T
AskaEth 5f8382565e
CI / fmt (rustfmt --check) (push) Waiting to run
CI / clippy (ubuntu-latest) (push) Waiting to run
CI / clippy (windows-latest) (push) Waiting to run
CI / test (ubuntu-latest) (push) Waiting to run
CI / test (windows-latest) (push) Waiting to run
CI / build release (ubuntu-latest) (push) Waiting to run
CI / build release (windows-latest) (push) Waiting to run
Guards / core 零 UI 守门 (push) Waiting to run
Guards / 文件行数 ≤400 守门 (push) Waiting to run
Guards / 依赖许可与来源(cargo-deny) (push) Waiting to run
Unlucky Launcher v0.1.0
单提交快照:main 只保留已发布版本的代码树,开发史在 dev。
2026-11-01 20:02:49 +08:00

130 lines
4.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! `core::game::java::discover`:标准安装位置扫描与来源优先级。
//!
//! 真机上扫到什么取决于本机装了什么,所以断言只钉**不变量**:
//! 扫描结果形状、来源优先级(env 胜过扫盘)、去重保留高优先级、缺目录不报错。
use unlucky_core::game::java::discover;
use unlucky_core::game::java::mapping::{JavaRequirement, RequirementSource};
use unlucky_core::game::java::{pick, JavaOrigin, JavaRuntime};
fn runtime(path: &str, major: u32, origin: JavaOrigin) -> JavaRuntime {
JavaRuntime {
binary: std::path::PathBuf::from(path),
origin,
version: Some(format!("openjdk version \"{major}.0.1\"")),
major: Some(major),
bits: 64,
vendor: None,
}
}
fn at_least(minimum: u32) -> JavaRequirement {
JavaRequirement::new(minimum, None, RequirementSource::Table)
}
#[test]
fn scanned_paths_always_point_at_a_java_binary() {
// 本机可能一个都没有(裸机/容器)——那也算通过,只是列表为空。
for binary in discover::scan_java_binaries() {
assert!(
binary.is_file(),
"扫描结果必须是真实存在的文件:{}",
binary.display()
);
assert_eq!(
binary
.file_name()
.map(|name| name.to_string_lossy().into_owned()),
Some(unlucky_core::game::java::java_binary_name().to_string()),
"扫描结果必须是 bin/java[.exe]:{}",
binary.display()
);
}
}
#[test]
fn standard_roots_are_absolute_and_unique() {
let roots = discover::standard_roots();
for root in &roots {
assert!(
root.is_absolute(),
"候选根必须是绝对路径:{}",
root.display()
);
}
let mut keys: Vec<String> = roots.iter().map(|root| discover::path_key(root)).collect();
let total = keys.len();
keys.sort();
keys.dedup();
assert_eq!(keys.len(), total, "候选根不该重复");
}
#[test]
fn environment_java_beats_scanned_java_when_both_satisfy() {
// D13 的「优先级链不变」:环境变量是用户意图,扫盘只是候选。
let candidates = [
runtime(
"C:/Program Files/Eclipse Adoptium/jdk-21/bin/java.exe",
21,
JavaOrigin::System,
),
runtime(
"C:/Program Files/Microsoft/jdk-21/bin/java.exe",
21,
JavaOrigin::JavaHome,
),
];
let picked = pick(&candidates, &at_least(17)).expect("应有候选");
assert_eq!(picked.origin, JavaOrigin::JavaHome);
}
#[test]
fn scanned_java_is_still_used_when_nothing_else_matches() {
// MSI 装了 Temurin 21、没设环境变量、PATH 上是 Java 8:1.20.5 只认扫盘那个。
let candidates = [
runtime("java", 8, JavaOrigin::Path),
runtime(
"C:/Program Files/Java/jdk-21/bin/java.exe",
21,
JavaOrigin::System,
),
];
let picked = pick(&candidates, &at_least(21)).expect("应有候选");
assert_eq!(picked.origin, JavaOrigin::System);
}
#[test]
fn dedupe_collapses_one_install_found_twice() {
// `JAVA_HOME` 指向 Program Files 里的 JDK → 同一个 java 不应列两次。
// 第二条的「另一种写法」随平台给:Windows 上大小写和分隔符都可能不一致(NTFS 不区分
// 大小写),POSIX 上大小写是有效区别,只能靠分隔符拼出同一路径的第二种写法。
let duplicate = if cfg!(windows) {
"c:/program files/java/jdk-21/bin/java.exe"
} else {
"C:\\Program Files\\Java\\jdk-21/bin/java.exe"
};
let candidates = discover::dedupe(vec![
runtime(
"C:/Program Files/Java/jdk-21/bin/java.exe",
21,
JavaOrigin::JavaHome,
),
runtime(duplicate, 21, JavaOrigin::System),
]);
assert_eq!(candidates.len(), 1);
assert_eq!(candidates[0].origin, JavaOrigin::JavaHome);
}
#[test]
fn registry_absence_is_tolerated() {
// 非 Windows 必然为空;Windows 上没装老 Oracle JDK 也是空。
let homes = discover::registry_homes();
for home in &homes {
assert!(
home.is_absolute(),
"注册表里的 JavaHome 应是绝对路径:{}",
home.display()
);
}
}