测试(计费): 固化会员目录价格与泥点随 rank 递增的不变量

在 catalog 文档写明升级补差依赖的单调性不变量,并新增回归测试断言 rank 越高月价、年价、每期泥点严格递增

Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
2026-10-02 19:23:36 +08:00
parent 58a79a2e4e
commit 8e1471d7af
@@ -8,6 +8,10 @@
//! 价格是**后端唯一真相**,前端展示价只用于渲染,下单时后端按同一份目录重算。
//!
//! 本期模型权限只落字段、只用于展示,不做服务端拦截;并发上限只做判定,同样不拦截。
//!
//! 目录不变量:按 `rank` 升序,月价、年价、每期泥点必须**严格递增**(`Normal` 为 0)。
//! 升级补差按 `rank` 判定、按价差 / 点差计价,若高 `rank` 的行反而更便宜或更少点,
//! `saturating_sub` 会把补差静默算成 0;后台改价时不得破坏该不变量。
use serde::{Deserialize, Serialize};
@@ -298,6 +302,35 @@ mod tests {
assert!(is_unlimited_concurrency(max.concurrent_job_limit));
}
#[test]
fn enabled_plans_increase_in_price_and_points_with_rank() {
// 中文注释:升级补差依赖「rank 越高、价格与每期泥点越大」这一不变量;
// 后台改价破坏它时,升级会静默算成 0,因此把种子目录的不变量固化成回归断言。
let mut rows = runtime_profile_membership_plan_catalog();
rows.sort_by_key(|row| row.rank);
for pair in rows.windows(2) {
let (lower, higher) = (&pair[0], &pair[1]);
assert!(
higher.month_price_cents > lower.month_price_cents,
"{} 的月价必须高于 {}",
higher.title,
lower.title
);
assert!(
higher.year_price_cents > lower.year_price_cents,
"{} 的年价必须高于 {}",
higher.title,
lower.title
);
assert!(
higher.period_points > lower.period_points,
"{} 的每期泥点必须高于 {}",
higher.title,
lower.title
);
}
}
#[test]
fn year_price_is_stored_independently_of_the_month_price() {
// 中文注释:年价是独立可配置字段,这里断言的是种子数值本身,而不是月价 ×10 的推导关系。