diff --git a/client/electron/test/run-all.mjs b/client/electron/test/run-all.mjs index 0ea5c3e..e3f3e36 100644 --- a/client/electron/test/run-all.mjs +++ b/client/electron/test/run-all.mjs @@ -2364,11 +2364,11 @@ let selfCheckRuns = 0; * ⇒ 样本与生产扫描调的是**同一个** `declaredSelfTests`(不是抄一份)。 */ const FORM_SAMPLES = [ - ['function 声明', 'function fooSelfTest() {}\n'], - ['箭头函数', 'const fooSelfTest = () => {};\n'], - ['async function', 'async function fooSelfTest() {}\n'], - ['名与括号间有空格', 'function fooSelfTest (a) {}\n'], - ['const = async (…', 'const fooSelfTest = async (a) => {};\n'], + ['function 声明', 'function fooSelfTest() {}\n', /^function fooSelfTest\(\)/], + ['箭头函数', 'const fooSelfTest = () => {};\n', /^const fooSelfTest = \(\) =>/], + ['async function', 'async function fooSelfTest() {}\n', /^async function fooSelfTest\(\)/], + ['名与括号间有空格', 'function fooSelfTest (a) {}\n', /^function fooSelfTest \(/], + ['const = async (…', 'const fooSelfTest = async (a) => {};\n', /^const fooSelfTest = async \(/], ]; /* * ★★ **样本表本身也必须被钉住**(我自己变异出来的 M45)。 @@ -2404,6 +2404,40 @@ let selfCheckRuns = 0; console.log(`RED 这些样本不在要求清单里(加了样本却没说是为了守哪种写法):${stray.join('、')}`); reds.push(`(自检)\`FORM_SAMPLES\` 有多余样本未登记进 \`REQUIRED_FORMS\`:${stray.join('、')}`); } + /* + * ★★ **标签不许撒谎**(我自己变异出来的 M47,比 M45 更深一层)。 + * + * 实测:把 `['箭头函数', 'const fooSelfTest = () => {};']` 的**内容**换成 + * `'function fooSelfTest() {}'`(**标签不动**、样本个数不变)⇒ 默认跑 **0 条 RED**、`red` 仍是 9。 + * ⇒ M45 修的是"样本**个数/名字**少了要红",但**名字对不上内容**当时无人管: + * 表上写着覆盖"箭头函数",而那份样本**根本不是箭头函数**。 + * + * ★ 后果我实测过,而且它**让报警自己少说话**(不只是少覆盖): + * 在上面那个撒谎标签的前提下,把 `const` 那条正则删掉(⇒ **箭头写法真的认不出来了**), + * 报警只点名 `const = async (…`,**"箭头函数"一个字都不提**(`grep -c` = **0**)。 + * ⇒ 覆盖表**声称**覆盖了箭头函数,而报警里那一格**消失了**。 + * 这正是我们这一路最怕的形状:**该说话的地方没说话,而账面上看不出少了什么。** + * + * ⇒ 修法:每个样本再带一条**见证**(witness)——"这条样本为什么算那种写法"的**机械**判据: + * ① 样本内容必须满足自己的见证(⇒ 标签与内容不符 = 红); + * ② 见证必须**能区分**:至少要能否掉另一条样本(否则 `/./` 这种空见证也算"覆盖")。 + * ⇒ 标签是**散文**,见证是**结构**;把"这条样本是哪一种写法"从散文挪进结构。 + */ + const liar = FORM_SAMPLES.filter(([, src, w]) => !w.test(src)).map(([name]) => name); + if (liar.length) { + console.log(`RED 这些样本**标签与内容不符**(内容不满足它自己的见证):${liar.join('、')}` + + ' ⇒ 覆盖表在说谎,而报警会因此**少说话**'); + reds.push(`(自检)\`FORM_SAMPLES\` 标签与内容不符:${liar.join('、')}` + + ' —— 声称覆盖了那种写法,而那份样本不是它'); + } + const vacuous = FORM_SAMPLES.filter(([name, , w]) => + !FORM_SAMPLES.some(([other, otherSrc]) => other !== name && !w.test(otherSrc))).map(([n]) => n); + if (vacuous.length) { + console.log(`RED 这些见证**区分不了任何东西**(对别的样本也成立):${vacuous.join('、')}` + + ' ⇒ 见证表自己退化成"永远通过"'); + reds.push(`(自检)\`FORM_SAMPLES\` 的见证对别的样本也成立:${vacuous.join('、')}` + + ' —— 空见证等于没覆盖'); + } const missed = FORM_SAMPLES.filter(([, src]) => !declaredSelfTests(src).includes('fooSelfTest')); if (missed.length) { console.log(`RED 发现规则认不出这些写法(⇒ 那种写法写了自检也不会被接线防线看见):` @@ -2438,7 +2472,8 @@ let selfCheckRuns = 0; console.log(`自检段:${SELFTESTS.length} 个自检已在**默认路径**内跑过` + `(${SELFTESTS.map(([n]) => `--${n}`).join('、')});` + `源码里 ${declared.length} 个 \`*SelfTest\` 函数**全部**在册(无"写了没接线");` - + `发现规则在 ${FORM_SAMPLES.length} 种写法上都有对照(要求 ${REQUIRED_FORMS.length} 种,缺一即红)`); + + `发现规则在 ${FORM_SAMPLES.length} 种写法上都有对照(要求 ${REQUIRED_FORMS.length} 种,缺一即红;` + + '每条样本都带能区分它自己的见证)'); } }