Files
sprites/tools/build/test/exec.test.ts
Christopher Monsanto 2d83f4a16f Fix review findings in tools/build
- Verify rename sources against recorded stats at copy time; colliding
  rename destinations/sources fall back to running the rule
- Restrict rename detection to single-input, no-deps rules (sheet-style
  rules embed input names in output bytes)
- Include input extensions in the rename template (magick picks output
  format from extensions)
- Adopt only rules with no stored record, never known-dirty ones
- Skip dotfiles in glob (tup parity)
- Complete sheet dep closures (data/lib, lib/root)
- Validate --jobs; reject non-numeric values instead of silently no-oping
- Worker pool drains all workers before rethrowing; per-rule internal
  errors abort scheduling instead of racing db.close()
- SIGKILL all live process groups on second Ctrl-C
- Transactional loadStoredRules snapshot; dry run without existing state
  uses an in-memory db; idempotent DDL
- rule() rejects % placeholders in literal outputs

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-15 22:32:59 -04:00

30 lines
1007 B
TypeScript

import assert from 'node:assert/strict';
import {test} from 'node:test';
import {runShell, workerPool} from '../exec.ts';
test('runShell runs && chains from stdin and reports exit status', async () => {
const signal = new AbortController().signal;
const ok = await runShell('echo one && echo two', {cwd: process.cwd(), signal});
assert.equal(ok.code, 0);
assert.equal(ok.output, 'one\ntwo\n');
const bad = await runShell('echo partial && false && echo never', {cwd: process.cwd(), signal});
assert.equal(bad.code, 1);
assert.equal(bad.output, 'partial\n');
});
test('workerPool waits for every worker before rethrowing', async () => {
let finished = 0;
await assert.rejects(
workerPool([1, 2, 3, 4], 2, async item => {
if (item === 1) {
throw new Error('boom');
}
await new Promise(resolve => setTimeout(resolve, 20));
finished++;
}),
/boom/);
assert.equal(finished, 3);
});