Files
MetonaSqlark/jest.config.cjs
T
thzxx 0b44620721 fix(v0.8.0): 全量回归审查 —— 1 处 P0 数据丢失 + 4 处 P1 + 9 处 P2 根因修复
方法:四个对抗性子代理分头审查(数据正确性 / 文档宣称 vs 实现 / 公共 API 契约 /
测试质量),每条结论要求可复现证据;逐条复核 + 探针确认 + 变异验证(40 项全部
被对应用例拦住)。

P0:事务活跃期间 repair()/close()/周期 checkpoint 推进 WAL 水位 → 已 COMMIT 的
事务整批消失且恢复报告"干净"。根因 hasPendingFlushData()/computeDurableLsn()
不看 txnSnapshot;守卫此前只在 CheckpointManager 两个回调里。修复:守卫下沉到
computeDurableLsn() 与 advanceWalCheckpoint() 入口(唯一实现)。

P1:
- WAL 前缀缺失丢弃整段活分片(回退上一代 manifest 时 kept 为空)→ 前缀缺失单独
  记录,后缀照常重放;仅 fromLsn === 0 时才算真异常
- 孤儿回收门槛只看引擎层 dataLossSuspected,漏掉 LSM 层被丢的 SSTable →
  统一 describeRecoveryDamage() 聚合判定(损坏时绝不删"引用不到"的文件)
- vacuum() 逐层压缩绕过维护链 → vacuumLevels() 每层作为维护链任务执行
- reclaimRetiredNow() 无视在途读者(读者把"已退休"读成"文件损坏")→ 有读者时
  退化为延迟回收

P2:WAL 记录级 CRC 损坏不计数不上报;旧格式表结构记录形状损坏静默当空库;
bloomFilterBitsPerKey 配置被接受却完全不生效(构建器写死默认值,实现缺陷);
幽灵 meta;介质读故障等于文件损坏的语义无用例;manifest 回读校验两条守卫无用例;
文件名≠载荷世代判定无用例;pageIdWatermark 单调性无用例;分片号两条真实不变量
无用例。

覆盖率口径(第二处漏洞):interface.ts 混着三个运行时函数(cloneRow 等)却被
描述为"纯类型、不纳入统计" → 实现搬到 src/engine/row_clone.ts;搬完门禁真的
失败(functions 93.84% < 94%),补测退化路径后通过。

测试质量:3 条空壳用例改值级断言;1 条"全损坏"用例实际只走缓存 → 拆成两条真
用例;5 秒墙钟 race 改门控 + 失败上限;setTimeout 改 whenIdle();<= 收紧为 <。

变异脚本加固:正控(干净基线必须全绿)、编译失败/0 用例单独归类、300s 超时、
逐字节 sha256 恢复校验、O_EXCL 进程锁、锚点唯一性;变异 22 → 40 项。

文档两轮订正(16 + 11 条不成立宣称):MVCC 快照隔离、backup 一致性快照、
"空洞检测截断"、体积(251,109 B / gzip 63,145 B)、测试与覆盖率数字、
"5 种存储引擎"、Tree-shakable、错误码表补 16 个码、恢复报告字段、已知限制
(回退单向 / 多实例依赖 Web Locks / manifest 体积 / 尾部 WAL 分片不可识别)。

验证:常规套件 92 套件 / 1980 用例全绿;覆盖率 90.59 / 82.59 / 94.14 / 93.50
(阈值 90/82/94/93);e2e 14/14(真实 Chromium + OPFS + CDP 崩溃);
重型套件 4 套件 / 27 用例;变异 40/40;lint + 两份 tsc 干净;dist 已重建。
2026-09-15 16:33:40 +08:00

63 lines
2.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
module.exports = {
testEnvironment: 'jsdom',
setupFiles: ['./jest.setup.js'],
transform: {
'^.+\\.ts$': 'babel-jest',
},
transformIgnorePatterns: [
'/node_modules/(?!(@rollup)/)',
],
moduleFileExtensions: ['ts', 'js', 'json'],
// 默认 testMatch 不会发现 __tests__ 之外、名为 helpers/ 目录里的 .test.ts 文件,
// 因此显式声明匹配规则(v0.8.0:测试基座自身的自测放在 tests/helpers/ 下)。
testMatch: ['**/*.test.ts'],
// Playwright e2etests/e2e/)不属于 jest 单元测试
testPathIgnorePatterns: [
'/node_modules/',
'/tests/e2e/',
],
//
// v0.8.0 覆盖率口径修正(根治):
//
// 此前为 `'!src/**/index.ts'` —— 这条 glob 把 15 个文件整体排除,其中包含
// src/engine/aria/index.tsAriaEngine 主实现 2282 行)、src/engine/kvstore/index.ts
// KVStore 本体)、src/hybrid/index.ts、src/migration/index.ts 等**实现文件**
// 而非桶文件。后果:发布的"90.1% 行覆盖率"只在约 75% 的可执行源码上成立,
// 且 v0.2.6 曾在 CHANGELOG 里承认过同类问题("91.0% 为排除 Aria 模块的陈旧数据")
// 后又在 v0.5.1 以另一种写法复发。
//
// 现在只排除**确实没有可执行语句**的文件(纯类型声明),并且逐个显式列出、
// 附理由 —— 新增文件默认纳入统计,不会再被 glob 静默吞掉。
//
collectCoverageFrom: [
'src/**/*.ts',
// 纯类型声明:可执行语句 0 行(接口/类型别名),纳入统计只会稀释分母
'!src/engine/interface.ts',
'!src/query/ast.ts',
],
coverageDirectory: 'coverage',
coverageReporters: ['text', 'lcov'],
//
// v0.8.0 覆盖率门禁(此前完全不存在:jest.config 与 CI 都没有任何阈值,
// 覆盖率从 90% 掉到 60% 也全绿)。
//
// 阈值 = 在**修正口径后**(不再排除实现文件)实测的真实基线,下取整到整数百分点。
// 历史基线(2026-08-15):Statements 90.66% / Branches 82.94% / Functions 94.36% / Lines 93.43%
// v0.8.0 收尾实测(2026-09-151980 用例):Statements 90.59% / Branches 82.59% /
// Functions 94.14% / Lines 93.50%
//
coverageThreshold: {
global: {
statements: 90,
branches: 82,
functions: 94,
lines: 93,
},
},
verbose: true,
// 注意:forceExit 会掩盖句柄/定时器泄漏。v0.8.0 保留它以便常规开发快速迭代,
// 但新增了独立的 `npm run test:leaks`--detectOpenHandles 且不 forceExit)用于泄漏检查。
forceExit: true,
testTimeout: 15000,
};