42 lines
2.4 KiB
TypeScript
42 lines
2.4 KiB
TypeScript
// 起動に失敗したとき、その理由が画面に出ることを守るテスト (#1235)。
|
|
//
|
|
// 起動を断る判定は 3 行以上の本文で「なぜ止めたか」と「どう直すか」を書く。
|
|
// ところが致命的な例外は `src/main.ts` の最上位ハンドラが `err.stack` ごと
|
|
// 1 レコードで書き出すので、記録の並びは【本文】→【呼び出し位置の羅列】になる。
|
|
// `scripts/server.sh` が末尾 5 行しか出さないと、出るのは呼び出し位置だけで、
|
|
// 肝心の本文は画面から溢れる。直し方が書いてあるのに管理者には見えない。
|
|
//
|
|
// だからここで守るのは「行数の数字」ではなく、**本文が収まる幅が残っていること**。
|
|
// 末尾の行数を減らす変更は、ここで落ちる。
|
|
import { describe, it, expect } from 'vitest';
|
|
import { readFileSync } from 'node:fs';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { dirname, join } from 'node:path';
|
|
|
|
const repoRoot = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
|
|
/** 起動失敗の案内は最長で 4 行。加えてスタックの見出しと呼び出し位置が続く。 */
|
|
const MIN_TAIL_LINES = 20;
|
|
|
|
describe('起動失敗時の出力 (#1235)', () => {
|
|
it('server.sh の起動失敗は、案内の本文が収まる行数を出す', () => {
|
|
const sh = readFileSync(join(repoRoot, 'scripts', 'server.sh'), 'utf8');
|
|
const failureBlock = sh.slice(sh.indexOf('Server failed to start'));
|
|
const tail = /tail\s+(?:-n\s*)?-?(\d+)\s+"\$LOG_FILE"/.exec(failureBlock);
|
|
expect(tail).not.toBeNull();
|
|
expect(Number(tail![1])).toBeGreaterThanOrEqual(MIN_TAIL_LINES);
|
|
});
|
|
|
|
it('起動を断る本文とスタックの合計が、その行数に収まる', () => {
|
|
// 本文の行数は実物から数える。文面を伸ばしたときに、この歯止めが
|
|
// 一緒に見直されるようにするため。
|
|
const src = readFileSync(join(repoRoot, 'src', 'worker-bootstrap.ts'), 'utf8');
|
|
// throw new Error(`...`) のテンプレートリテラルに含まれる改行の数。
|
|
const refusals = src.match(/throw new Error\(\s*`[\s\S]*?\)\s*;/g) ?? [];
|
|
expect(refusals.length).toBeGreaterThan(0);
|
|
const longest = Math.max(...refusals.map((r) => (r.match(/\\n/g) ?? []).length + 1));
|
|
// スタックの見出し 1 行 + 呼び出し位置の余裕。
|
|
expect(longest + 10).toBeLessThanOrEqual(MIN_TAIL_LINES);
|
|
});
|
|
});
|