Files
Unlucky-Launcher/crates/core/tests/game/java_mapping.rs
T
AskaEth bc41dfcf7d
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
Unlucky Launcher v0.0.1-alpha
Rust 原生单文件 Minecraft 启动器:CLI 完整可用(install/launch/accounts/java/diagnose/agent),
MCP server 接入外部 Agent 工具,GUI 开发中。
2026-10-31 21:54:10 +08:00

107 lines
3.9 KiB
Rust

//! MC↔Java 映射:版本 JSON 的 `javaVersion` 优先(含继承链),上限取自静态表。
use std::path::PathBuf;
use unlucky_core::game::java::mapping;
fn temp_dir(tag: &str) -> PathBuf {
use std::sync::atomic::{AtomicU64, Ordering};
static COUNTER: AtomicU64 = AtomicU64::new(0);
let nanos = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map_or(0, |elapsed| elapsed.as_nanos());
let seq = COUNTER.fetch_add(1, Ordering::Relaxed);
let dir = std::env::temp_dir().join(format!(
"ull-java-{tag}-{}-{nanos}-{seq}",
std::process::id()
));
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(&dir).expect("建临时目录");
dir
}
#[test]
fn version_json_java_version_beats_the_static_table() {
let root = temp_dir("mapping");
let layout = unlucky_core::game::GameLayout::new(&root);
let write = |id: &str, json: serde_json::Value| {
let dir = root.join("versions").join(id);
std::fs::create_dir_all(&dir).expect("建版本目录");
std::fs::write(
dir.join(format!("{id}.json")),
serde_json::to_vec(&json).expect("序列化"),
)
.expect("写版本 JSON");
};
// 1.17 的清单自己说是 16(静态表也是 16,但来源必须标 manifest)。
write(
"1.17.1",
serde_json::json!({"id": "1.17.1", "javaVersion": {"component": "java-runtime-alpha", "majorVersion": 16}}),
);
let manifest = mapping::requirement_for_version(&layout, "1.17.1");
assert_eq!(manifest.minimum, 16);
assert_eq!(manifest.source.as_str(), "manifest");
// 魔改实例覆盖父版本:21 应当生效。
write("1.20.1", serde_json::json!({"id": "1.20.1"}));
write(
"1.20.1-forge",
serde_json::json!({"id": "1.20.1-forge", "inheritsFrom": "1.20.1", "javaVersion": {"majorVersion": 21}}),
);
assert_eq!(
mapping::requirement_for_version(&layout, "1.20.1-forge").minimum,
21
);
// 清单没写 javaVersion:父版本也没有 → 静态表兜底。
let table = mapping::requirement_for_version(&layout, "1.20.1");
assert_eq!(table.minimum, 17);
assert_eq!(table.source.as_str(), "table");
// 1.12.2:清单只说「最低 8」,但上限(LaunchWrapper 只能 Java 8)由静态表补上。
write(
"1.12.2",
serde_json::json!({"id": "1.12.2", "javaVersion": {"component": "jre-legacy", "majorVersion": 8}}),
);
let legacy = mapping::requirement_for_version(&layout, "1.12.2");
assert_eq!((legacy.minimum, legacy.maximum), (8, Some(8)));
assert_eq!(legacy.source.as_str(), "manifest");
assert!(
mapping::check(21, &legacy).is_some(),
"1.12.2 + Java 21 必须报不符"
);
// 版本根本没装:按 id 走静态表,不报错。
let missing = mapping::requirement_for_version(&layout, "26.3");
assert_eq!(missing.minimum, 25);
let _ = std::fs::remove_dir_all(&root);
}
#[test]
fn parent_java_version_is_inherited() {
let root = temp_dir("inherit");
let layout = unlucky_core::game::GameLayout::new(&root);
let write = |id: &str, json: serde_json::Value| {
let dir = root.join("versions").join(id);
std::fs::create_dir_all(&dir).expect("建版本目录");
std::fs::write(
dir.join(format!("{id}.json")),
serde_json::to_vec(&json).expect("序列化"),
)
.expect("写版本 JSON");
};
write(
"1.20.5",
serde_json::json!({"id": "1.20.5", "javaVersion": {"component": "java-runtime-delta", "majorVersion": 21}}),
);
write(
"1.20.5-fabric",
serde_json::json!({"id": "1.20.5-fabric", "inheritsFrom": "1.20.5"}),
);
let requirement = mapping::requirement_for_version(&layout, "1.20.5-fabric");
assert_eq!(requirement.minimum, 21);
assert_eq!(requirement.source.as_str(), "manifest");
let _ = std::fs::remove_dir_all(&root);
}