release: v0.2.4 里程碑快照(孤儿提交,无父;树 = dev 68362e5)
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
CI / runtime smoke (ubuntu x64, xvfb) (push) Waiting to run
CI / runtime smoke (macos arm64, probe) (push) Skipped
CI / update-e2e (windows x64) (push) Waiting to run
GPU evidence / GPU 判据自测(不需 GPU;跳过 ≠ 已验证) (push) Waiting to run
GPU evidence / GPU 证据 — 探测可用产物与硬件适配器 (push) Waiting to run
Guards / core 零 UI 守门 (push) Waiting to run
Guards / presenter 零 UI 守门 (push) Waiting to run
Guards / design 零第三方依赖守门 (push) Waiting to run
Guards / unsafe 落点守门(集合必须恰好等于期望) (push) Waiting to run
Guards / 文件行数 ≤400 守门 (push) Waiting to run
Guards / 依赖许可与来源(cargo-deny) (push) Waiting to run
Release guard / 发布标记语义守门(push tag → 稳定版) (push) Waiting to run
Signing status(播报,不是门禁) / 判据自测(三行/退出码/变异重放/接线) (push) Waiting to run
Signing status(播报,不是门禁) / 签名就绪度(播报) (push) Waiting to run
Release / 选槽位(默认四个:Windows 两档 + Linux 两档) (push) Waiting to run
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
CI / runtime smoke (ubuntu x64, xvfb) (push) Waiting to run
CI / runtime smoke (macos arm64, probe) (push) Skipped
CI / update-e2e (windows x64) (push) Waiting to run
GPU evidence / GPU 判据自测(不需 GPU;跳过 ≠ 已验证) (push) Waiting to run
GPU evidence / GPU 证据 — 探测可用产物与硬件适配器 (push) Waiting to run
Guards / core 零 UI 守门 (push) Waiting to run
Guards / presenter 零 UI 守门 (push) Waiting to run
Guards / design 零第三方依赖守门 (push) Waiting to run
Guards / unsafe 落点守门(集合必须恰好等于期望) (push) Waiting to run
Guards / 文件行数 ≤400 守门 (push) Waiting to run
Guards / 依赖许可与来源(cargo-deny) (push) Waiting to run
Release guard / 发布标记语义守门(push tag → 稳定版) (push) Waiting to run
Signing status(播报,不是门禁) / 判据自测(三行/退出码/变异重放/接线) (push) Waiting to run
Signing status(播报,不是门禁) / 签名就绪度(播报) (push) Waiting to run
Release / 选槽位(默认四个:Windows 两档 + Linux 两档) (push) Waiting to run
本批内容见 CHANGELOG.md 的 0.2.4 段。按 D41 用孤儿快照推 main,保留「公开史只有里程碑」的模型。
This commit is contained in:
commit
a5d1dec495
1580 files changed
+320938
No files matched your search
@@ -0,0 +1,136 @@
|
||||
//! `dto::adopt` 的 IPC 契约用例(M223 从 `dto/adopt.rs` **纯搬移**,断言一条未改)。
|
||||
//!
|
||||
//! 为什么搬:`dto/adopt.rs` 落笔 512 行,越过 400 行硬线(AGENTS §3.1);口径与
|
||||
//! [`crate::dto::events::tests`] 完全一致——**纯搬移、一行不改**。`adopt.rs` 是非 `mod.rs`
|
||||
//! 文件,`mod tests;` 的落点就是本文件。
|
||||
|
||||
use super::*;
|
||||
|
||||
fn candidate(version_id: &str, problems: Vec<AdoptProblemView>) -> AdoptCandidateView {
|
||||
AdoptCandidateView {
|
||||
version_id: version_id.to_string(),
|
||||
jar_present: true,
|
||||
inherits: Vec::new(),
|
||||
registered: Vec::new(),
|
||||
problems,
|
||||
}
|
||||
}
|
||||
|
||||
fn scan_view() -> AdoptScanView {
|
||||
AdoptScanView {
|
||||
versions_dir: PathBuf::from("/game/versions"),
|
||||
candidates: vec![
|
||||
candidate("1.20.1", Vec::new()),
|
||||
candidate(
|
||||
"1.19.4",
|
||||
vec![AdoptProblemView {
|
||||
code: "manifest_missing".to_string(),
|
||||
message: "版本 1.19.4 没有清单文件".to_string(),
|
||||
}],
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn events_round_trip_through_json() {
|
||||
let event = AdoptEvent::Failed(Box::new(AdoptFailureView {
|
||||
code: "adopt_not_adoptable".to_string(),
|
||||
message: "版本 1.19.4 不能登记".to_string(),
|
||||
problems: vec![AdoptProblemView {
|
||||
code: "manifest_missing".to_string(),
|
||||
message: "清单缺了".to_string(),
|
||||
}],
|
||||
}));
|
||||
let text = serde_json::to_string(&event).expect("序列化");
|
||||
assert_eq!(
|
||||
serde_json::from_str::<AdoptEvent>(&text).expect("反序列化"),
|
||||
event
|
||||
);
|
||||
|
||||
let command = AdoptCommand::Preview(Box::new(AdoptRequestView {
|
||||
version_id: "1.20.1".to_string(),
|
||||
name: Some("生存".to_string()),
|
||||
target: AdoptTargetView::Shared,
|
||||
}));
|
||||
let text = serde_json::to_string(&command).expect("序列化");
|
||||
assert_eq!(
|
||||
serde_json::from_str::<AdoptCommand>(&text).expect("反序列化"),
|
||||
command
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scan_summarises_adoptable_and_empty() {
|
||||
let view = scan_view();
|
||||
assert_eq!(view.total(), 2);
|
||||
assert_eq!(view.adoptable(), 1);
|
||||
assert!(!view.is_empty());
|
||||
assert!(AdoptScanView {
|
||||
versions_dir: PathBuf::from("/game/versions"),
|
||||
candidates: Vec::new(),
|
||||
}
|
||||
.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn target_slugs_round_trip_and_mark_foreign_dirs() {
|
||||
for target in AdoptTargetView::ALL {
|
||||
assert_eq!(AdoptTargetView::from_slug(target.slug()), Some(target));
|
||||
}
|
||||
assert_eq!(AdoptTargetView::default(), AdoptTargetView::InstanceDir);
|
||||
assert!(!AdoptTargetView::InstanceDir.touches_foreign_dir());
|
||||
assert!(AdoptTargetView::Shared.touches_foreign_dir());
|
||||
assert!(AdoptTargetView::VersionDir.touches_foreign_dir());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn state_follows_the_four_stages() {
|
||||
let mut state = AdoptState::default();
|
||||
assert_eq!(state.stage(), AdoptStage::Pick);
|
||||
|
||||
state.apply(AdoptEvent::Scan(Box::new(scan_view())));
|
||||
assert_eq!(state.stage(), AdoptStage::Pick);
|
||||
assert_eq!(state.scan.as_ref().map(AdoptScanView::adoptable), Some(1));
|
||||
|
||||
let plan = AdoptPlanView {
|
||||
version_id: "1.20.1".to_string(),
|
||||
name: "1.20.1".to_string(),
|
||||
target: AdoptTargetView::InstanceDir,
|
||||
isolation: AdoptIsolationView::Custom,
|
||||
run_dir: PathBuf::from("/ull/data/instances/1.20.1"),
|
||||
notes: vec!["运行目录 = /ull/data/instances/1.20.1".to_string()],
|
||||
};
|
||||
state.apply(AdoptEvent::Planned(Box::new(plan.clone())));
|
||||
assert_eq!(state.stage(), AdoptStage::Preview);
|
||||
assert_eq!(
|
||||
state.plan.as_ref().map(|plan| &plan.run_dir),
|
||||
Some(&plan.run_dir)
|
||||
);
|
||||
|
||||
// 失败会把预检顶掉:留着预检,确认按钮就会在「不能登记」的结论上继续亮着
|
||||
state.apply(AdoptEvent::Failed(Box::new(AdoptFailureView {
|
||||
code: "adopt_duplicate_name".to_string(),
|
||||
message: "已有同名实例".to_string(),
|
||||
problems: Vec::new(),
|
||||
})));
|
||||
assert_eq!(state.stage(), AdoptStage::Failed);
|
||||
assert!(state.plan.is_none());
|
||||
|
||||
state.apply(AdoptEvent::Done(Box::new(AdoptDoneView {
|
||||
instance_id: "id-1".to_string(),
|
||||
name: "1.20.1".to_string(),
|
||||
version_id: "1.20.1".to_string(),
|
||||
isolation: AdoptIsolationView::Custom,
|
||||
run_dir: PathBuf::from("/ull/data/instances/1.20.1"),
|
||||
dir_created: true,
|
||||
notes: Vec::new(),
|
||||
})));
|
||||
assert_eq!(state.stage(), AdoptStage::Done);
|
||||
assert!(state.failure.is_none());
|
||||
|
||||
// 关面板 = 全清(再开要重新扫,否则画的是上一轮的候选)
|
||||
state.apply(AdoptEvent::Cleared);
|
||||
assert_eq!(state.stage(), AdoptStage::Pick);
|
||||
assert!(state.scan.is_none() && state.done.is_none());
|
||||
}
|
||||
Reference in new issue
Block a user