fix(m168): 复审 r3 四项 —— 说准 panic 档、给两条修复补守卫、时限算术补洞
复审 r3(p2-4items / fix-then-merge)四项 + 顺手五条:
1. **P2-1 `catch_unwind` 在发布档是死代码,三处文档说了不成立的话**:
`Cargo.toml` 的 `[profile.release]` 是 `panic = "abort"`(只有 `fast` 是 `unwind`),发布走
`--release`。分两半写清楚:①**闸前移仍安全**——release 档 panic 是进程退出,不存在永久停在
`Downloading`;`dev`/`test`/`fast` 档 `catch_unwind` 真会写 `Failed`;②但「下载失败不崩」在
panic 这一支上对发布版**是反的**:注册/`load_font` panic ⇒ 启动器整体 abort,不是降级。
`install.rs::plan_with_offline` 的文档(新增两档对照表)、`worker.rs` 模块文档与 `run` 注释全部
按这个说法重写,不再用 `catch_unwind` 给「不崩」背书。
2. **P2-2 「启动不发起下载」这条修复没有守卫**:拆出纯函数
`fonts::resolve_with_faces(setting, faces)`(`resolve_with` 只是 `system_faces()` 的包装),
新增 `fonts::tests::resolving_fonts_never_starts_a_download`:给一张只有拉丁族的脸表
(一定判 `NeedsDownload`),断言调用后 `install::status()` **不是** `Downloading`。
变异(实跑):把 `install::after_probe(cjk_report.strategy)` 加回 `resolve_with_faces` ⇒
`求值字体**不许**发起下载(状态从 Unknown 变成了 Downloading { bytes: 17772300 })`,红。
3. **P2-3 时限算术有洞 + `is_last` 没守卫**:改 `ATTEMPT_DEADLINE=60 s` / `TOTAL_DEADLINE=420 s`
(原来 120/360 时,第一个候选吃掉 120 s 后最后一个只剩 240 s ⇒ 门槛 72.3 KiB/s,r1 实测
67 KiB/s 需要 259 s,仍然必失败)。文档按新数值重算成一张表:第一个候选瞬间失败 ⇒ 420 s ⇒
42.3 KiB/s;爬满 60 s 被切 ⇒ 360 s ⇒ 49.4 KiB/s,两者都低于实测最慢的 67 KiB/s。
守卫:把同解的旧用例换成 **单候选 + attempt 300 ms / total 5 s**——有 `is_last` 时跑到总时限
(≈5 s),没有时 300 ms 就切,两种实现可分辨。变异(实跑):删掉 `is_last` ⇒
`the_last_candidate_gets_the_whole_remaining_budget` 红在
`最后一个候选该拿整个剩余预算(≈5 s)…452.6035ms`。
4. **P2-4(b)(c)**:①`install::tests` 里三处判据用例改用 `plan_with_offline(..., false)`,把进程级
`OFFLINE` 从判据里摘出去(否则同进程里 `headless(screenshot_options())` 会把它置 true 且从不
还原 ⇒ 结果依赖执行顺序);②`fonts.rs` 注释改成真实机制——出图 harness 不经
`App::with_presenter`、压根没有 `set_offline`,它零流量靠的是「`resolve_with` 不触发」。
顺手:①`sha256_mismatch…` 的 doc 改成「两层校验互备,本用例抓的是两层同时拆」(原来说
「拆任意一层就红」是假的);②`font.rs` 文档「把 90 s 压成 300 ms」→ 60 s/420 s;③`install.rs` 与
`catalog/font_install.rs` 的「≈17 MB」→ 16.9;④`worker::start` 的裸 `thread::spawn` 换成
`Builder::spawn`,起不来就落 `Failed`(发布档 panic = abort,不能让它 panic);线程体抽成 `run()`。
验证(`CARGO_TARGET_DIR=C:/Temp/ull-target/wt-168`,取退出码、不截断):
- `cargo test -p unlucky-app-iced --lib` → **688 passed / 0 failed / 2 ignored / exit 0**
- `cargo test -p unlucky-core --all-targets` → **16 个 target / 1189 passed / 0 failed / exit 0**
- `cargo test -p unlucky-i18n` → 31 passed / 0 failed / exit 0
- `cargo clippy -p unlucky-i18n -p unlucky-core -p unlucky-app-iced --all-targets -- -D warnings` → exit 0
- `cargo fmt --all -- --check` 干净;全仓无文件 >400;本轮改动文件最大 378(`app-iced/src/fonts.rs`)
This commit is contained in:
1 parent
b9009c0e61
commit
460da9330d
9 files changed
+231
-103
No files matched your search
@@ -178,7 +178,7 @@ fn a_started_or_finished_install_is_not_restarted() {
|
||||
|
||||
for current in [downloading, ready] {
|
||||
assert_eq!(
|
||||
plan(Strategy::NeedsDownload(&NOTO_SANS_SC), ¤t),
|
||||
plan_with_offline(Strategy::NeedsDownload(&NOTO_SANS_SC), ¤t, false),
|
||||
Step::Skip,
|
||||
"{current:?}:已经在下载 / 已就绪时再问一次,必须什么都不做"
|
||||
);
|
||||
@@ -194,14 +194,18 @@ fn a_started_or_finished_install_is_not_restarted() {
|
||||
},
|
||||
] {
|
||||
assert_eq!(
|
||||
plan(Strategy::NeedsDownload(&NOTO_SANS_SC), ¤t),
|
||||
plan_with_offline(Strategy::NeedsDownload(&NOTO_SANS_SC), ¤t, false),
|
||||
Step::Start(&NOTO_SANS_SC),
|
||||
"{current:?}:需要下载且还没成就该发起(失败后的重试也只能走这条)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 三种「不需要下载」的策略在 [`plan`] 里只产生 `Apply`(**零网络**),且状态文案对得上。
|
||||
/// 三种「不需要下载」的策略在判据表里只产生 `Apply`(**零网络**),且状态文案对得上。
|
||||
///
|
||||
/// 这里显式给 `offline = false`(`plan_with_offline`)而不是用 `plan`:`plan` 会读进程级的
|
||||
/// `set_offline` 开关,而同进程里 `headless(screenshot_options())` 那 20+ 处会把它置 true 且
|
||||
/// 从不还原(复审 r3 P2-4 ①)——用 `plan` 的话这三条的结果取决于执行顺序。
|
||||
///
|
||||
/// 抓得住:谁把 `NotNeeded` / `System` / `Unprobeable` 的臂改成 `Start`(那就会替英文用户偷偷
|
||||
/// 下一次 17 MiB);也抓得住「系统已有字体」被记成「需要下载」这种状态映射错。
|
||||
@@ -209,11 +213,15 @@ fn a_started_or_finished_install_is_not_restarted() {
|
||||
#[test]
|
||||
fn the_idle_strategies_only_apply_state() {
|
||||
assert_eq!(
|
||||
plan(Strategy::NotNeeded, &CjkInstall::Unknown),
|
||||
plan_with_offline(Strategy::NotNeeded, &CjkInstall::Unknown, false),
|
||||
Step::Apply(CjkInstall::NotNeeded)
|
||||
);
|
||||
assert_eq!(
|
||||
plan(Strategy::System { family: "SimSun" }, &CjkInstall::Unknown),
|
||||
plan_with_offline(
|
||||
Strategy::System { family: "SimSun" },
|
||||
&CjkInstall::Unknown,
|
||||
false
|
||||
),
|
||||
Step::Apply(CjkInstall::System {
|
||||
family: "SimSun".to_owned()
|
||||
})
|
||||
@@ -221,9 +229,15 @@ fn the_idle_strategies_only_apply_state() {
|
||||
// 复审 r2 P2-2 ② 改判:**下载中一律 Skip**,即使策略说「探测不出」。
|
||||
// 上一版在这里断言 `Apply(Unprobeable)`,理由是「否则界面会停在正在下载」——那个理由只对
|
||||
// 僵死成立(线程 panic),而在飞是常见情形:线程还在下,状态却被改成「无法探测」,下完又
|
||||
// 翻回「已就绪」,状态行在几十秒里来回翻。僵死由 worker 的 catch_unwind 兜底。
|
||||
// 翻回「已就绪」,状态行在几十秒里来回翻。「僵死」那一半按构建档分两说(worker 模块文档):
|
||||
// unwind 档(dev/test/fast)由 `catch_unwind` 兜底;发布档 `panic = "abort"` 是进程退出,
|
||||
// 不存在停在 Downloading 的状态。
|
||||
assert_eq!(
|
||||
plan(Strategy::Unprobeable, &CjkInstall::Downloading { bytes: 1 }),
|
||||
plan_with_offline(
|
||||
Strategy::Unprobeable,
|
||||
&CjkInstall::Downloading { bytes: 1 },
|
||||
false
|
||||
),
|
||||
Step::Skip,
|
||||
"在飞的下载不许被别的策略改写状态"
|
||||
);
|
||||
@@ -244,7 +258,7 @@ fn every_strategy_skips_while_a_download_is_in_flight() {
|
||||
Strategy::Unprobeable,
|
||||
] {
|
||||
assert_eq!(
|
||||
plan(strategy, &downloading),
|
||||
plan_with_offline(strategy, &downloading, false),
|
||||
Step::Skip,
|
||||
"{strategy:?}:下载中不许改状态、不许起第二条线程"
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user