fix(m161-r1): 崩溃/静默失败不再冒充「启动进程失败」;补三处假绿的守卫
复审 P1-1(用户可见假文案):`LaunchEnd` 在 `failure == None`(跑起来之后崩的)时
临时造了 `Stage::Spawn + format!("exit {:?}")`,于是磁贴写「启动失败 · 启动游戏进程」、
详情页漏出 `exit Some(1)`、静默失败丢掉「exit 0 却没起来」,而同一时刻 Toast 说「崩溃」。
- 新增 `LaunchFailureCause{Stage|Crashed|SilentFailure}`(dto/launch_failure.rs),
`LaunchFailureCause::of(outcome, failure, exit_code)` 是唯一组装点;`InstanceRuntime::Failed{cause}`。
`LaunchFailureStage` 保持「只装装配阶段」(文档那句「崩溃是结局不是阶段」现在成立)。
- 界面:`InstancesFailed`(框架)+ `InstancesCrashed` + `InstancesSilentFailed`;
删掉 `InstancesFailedStage`。退出码按数字出词,不再有 Debug 文本。
- 用例:presenter 断言**枚举变体**(三种形状逐条)、app 断言**具体句子**
(「不许出现 Some(」「进程起来了不许说启动游戏进程」「静默失败要点出没起来」)。
mock 夹具与 launch_state_tests 的期望值同步;launch-error 三张图重拍。
复审 P2-1(`convert::failure_stage` 零覆盖):新增 `convert/stage_tests.rs` 5 条(三档 +
「既没回滚也没宣称干净」+ 非致命无阶段 + `failed_report_with` ⇒ NotStarted)。
变异实测:改成恒 `RolledBack` ⇒ 3 条红。
复审 P2-2(矮窗口用例的算式三个数全错、`body_height` 零测试):用例改成直接调
`frame::body_height`,chrome 从 `Ui::metrics` + `WidthClass::gutter` 现取,并把门槛与真实
chrome 绑死(chrome+MIN ⇒ Split、-1px ⇒ ScrollWhole);新增 `frame` 自己的 `body_height` 用例。
变异实测:`2.0 * gutter` → `gutter` ⇒ 2 条红。
复审 P2-3(源指纹闸门 / `Refused` 零覆盖):新增两条 core 用例——闸门(原地留着 prefs.json
+ 预先写好的同源收据 ⇒ Nothing 且收据未被重写,反证:源变了允许重放)、`Refused`
(`$schema` 1.7.0 ⇒ ReadOnly ⇒ 不动旧文件、不写收据、理由含「不可写」)。
变异实测:删闸门 ⇒ 1 条红;`can_save` 守卫改 `if false` ⇒ 1 条红。
顺手收:
- CLI `pack import` 那句「已整包回滚」也按三档出词(`RollbackStage` + `rollback_line`),
加 2 条单测。CLI 不依赖 presenter,判定暂与 presenter 各一份 → 已 file finding 建议下沉 core。
- 设置页 `status_text()` 抽出 applying 档,用例断言「正在安装…」且非错误色。
金表:新 key 加在 `golden.rs`(81 行),未动 `golden/tail.rs`(211 行),避免与 M162 的拆分冲突。
This commit is contained in:
1 parent
6804b0ad1d
commit
79b796fd58
21 files changed
+894
-168
No files matched your search
@@ -99,3 +99,49 @@ fn two_pane_body_is_narrower_than_the_available_width() {
|
||||
assert!(wide.column < wide.available);
|
||||
assert!(wide.secondary.is_some());
|
||||
}
|
||||
|
||||
/// **`body_height` 用真的 `Ui::metrics` + `FrameMetrics` 算**(M161 复审 P2-2:这条函数此前
|
||||
/// 一条测试都没有,而④的「最小窗口」用例是拿 56/88/32 反推的——三个数全错)。
|
||||
///
|
||||
/// 抓得住:①`titlebar_height` / `header_height` / `gutter` 任何一个被改(chrome 变了,
|
||||
/// 下面的等式立刻红);②把两行页头当单行算(`has_subtitle` 被忽略);③把页边距只减一遍。
|
||||
#[test]
|
||||
fn body_height_subtracts_the_real_shell_chrome() {
|
||||
let ui = ui();
|
||||
let metrics = frame_metrics(PaneKit::Single, 880.0);
|
||||
let metrics_wide = frame_metrics(PaneKit::Single, 1180.0);
|
||||
|
||||
let chrome = |two_line: bool| {
|
||||
ui.metrics().titlebar_height + ui.metrics().header_height(two_line) + 2.0 * metrics.gutter
|
||||
};
|
||||
|
||||
// 真值来自 token:自绘标题栏 48 + 两行页头 84 + 上下页边距 2×24 = 180。
|
||||
assert_eq!(
|
||||
chrome(true),
|
||||
48.0 + 84.0 + 2.0 * 24.0,
|
||||
"chrome 与 design token 不一致(titlebar_height / page_header_tall_height / Expanded gutter)"
|
||||
);
|
||||
assert_eq!(body_height(&ui, metrics, 560.0, true), 560.0 - chrome(true));
|
||||
// 单行页头少 28(84 − 56 = `page_header_tall_height` − `page_header_height`)。
|
||||
assert_eq!(
|
||||
body_height(&ui, metrics, 560.0, false),
|
||||
560.0 - chrome(false)
|
||||
);
|
||||
assert!(
|
||||
body_height(&ui, metrics, 560.0, true) < body_height(&ui, metrics, 560.0, false),
|
||||
"带副标题的页头更高,正文可用高必须更小"
|
||||
);
|
||||
// 窄窗(Compact < 600)页边距更小 ⇒ 同样窗口高下正文更高。
|
||||
let compact = frame_metrics(PaneKit::Single, 560.0);
|
||||
assert_eq!(compact.class, crate::pages::layout::WidthClass::Compact);
|
||||
assert!(
|
||||
compact.gutter < metrics_wide.gutter,
|
||||
"Compact 档的页边距应小于 Expanded(16 < 24)"
|
||||
);
|
||||
assert!(
|
||||
body_height(&ui, compact, 560.0, true) > body_height(&ui, metrics_wide, 560.0, true),
|
||||
"页边距变小 ⇒ 正文可用高变大"
|
||||
);
|
||||
// 窗口比外壳还矮时不返回负数(不许把版面算成 NaN/负值)。
|
||||
assert_eq!(body_height(&ui, metrics, 100.0, true), 0.0);
|
||||
}
|
||||
Reference in new issue
Block a user