bf63766d88
- spacetime-editor-idempotency-smoke.test.ts:terminates a live standalone-shaped child process 补第三参 20_000,并加注释写明这是负载敏感的局部超时。 - 性质说明:这是局部有界超时,不是放宽判据。断言 child.exitCode !== null || child.signalCode !== null 一字未动,全局 testTimeout 与 maxThreads 也未动。 - 为什么不加注入桩:该用例的存在意义就是验真实杀进程路径(spawn 真实常驻 node → stopStandalone → Windows 上 spawn taskkill /PID /T /F 杀进程树并等退出)。加桩等于把被测对象换掉,比放宽断言更隐蔽,因此明确不采用注入桩。 - 为什么需要:这两个真实进程的启动与回收在全并行负载下会明显超过默认 5000ms;单独跑实测 167ms,全仓并行时曾撞满 5000ms 上限。 - 上限仍具约束力:stopStandalone 自身对 SIGTERM → SIGKILL 只有 5s 有界等待,而 runTaskKill 与 SIGKILL 之后的 once(child, 'exit') 都没有内部超时,20s 外层上限仍能抓住真实挂死。 - 已实测第三参在当前 vitest 0.34.6 生效:临时把该值改成 1 时复现 Test timed out in 1ms,改回 20_000 后该文件 4 passed。
89 lines
2.7 KiB
TypeScript
89 lines
2.7 KiB
TypeScript
import { spawn } from 'node:child_process';
|
|
|
|
import { describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
parseProcedureOutput,
|
|
parseSqlRows,
|
|
sanitizeDiagnostic,
|
|
stopStandalone,
|
|
} from './spacetime-editor-idempotency-smoke.mjs';
|
|
|
|
describe('SpacetimeDB editor idempotency smoke parsers', () => {
|
|
it('parses successful and failed procedure SATS results', () => {
|
|
expect(
|
|
parseProcedureOutput(
|
|
'[true,[0,["project-a","owner-a"]],[1,[]]]',
|
|
'create_editor_project_and_return',
|
|
),
|
|
).toEqual({
|
|
ok: true,
|
|
record: ['project-a', 'owner-a'],
|
|
errorMessage: null,
|
|
});
|
|
expect(
|
|
parseProcedureOutput(
|
|
'[false,[1,[]],[0,"幂等创建冲突"]]',
|
|
'create_editor_project_and_return',
|
|
),
|
|
).toEqual({
|
|
ok: false,
|
|
record: null,
|
|
errorMessage: '幂等创建冲突',
|
|
});
|
|
expect(
|
|
parseProcedureOutput(
|
|
'[true,[1,[]],[0,["receipt-owner",[],[]]],[1,[]]]',
|
|
'delete_editor_asset_folder_and_return',
|
|
),
|
|
).toEqual({
|
|
ok: true,
|
|
record: ['receipt-owner', [], []],
|
|
errorMessage: null,
|
|
});
|
|
});
|
|
|
|
it('parses only the rows from one JSON SQL statement', () => {
|
|
const stdout = JSON.stringify([
|
|
{
|
|
schema: { elements: [{ name: 'project_id' }] },
|
|
rows: [['project-a'], ['project-b']],
|
|
total_duration_micros: 12,
|
|
},
|
|
]);
|
|
|
|
expect(parseSqlRows(stdout, 'projects')).toEqual([
|
|
['project-a'],
|
|
['project-b'],
|
|
]);
|
|
expect(() => parseSqlRows('[]', 'projects')).toThrow(
|
|
'invalid result shape',
|
|
);
|
|
});
|
|
|
|
it('redacts an isolated CLI token from diagnostics', () => {
|
|
expect(sanitizeDiagnostic('failed token-private', ['token-private'])).toBe(
|
|
'failed [redacted]',
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('SpacetimeDB editor idempotency smoke cleanup', () => {
|
|
// 本用例真会拉起真实子进程:spawn 一个常驻 node,再由 stopStandalone 在 Windows 上
|
|
// spawn taskkill /PID /T /F 杀进程树并等退出。全并行负载下这两个真实进程的启动与回收
|
|
// 会明显超过 vitest 默认的 5000ms,因此只给这一条设局部有界超时,不动全局 testTimeout
|
|
// 与 maxThreads。这里不加注入桩:本用例的意义就是验真实杀进程路径,加桩等于换掉被测对象。
|
|
// stopStandalone 自身对 SIGTERM → SIGKILL 只有 5s 有界等待,20s 外层上限仍能抓住真实挂死。
|
|
it('terminates a live standalone-shaped child process', async () => {
|
|
const child = spawn(
|
|
process.execPath,
|
|
['-e', 'setInterval(() => {}, 1000)'],
|
|
{ stdio: 'ignore' },
|
|
);
|
|
|
|
await stopStandalone(child);
|
|
|
|
expect(child.exitCode !== null || child.signalCode !== null).toBe(true);
|
|
}, 20_000);
|
|
});
|