refactor(download): 纯搬移为 M289 腾出行数余量(config 单测 / engine 只读查询面)
两个文件都是 400 行零余量的硬线,本 mission 要加超时字段与失速诊断,先纯搬移: * `config.rs` 的 `#[cfg(test)] mod tests`(174 行)→ `config/tests.rs`, 原文件用 `#[cfg(test)] #[path = "config/tests.rs"] mod tests;` 声明; * `engine.rs` 的七个只读 getter(`config` / `concurrency_probe` / `client` / `region` / `mirrors` / `health` / `cache`,44 行)→ `engine/inspect.rs`。 逐字节未改:搬移块去缩进后与 HEAD 原文 `diff` 均为 exit 0。 行为零变化(同一批测试仍全绿);新文件都在 `crates/core/src/download/**` 内, 外部路径(`download::config::EngineConfig` 等)不变。
This commit is contained in:
1 parent
8b48c494cd
commit
61c8a4eff9
4 files changed
+237
-219
No files matched your search
@@ -223,178 +223,5 @@ pub fn publish(cache_root: &Path, next: DownloadTuning) -> bool {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::setting::keys::{launcher_schema, launcher_version};
|
||||
|
||||
/// **守门③**:schema 的默认值 / 区间 / 键名与 `EngineConfig::default()` / 调优默认值取同一组常量。
|
||||
/// 变异证明(只改实现侧):`EngineConfig::default()` 的并发写回 64、schema 默认值写成 16、
|
||||
/// `MAX_CONCURRENCY` 改了而 schema 仍写 64 ⇒ 各自红。
|
||||
#[test]
|
||||
fn the_schema_contract_is_single_sourced() {
|
||||
let schema = launcher_schema();
|
||||
assert_eq!(schema.version(), launcher_version());
|
||||
let cfg = EngineConfig::default();
|
||||
let tune = DownloadTuning::default();
|
||||
|
||||
// 并发 1~64(0 张许可没意义);尝试次数 **0**~10(P2-1:0 = 只试一次,旧配置里真有)。
|
||||
let contract: [(&str, i64, i64, usize); 2] = [
|
||||
(
|
||||
KEY_CONCURRENCY,
|
||||
i64::try_from(DEFAULT_MAX_CONCURRENCY).expect("装得下"),
|
||||
1,
|
||||
MAX_CONCURRENCY,
|
||||
),
|
||||
(
|
||||
KEY_RETRY_LIMIT,
|
||||
i64::from(DEFAULT_MAX_ATTEMPTS_PER_SOURCE),
|
||||
0,
|
||||
usize::try_from(MAX_ATTEMPTS_PER_SOURCE).expect("装得下"),
|
||||
),
|
||||
];
|
||||
for (key, default, min, max) in contract {
|
||||
let spec = schema.spec(key).expect("键已登记");
|
||||
assert_eq!(spec.default, serde_json::json!(default), "{key}");
|
||||
assert_eq!(
|
||||
spec.kind,
|
||||
crate::setting::spec::ValueKind::Int {
|
||||
min,
|
||||
max: i64::try_from(max).expect("装得下"),
|
||||
},
|
||||
"{key}"
|
||||
);
|
||||
}
|
||||
assert_eq!(cfg.max_concurrency, DEFAULT_MAX_CONCURRENCY);
|
||||
assert_eq!(tune.max_concurrency, DEFAULT_MAX_CONCURRENCY);
|
||||
assert_eq!(cfg.max_attempts_per_source, DEFAULT_MAX_ATTEMPTS_PER_SOURCE);
|
||||
assert_eq!(
|
||||
tune.max_attempts_per_source,
|
||||
DEFAULT_MAX_ATTEMPTS_PER_SOURCE
|
||||
);
|
||||
}
|
||||
|
||||
/// `SettingSpec.doc` 是 `&'static str`(`concat!` 插不进常量),描述里的数字只能手写——这条钉住它,
|
||||
/// 改常量不改文案就红(`catalog.rs` 会把这些 doc 当 JSON schema 的 description 发出去)。
|
||||
#[test]
|
||||
fn the_key_docs_quote_the_real_limits() {
|
||||
let schema = launcher_schema();
|
||||
let doc = |key: &str| schema.spec(key).expect("键已登记").doc;
|
||||
assert!(doc(KEY_CONCURRENCY).contains(&format!("1~{MAX_CONCURRENCY}")));
|
||||
assert!(doc(KEY_CONCURRENCY).contains(&format!("出厂 {DEFAULT_MAX_CONCURRENCY}")));
|
||||
assert!(doc(KEY_RETRY_LIMIT).contains(&format!("出厂 {DEFAULT_MAX_ATTEMPTS_PER_SOURCE}")));
|
||||
}
|
||||
|
||||
/// 未填 / 越界回落默认(不阻断下载);**`retry_limit: 0` 是合法值**,语义 = 只试一次。
|
||||
///
|
||||
/// 变异证明:把并发的区间过滤删掉 ⇒ `0` / `9999` 两条红;把尝试次数的 `.max(1)` 删掉 ⇒
|
||||
/// `0 → 1` 那条红(引擎会拿到 0 次尝试);把 `0` 判成越界 ⇒ 同样红。
|
||||
#[test]
|
||||
fn missing_or_illegal_values_fall_back_to_the_defaults() {
|
||||
assert_eq!(
|
||||
DownloadTuning::from_settings(None, None, None),
|
||||
DownloadTuning::default()
|
||||
);
|
||||
|
||||
let just_over = i64::try_from(MAX_CONCURRENCY).expect("上限装得下") + 1;
|
||||
for bad in [0_i64, -1, 9_999, just_over] {
|
||||
let tune = DownloadTuning::from_settings(Some(bad), None, None);
|
||||
assert_eq!(tune.max_concurrency, DEFAULT_MAX_CONCURRENCY, "{bad}");
|
||||
}
|
||||
// 0 与 1 都 = 只试一次:旧配置里的 0 不许回落成出厂 3(那正是「界面 0、引擎 3」)。
|
||||
for zero_or_one in [0_i64, 1] {
|
||||
let tune = DownloadTuning::from_settings(None, Some(zero_or_one), None);
|
||||
assert_eq!(tune.max_attempts_per_source, 1, "{zero_or_one}");
|
||||
}
|
||||
for bad in [-1_i64, 9_999] {
|
||||
let tune = DownloadTuning::from_settings(None, Some(bad), None);
|
||||
assert_eq!(
|
||||
tune.max_attempts_per_source,
|
||||
DEFAULT_MAX_ATTEMPTS_PER_SOURCE
|
||||
);
|
||||
}
|
||||
|
||||
let tune = DownloadTuning::from_settings(Some(2), Some(2), None);
|
||||
assert_eq!(tune.max_concurrency, 2);
|
||||
assert_eq!(tune.max_attempts_per_source, 2);
|
||||
}
|
||||
|
||||
/// 三态:**空串 ≠ 关**(这条是「设置项说假话」的高发点,M197 的键语义同源)。
|
||||
#[test]
|
||||
fn empty_gh_proxy_means_follow_builtin_not_off() {
|
||||
assert_eq!(gh_proxy_override(""), GhProxyOverride::Builtin);
|
||||
assert_eq!(gh_proxy_override(" "), GhProxyOverride::Builtin);
|
||||
for off in [
|
||||
"off", "OFF", " none ", "direct", "disable", "disabled", "no",
|
||||
] {
|
||||
assert_eq!(gh_proxy_override(off), GhProxyOverride::Off, "{off}");
|
||||
}
|
||||
assert_eq!(
|
||||
gh_proxy_override(" https://gh.example/ "),
|
||||
GhProxyOverride::Prefix("https://gh.example/".to_string())
|
||||
);
|
||||
// 未填(键不存在)也是 Builtin,不是 Off。
|
||||
assert_eq!(
|
||||
DownloadTuning::from_settings(None, None, None).gh_proxy,
|
||||
GhProxyOverride::Builtin
|
||||
);
|
||||
}
|
||||
|
||||
/// `apply_gh_proxy` 的三档真的改到档案上、并且**改到候选链上**(`expand()` 读的就是档案里那个
|
||||
/// 前缀;自定义前缀那一档的链断言在 `shared.rs`)。变异证明:`Off` 分支改成原样返回 ⇒ `off` 红。
|
||||
#[test]
|
||||
fn gh_proxy_override_reaches_the_profile_and_the_chain() {
|
||||
use crate::download::mirrors::{MirrorTable, SOURCE_GH_PROXY};
|
||||
use crate::download::types::ResourceKind;
|
||||
|
||||
let url = "https://github.com/o/r/releases/download/v1/a.jar";
|
||||
let table = MirrorTable::builtin();
|
||||
let sources = |profile: &RegionProfile| -> Vec<String> {
|
||||
table
|
||||
.expand(url, ResourceKind::Other, profile)
|
||||
.into_iter()
|
||||
.map(|candidate| candidate.source)
|
||||
.collect()
|
||||
};
|
||||
|
||||
let mirror_first = RegionProfile::mirror_first(0);
|
||||
let kept = DownloadTuning::default().apply_gh_proxy(mirror_first.clone());
|
||||
assert_eq!(kept.gh_proxy, mirror_first.gh_proxy, "Builtin 不该动档案");
|
||||
assert!(
|
||||
sources(&kept).contains(&SOURCE_GH_PROXY.to_string()),
|
||||
"出厂套前缀"
|
||||
);
|
||||
|
||||
let off = DownloadTuning::from_settings(None, None, Some("off"))
|
||||
.apply_gh_proxy(mirror_first.clone());
|
||||
assert!(
|
||||
!sources(&off).contains(&SOURCE_GH_PROXY.to_string()),
|
||||
"关了就没候选"
|
||||
);
|
||||
|
||||
let prefix = DownloadTuning::from_settings(None, None, Some("https://gh.example/"))
|
||||
.apply_gh_proxy(mirror_first);
|
||||
assert_eq!(prefix.gh_proxy.as_deref(), Some("https://gh.example/"));
|
||||
assert!(prefix.gh_proxy_enabled(), "前缀生效");
|
||||
}
|
||||
|
||||
/// 每个数据根的调优互不串味(一个根改成 2 不该改另一个根的引擎)。
|
||||
/// 变异证明:把 `wanted`/`publish` 的键改回单一进程级槽位 ⇒ 第二个根读到 2,红。
|
||||
#[test]
|
||||
fn tuning_is_per_cache_root_and_no_change_is_reported_as_such() {
|
||||
let a = PathBuf::from("/tmp/ull-tuning-a");
|
||||
let b = PathBuf::from("/tmp/ull-tuning-b");
|
||||
assert_eq!(wanted(&a), DownloadTuning::default());
|
||||
|
||||
let changed = DownloadTuning::from_settings(Some(2), None, None);
|
||||
assert!(publish(&a, changed.clone()), "真变了要报变更");
|
||||
assert_eq!(wanted(&a), changed);
|
||||
assert!(!publish(&a, changed.clone()), "同值不该报变更");
|
||||
assert_eq!(wanted(&b), DownloadTuning::default(), "别的根不受影响");
|
||||
|
||||
assert!(
|
||||
publish(&a, DownloadTuning::default()),
|
||||
"恢复默认也是一次变更"
|
||||
);
|
||||
assert_eq!(wanted(&a), DownloadTuning::default());
|
||||
}
|
||||
}
|
||||
#[path = "config/tests.rs"]
|
||||
mod tests;
|
||||
Reference in new issue
Block a user