二七王:补 9 处 design 规则的正/反/边界用例(均通过变异检验)
对 design §1~§12 重做「每条规则是否三类用例齐全」的审计。此前的覆盖矩阵按 「被测函数」组织,容易漏掉跨函数才体现的规则,本轮补齐 9 处: - G1/G2 §4.2 叫分:下限5与非首家不叫接受,负数/缺call/步进外/同分拒; 「不叫即退出本局叫分」——反悔再叫被 SEAT 拒、callproc 不变、仍轮到下一家 - G3 §4.5 埋牌:非庄家 SEAT、step2/step5 STEP、7张/9张/空数组 PARAM - G4 §5.1 每轮由上一轮牌面最大的一方先出(闲1赢/闲2赢两种) - G5 §6.2 闲家赢计入台面全部分牌(含庄家自己打出的)、庄家赢作废、 两个闲家谁赢结果一致 - G6 §8 算奖快照:庄家埋后28(已埋不在内)、闲家28、投降36、打出后不缩水 - G7 §3 对子只认同花色同点数两副:跨花色副7/副2、正副7、大小王均不成对 - G8 §6.3 赢末轮的牌不全是主牌就不扣底(副牌拖拉机/混合出牌/顺序颠倒) - G9 §11 无超时托管守卫:对局阶段 min_ontimeout 调用次数必须为 0, 将来有人加超时代打就会转红 每条都在副本上注入违反该规则的改动确认转红(7 组变异全部被抓住)。 顺带修一个测试自身的问题:mkBury 桩缺 do_burycard,导致「埋牌张数校验被 改松」这类变异表现为整个文件崩溃而非某条断言转红,后续断言全不执行。桩已 补完整到能走完成功路径。 全套单测 462 → 511 项全绿。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -147,7 +147,7 @@
|
||||
|
||||
## 5. 当前状态小结 —— ✅ DoD 达成,P0/P1/P2 全部完成
|
||||
|
||||
**共 361 项断言全绿**(`test_arith` 106 / `test_callgrade` 6 / `test_config` 19 / `test_deal` 12 / `test_desk` 6 / `test_follow` 50 / `test_input` 34 / `test_paiju` 31 / `test_rpc` 68 / `test_success` 29)。
|
||||
**共 511 项断言全绿**(`test_arith` 122 / `test_calc` 49 / `test_callgrade` 6 / `test_config` 19 / `test_deal` 12 / `test_desk` 6 / `test_endgame` 25 / `test_follow` 58 / `test_followdiff` 12 / `test_input` 34 / `test_paiju` 50 / `test_rpc` 89 / `test_success` 29)。其中 `test_calc`/`test_followdiff` 见 §7、G1~G9 见 §8。
|
||||
|
||||
design 全部服务端可验证章节均有正/反/边界单测:
|
||||
- **§2 构成**:`test_deal` 92张/去3-4/三家28+底8/分值。
|
||||
@@ -182,6 +182,55 @@ design 全部服务端可验证章节均有正/反/边界单测:
|
||||
| §9 出牌历史按查牌模式门控 | `get_deskinfo` | 反:不查牌房无 `pushlist`;正:可查牌房有 `pushlist`;边界:两种模式下当前轮桌面牌 `playproc.cards` 都必须恢复 | `test_rpc` | ✅ 4 |
|
||||
| §3 相邻链花色 | `is_continuous` | 正:同花色 8-6 连;反:三组跨花色 8-6 不连;反:差 2 但非 8/6 不连 | `test_arith` | ✅ 5 |
|
||||
|
||||
**关于超时**:`countdown` 只作展示、服务端不做任何超时动作,这是 design §11 确认的规则(并非缺口),因此**没有也不需要「超时自动操作」的用例**;反过来,若将来有人给服务端加了超时代打,那才是违反 design §11,应由核对拦下。
|
||||
**关于超时**:`countdown` 只作展示、服务端不做任何超时动作,这是 design §11 确认的规则(并非缺口),因此**没有也不需要「超时自动操作」的用例**;反过来,若将来有人给服务端加了超时代打,那才是违反 design §11——现已由 `test_rpc` 的**守卫用例**拦下(见 §8 G9)。
|
||||
|
||||
---
|
||||
|
||||
## 7. 第五轮:按 design 原文另写参考实现的差分测试
|
||||
|
||||
> 前六节的用例都是**手写的场景枚举**——覆盖的是"我想到的情况"。第五轮补两组**差分测试**:把 design 的规则整条转写成参考实现,与代码大面积对拍,覆盖手写用例想不到的组合。
|
||||
|
||||
| 文件 | 覆盖 | 规模 |
|
||||
| --- | --- | --- |
|
||||
| `test_calc.js` | §7 算子全量对拍:参考实现逐字转写自 §7.1/§7.2/§7.3 判定表,比 base / Q / 判定倍率 / 最终子数 | 2 模式 × 14 档 × grade 0~260 = **7308 格**,另按 design 的 17 张表逐格抽查 **141 个写死的最终子数** |
|
||||
| `test_followdiff.js` | §5.2 跟牌强制层级穷举差分:参考裁定按原文写,对每手牌**枚举全部 C 张出牌组合**逐个对拍 | 约 **11 万组** |
|
||||
|
||||
**差分测试的强度取决于造牌器,不取决于对拍逻辑。** 第一版 `test_followdiff` 用纯随机抽牌跑 7.8 万组全绿,但把 `follow_tractor_cover_ok` 整个关掉**依然全绿**——因为唯一能区分"只出零散对子"与"先凑最长拖拉机"的形状是「同花色三组互不相邻的两连对」(12 张),随机抽根本抽不出来。故:
|
||||
|
||||
- 随机源必须是**固定种子 PRNG**(不用 `Math.random`),保证用例集可复现;
|
||||
- 关键结构必须用**确定性手牌**钉死(`structHands()`),不能指望随机覆盖到;
|
||||
- 注意别让掺入的其他花色把手牌撑过枚举上限而被**静默跳过**(踩过一次)。
|
||||
|
||||
---
|
||||
|
||||
## 8. 第五轮:逐规则的正/反/边界补全
|
||||
|
||||
> 对 design §1~§12 重新做了一次"每条规则是否三类用例齐全"的审计。覆盖面本来就广,但仍有 9 处 design 明文规则缺用例(多是**规则本身**而非入参校验,前几轮的矩阵按"被测函数"组织,容易漏掉这类"跨函数才体现"的规则)。
|
||||
|
||||
| # | design | 规则 | 补的用例(正/反/边界) | 文件 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| G1 | §4.2 | 暂定庄家必须叫、其后才可"更低或不叫" | 边界:下限 5 接受;正:非首家 `call=0` 接受;反:负数 / 缺 `call`(NaN) / 步进外小值 1 / 与当前叫分相同 均拒 | `test_rpc` |
|
||||
| G2 | §4.2 | **"不叫"即退出本局叫分,轮次跳过他** | 正:首家叫 65 后轮到 seat1;正:seat1 不叫后跳到 seat2;反:seat1 反悔再叫 → SEAT 拒、`callproc` 不变、仍轮到 seat2、未产生庄家 | `test_rpc` |
|
||||
| G3 | §4.5 | 埋牌仅庄家、仅埋牌阶段、恰 8 张 | 反:非庄家 → SEAT;反:step2/step5 埋 → STEP;边界:7 张 / 9 张 / 空数组 → PARAM | `test_rpc` |
|
||||
| G4 | §5.1 | **每轮由上一轮牌面最大的一方先出** | 正:闲 1 赢 → 下一轮 `start/currseat` 都是 1;边界:闲 2 赢 → 改由闲 2 先出 | `test_paiju` |
|
||||
| G5 | §6.2 | 闲家赢 → 台面**全部**分牌计入;庄家赢 → 分牌作废 | 反:庄赢 → 下发面无 `grade`、闲家捡分 0;正:闲 1 赢 → 15 分(**含庄家自己打出的 ♥5**);边界:闲 2 赢结果与闲 1 赢一致("两个闲家谁大不影响") | `test_paiju` |
|
||||
| G6 | §8 | 算奖快照的时间点与静态性 | 正:庄家 = 埋牌后 28 张、已埋 8 张不在内;正:闲家 = 发牌后 28 张;边界:投降局庄家 = 发牌+暗牌 36 张;边界:之后打出 10 张,快照仍是同样的 28 张 | `test_paiju` |
|
||||
| G7 | §3 | **对子只认同花色同点数的两副** | 正:同花色两副 ♥7/♥2/大王成对;反:♥7+♣7、♥2+♣2、正7+副7、正2+副2、大王+小王 均不成对;边界:四张跨花色 7/2 组不出拖拉机,而正7对+副7对可以 | `test_arith` |
|
||||
| G8 | §6.3 | 赢末轮的牌不全是主牌就不扣底 | 反:副牌两连对赢 → 0;反:混合出牌(主K+副K)→ 0;边界:主副提交顺序颠倒仍判 0 | `test_arith` |
|
||||
| G9 | §11 | **无超时托管**(守卫) | 守卫:叫分→选主→埋牌→出牌全程 `min_ontimeout` 调用次数为 0。将来若有人加"超时自动出牌/代打",必然要注册定时器,这条即转红 | `test_rpc` |
|
||||
|
||||
**每条都做了变异检验**(在副本上注入违反该规则的改动,确认对应断言转红):
|
||||
|
||||
| 注入的缺陷 | 转红的断言 |
|
||||
| --- | --- |
|
||||
| 去掉 `mod.jiaofen` 的"非当前叫分位"校验 | G2 三条 |
|
||||
| 埋牌张数 `!= 8` 放宽为 `< 1` | G3 两条边界 |
|
||||
| §6.2 改成庄家赢也累计闲家捡分 | G5 一条 |
|
||||
| 下一轮改为固定庄家先出 | G4 两条 |
|
||||
| 算奖快照不排除已埋的牌 | G6 两条 + 亮牌快照一条 |
|
||||
| `get_pairlist` 放宽为"只看点数" | G7 五条 |
|
||||
| 在 `mod.chupai` 里注册一个定时器 | G9 一条 |
|
||||
|
||||
> 过程中的一个教训:M2(埋牌张数)第一次跑出来是**整个文件崩溃**而不是干净的 FAIL——因为 `mkBury` 桩缺 `do_burycard`,校验一被改松就走到成功路径抛异常,后面的断言全不执行。**桩要完整到能走完成功路径**,否则"校验被改松"这类变异只会表现为崩溃,定位与信号都变差。已修。
|
||||
|
||||
> 原列在此处的两项「待外部输入」均已由规则设计者拍板:「不查牌模式是否屏蔽出牌历史」确认屏蔽,已改 design §9 + 代码 + 用例(见上表);「超时托管默认动作」确认维持现状、不做超时动作,已写入 design §11。至此测试计划无待外部输入项。
|
||||
|
||||
Reference in New Issue
Block a user