Unlucky Launcher v0.0.1-alpha
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
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 开发中。
This commit is contained in:
commit
bc41dfcf7d
517 files changed
+92844
No files matched your search
@@ -0,0 +1,109 @@
|
||||
//! 实例清单:稳定 UUID、增删查、落盘格式兼容。
|
||||
|
||||
use unlucky_core::game::profiles::{
|
||||
InstanceProfile, ProfileId, ProfileList, PROFILE_SCHEMA_VERSION,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn generated_ids_are_unique_and_uuid_shaped() {
|
||||
let ids: Vec<ProfileId> = (0..256).map(|_| ProfileId::generate()).collect();
|
||||
for id in &ids {
|
||||
assert!(id.is_uuid_shaped(), "id 形状不对: {id}");
|
||||
}
|
||||
let mut unique: Vec<&str> = ids.iter().map(ProfileId::as_str).collect();
|
||||
let total = unique.len();
|
||||
unique.sort_unstable();
|
||||
unique.dedup();
|
||||
assert_eq!(unique.len(), total, "同一批生成的 id 不能重复");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn id_shape_validation_rejects_junk() {
|
||||
assert!(!ProfileId::new("not-a-uuid").is_uuid_shaped());
|
||||
assert!(!ProfileId::new("").is_uuid_shaped());
|
||||
assert!(ProfileId::new("7c9e6679-7425-40de-944b-e07fc1f90ae7").is_uuid_shaped());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn upsert_and_remove_keep_one_entry_per_id() {
|
||||
let mut list = ProfileList::default();
|
||||
assert_eq!(list.schema_version, PROFILE_SCHEMA_VERSION);
|
||||
assert!(list.is_empty());
|
||||
|
||||
let mut profile = InstanceProfile::new("主世界", "1.20.1");
|
||||
assert_eq!(list.upsert(profile.clone()), None, "首次插入没有旧值");
|
||||
assert_eq!(list.len(), 1);
|
||||
|
||||
profile.name = "主世界(Fabric)".to_owned();
|
||||
let replaced = list.upsert(profile.clone()).expect("同 id 应替换");
|
||||
assert_eq!(replaced.name, "主世界");
|
||||
assert_eq!(list.len(), 1);
|
||||
assert_eq!(
|
||||
list.get(&profile.id).map(|p| p.name.as_str()),
|
||||
Some("主世界(Fabric)")
|
||||
);
|
||||
|
||||
let removed = list.remove(&profile.id).expect("应可删除");
|
||||
assert_eq!(removed.id, profile.id);
|
||||
assert!(list.is_empty());
|
||||
assert!(list.remove(&profile.id).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn profiles_group_by_version() {
|
||||
let mut list = ProfileList::default();
|
||||
list.upsert(InstanceProfile::new("a", "1.20.1"));
|
||||
list.upsert(InstanceProfile::new("b", "1.20.1"));
|
||||
list.upsert(InstanceProfile::new("c", "1.19.4"));
|
||||
|
||||
assert_eq!(list.for_version("1.20.1").len(), 2);
|
||||
assert_eq!(list.for_version("1.19.4").len(), 1);
|
||||
assert!(list.for_version("1.18.2").is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn roundtrips_profiles_json() {
|
||||
let mut list = ProfileList::default();
|
||||
let mut profile = InstanceProfile::new("整合包", "1.20.1-forge-47.2.0");
|
||||
profile.running_dir = Some(std::path::PathBuf::from("D:/mc/runs/pack"));
|
||||
profile
|
||||
.extra
|
||||
.insert("thirdPartyFlag".to_owned(), serde_json::json!(true));
|
||||
list.upsert(profile.clone());
|
||||
|
||||
let json = list.to_json_string().expect("应可序列化");
|
||||
let reparsed = ProfileList::from_json_str(&json).expect("应可再解析");
|
||||
assert_eq!(reparsed, list);
|
||||
assert_eq!(reparsed.schema_version, PROFILE_SCHEMA_VERSION);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reads_minimal_profile_file() {
|
||||
// 用户手改/旧版本写下的最小档案:只有三个必填语义字段,其它缺省。
|
||||
let list = ProfileList::from_json_str(
|
||||
r#"{ "profiles": [ { "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
|
||||
"name": "旧档案", "version_id": "1.12.2" } ] }"#,
|
||||
)
|
||||
.expect("最小档案应可解析");
|
||||
|
||||
assert_eq!(
|
||||
list.schema_version, PROFILE_SCHEMA_VERSION,
|
||||
"schemaVersion 缺省补齐"
|
||||
);
|
||||
assert_eq!(list.len(), 1);
|
||||
let profile = &list.profiles[0];
|
||||
assert_eq!(profile.name, "旧档案");
|
||||
assert!(profile.running_dir.is_none());
|
||||
assert!(profile.id.is_uuid_shaped());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_profiles_json_reports_context() {
|
||||
let error = ProfileList::from_json_str("{").expect_err("非法 JSON 应报错");
|
||||
match error {
|
||||
unlucky_core::game::error::GameError::Json { context, .. } => {
|
||||
assert_eq!(context, "profiles")
|
||||
}
|
||||
other => panic!("期望 Json 错误,得到 {other:?}"),
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user