test(#4520): migrate generators/doc-gates/attribution batch to named timeout constants
Batch 9 of 17 in the ad hoc timeout literal migration (epic #4445). Replaces every bare numeric timeout/timeoutMs object-literal property in 14 files with a named constant, per eslint-rules/no-adhoc-timeout-literal.cjs. Removes the 14 files from the rule's allowlist. The issue's own guess ("all run a scripts/*.cjs generator or lint script once, BUILD_TIMEOUT_MS class") needed two corrections found by reading every site directly. First, BUILD_TIMEOUT_MS's own doc comment scopes it specifically to scripts/build-hooks.js, which none of this batch's generator/lint-script sites run — a new shared constant, GENERATOR_SCRIPT_TIMEOUT_MS, covers the class instead. Second, no-pending-3212-markers.test.cjs's single site spawns `git ls-files` directly, not a scripts/*.cjs script at all — routed to a second new shared constant, REAL_REPO_GIT_TIMEOUT_MS, promoted once emitted-attribution.test.cjs's own git-plumbing sites were found sharing the same class and value. Isolated Standards-axis review caught a further misclassification: one of REAL_REPO_GIT_TIMEOUT_MS's three emitted-attribution.test.cjs sites actually builds a fresh throwaway temp repo (createTempDir + git init), contradicting that constant's own real-repo-tree-only scope. Fixed with a new file-local FRESH_FIXTURE_GIT_TIMEOUT_MS holding the exact pre-existing value under an honest name, rather than reusing the shared GIT_FIXTURE_TIMEOUT_MS (which would have doubled the bound). emitted-attribution.test.cjs also gets two more file-local constants: HEAVY_REAL_TREE_TEST_TIMEOUT_MS (node:test's own per-test timeout option, not a spawn bound) and BUILD_HOOKS_UNDER_LOAD_TIMEOUT_MS (the same build-hooks.js script as the shared norm, at 4x its bound inside the suite's heaviest test). emitted-ack-trailer.test.cjs gets IMPOSSIBLY_SHORT_GIT_TIMEOUT_MS — the one value in this migration that is deliberately tiny (20ms), used to force a timeout in a negative test, not generous headroom. No src/bin file touched, no numeric value changed anywhere. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,7 @@
|
|||||||
[
|
[
|
||||||
"tests/adr-612-bracket-coherence.test.cjs",
|
"tests/adr-612-bracket-coherence.test.cjs",
|
||||||
"tests/adr-612-bracket-read-tolerance.test.cjs",
|
"tests/adr-612-bracket-read-tolerance.test.cjs",
|
||||||
"tests/adr-index-gate.test.cjs",
|
|
||||||
"tests/adr857-core-without-capabilities.test.cjs",
|
"tests/adr857-core-without-capabilities.test.cjs",
|
||||||
"tests/api-coverage-gate-e2e.test.cjs",
|
|
||||||
"tests/api-coverage.test.cjs",
|
|
||||||
"tests/assumption-delta-checkpoint-e2e.test.cjs",
|
"tests/assumption-delta-checkpoint-e2e.test.cjs",
|
||||||
"tests/assumption-delta.test.cjs",
|
"tests/assumption-delta.test.cjs",
|
||||||
"tests/capability-cli.test.cjs",
|
"tests/capability-cli.test.cjs",
|
||||||
@@ -13,9 +10,7 @@
|
|||||||
"tests/capability-trust.test.cjs",
|
"tests/capability-trust.test.cjs",
|
||||||
"tests/capability-validator-task-content-resolver.test.cjs",
|
"tests/capability-validator-task-content-resolver.test.cjs",
|
||||||
"tests/capability-writer.test.cjs",
|
"tests/capability-writer.test.cjs",
|
||||||
"tests/changeset-new.test.cjs",
|
|
||||||
"tests/check-env.test.cjs",
|
"tests/check-env.test.cjs",
|
||||||
"tests/check-glossary-refs.test.cjs",
|
|
||||||
"tests/check-predicate.test.cjs",
|
"tests/check-predicate.test.cjs",
|
||||||
"tests/cjs-command-router-adapter.test.cjs",
|
"tests/cjs-command-router-adapter.test.cjs",
|
||||||
"tests/code-review-pipeline-regression.test.cjs",
|
"tests/code-review-pipeline-regression.test.cjs",
|
||||||
@@ -24,24 +19,16 @@
|
|||||||
"tests/config-get-default.test.cjs",
|
"tests/config-get-default.test.cjs",
|
||||||
"tests/dispatcher.test.cjs",
|
"tests/dispatcher.test.cjs",
|
||||||
"tests/effort-surface-axis.test.cjs",
|
"tests/effort-surface-axis.test.cjs",
|
||||||
"tests/emitted-ack-trailer.test.cjs",
|
|
||||||
"tests/emitted-attribution.test.cjs",
|
|
||||||
"tests/federated-config.test.cjs",
|
"tests/federated-config.test.cjs",
|
||||||
"tests/gate-predicate-evaluator.test.cjs",
|
"tests/gate-predicate-evaluator.test.cjs",
|
||||||
"tests/gen-context-index.test.cjs",
|
|
||||||
"tests/gen-health-docs.test.cjs",
|
|
||||||
"tests/gen-section-manifest.test.cjs",
|
|
||||||
"tests/gen-state-md-docs.test.cjs",
|
|
||||||
"tests/graphify.test.cjs",
|
"tests/graphify.test.cjs",
|
||||||
"tests/gsd-check-update-worker-platform-gate.test.cjs",
|
"tests/gsd-check-update-worker-platform-gate.test.cjs",
|
||||||
"tests/gsd-mcp-server-bin.test.cjs",
|
"tests/gsd-mcp-server-bin.test.cjs",
|
||||||
"tests/gsd-statusline.test.cjs",
|
"tests/gsd-statusline.test.cjs",
|
||||||
"tests/health-validation.test.cjs",
|
"tests/health-validation.test.cjs",
|
||||||
"tests/init.test.cjs",
|
"tests/init.test.cjs",
|
||||||
"tests/lint-docs-command-form.test.cjs",
|
|
||||||
"tests/locking-bugs-1909-1916-1925-1927.test.cjs",
|
"tests/locking-bugs-1909-1916-1925-1927.test.cjs",
|
||||||
"tests/milestone-lock.test.cjs",
|
"tests/milestone-lock.test.cjs",
|
||||||
"tests/no-pending-3212-markers.test.cjs",
|
|
||||||
"tests/pattern.test.cjs",
|
"tests/pattern.test.cjs",
|
||||||
"tests/perf-316-state-lock-buffer-alloc.test.cjs",
|
"tests/perf-316-state-lock-buffer-alloc.test.cjs",
|
||||||
"tests/perf-317-context-monitor-fs.test.cjs",
|
"tests/perf-317-context-monitor-fs.test.cjs",
|
||||||
@@ -53,7 +40,6 @@
|
|||||||
"tests/policy-160-route0-resume.test.cjs",
|
"tests/policy-160-route0-resume.test.cjs",
|
||||||
"tests/prohibition-enforcement.test.cjs",
|
"tests/prohibition-enforcement.test.cjs",
|
||||||
"tests/quick-batch.test.cjs",
|
"tests/quick-batch.test.cjs",
|
||||||
"tests/representative-corpus.test.cjs",
|
|
||||||
"tests/review-lane-invocation.test.cjs",
|
"tests/review-lane-invocation.test.cjs",
|
||||||
"tests/reviewer-manifest-body.test.cjs",
|
"tests/reviewer-manifest-body.test.cjs",
|
||||||
"tests/reviewer-trust-disclosure.test.cjs",
|
"tests/reviewer-trust-disclosure.test.cjs",
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const { spawnSync } = require('node:child_process');
|
|||||||
const { createTempDir, cleanup } = require('./helpers.cjs');
|
const { createTempDir, cleanup } = require('./helpers.cjs');
|
||||||
const { copyScriptWithDeps } = require('./helpers/copy-script-fixture.cjs');
|
const { copyScriptWithDeps } = require('./helpers/copy-script-fixture.cjs');
|
||||||
const { findTableWithColumns } = require('../gsd-core/bin/lib/markdown-table.cjs');
|
const { findTableWithColumns } = require('../gsd-core/bin/lib/markdown-table.cjs');
|
||||||
|
const { GENERATOR_SCRIPT_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||||
|
|
||||||
const REPO_ROOT = path.resolve(__dirname, '..');
|
const REPO_ROOT = path.resolve(__dirname, '..');
|
||||||
const SCRIPT_REL = path.join('scripts', 'gen-adr-index.cjs');
|
const SCRIPT_REL = path.join('scripts', 'gen-adr-index.cjs');
|
||||||
@@ -61,7 +62,7 @@ function run(root, args = []) {
|
|||||||
const res = spawnSync(process.execPath, [path.join(root, SCRIPT_REL), ...args], {
|
const res = spawnSync(process.execPath, [path.join(root, SCRIPT_REL), ...args], {
|
||||||
cwd: root,
|
cwd: root,
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
timeout: 30_000,
|
timeout: GENERATOR_SCRIPT_TIMEOUT_MS,
|
||||||
});
|
});
|
||||||
if (res.error) throw res.error;
|
if (res.error) throw res.error;
|
||||||
return { status: res.status, stdout: res.stdout || '', stderr: res.stderr || '' };
|
return { status: res.status, stdout: res.stdout || '', stderr: res.stderr || '' };
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ const path = require('node:path');
|
|||||||
|
|
||||||
const { cleanup, TEST_ENV_BASE } = require('./helpers.cjs');
|
const { cleanup, TEST_ENV_BASE } = require('./helpers.cjs');
|
||||||
const { runNode, OUTCOME } = require('./helpers/process-seam.cjs');
|
const { runNode, OUTCOME } = require('./helpers/process-seam.cjs');
|
||||||
|
const { LOOP_HOOK_POINT_CLI_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||||
// In-process seam for the fail-closed read-injection tests at the bottom of this
|
// In-process seam for the fail-closed read-injection tests at the bottom of this
|
||||||
// file (#2365 review): readPhaseScope is the pure phase-scope reader behind the
|
// file (#2365 review): readPhaseScope is the pure phase-scope reader behind the
|
||||||
// gate. Those tests monkeypatch fs rather than drive a subprocess.
|
// gate. Those tests monkeypatch fs rather than drive a subprocess.
|
||||||
@@ -39,7 +40,7 @@ function runTools(args, cwd) {
|
|||||||
const r = runNode([TOOLS_PATH, ...argv], {
|
const r = runNode([TOOLS_PATH, ...argv], {
|
||||||
cwd,
|
cwd,
|
||||||
env: { ...process.env, ...TEST_ENV_BASE },
|
env: { ...process.env, ...TEST_ENV_BASE },
|
||||||
timeoutMs: 60000,
|
timeoutMs: LOOP_HOOK_POINT_CLI_TIMEOUT_MS,
|
||||||
});
|
});
|
||||||
if (r.outcome === OUTCOME.EXITED && r.exitCode === 0) {
|
if (r.outcome === OUTCOME.EXITED && r.exitCode === 0) {
|
||||||
return { success: true, output: r.stdout.trim(), exitCode: 0, error: '' };
|
return { success: true, output: r.stdout.trim(), exitCode: 0, error: '' };
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const assert = require('node:assert/strict');
|
|||||||
const { spawnSync } = require('node:child_process');
|
const { spawnSync } = require('node:child_process');
|
||||||
const path = require('node:path');
|
const path = require('node:path');
|
||||||
const fc = require('fast-check');
|
const fc = require('fast-check');
|
||||||
|
const { PROBE_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||||
|
|
||||||
const MODULE_PATH = path.join(__dirname, '..', 'gsd-core', 'bin', 'lib', 'api-coverage.cjs');
|
const MODULE_PATH = path.join(__dirname, '..', 'gsd-core', 'bin', 'lib', 'api-coverage.cjs');
|
||||||
|
|
||||||
@@ -985,7 +986,7 @@ describe('api-coverage CLI — STDIN + exit codes', () => {
|
|||||||
const r = spawnSync(process.execPath, [CLI, '--json'], {
|
const r = spawnSync(process.execPath, [CLI, '--json'], {
|
||||||
input: stdin,
|
input: stdin,
|
||||||
encoding: 'utf-8',
|
encoding: 'utf-8',
|
||||||
timeout: 15000,
|
timeout: PROBE_TIMEOUT_MS,
|
||||||
});
|
});
|
||||||
return { exitCode: r.status, stdout: r.stdout, stderr: r.stderr };
|
return { exitCode: r.status, stdout: r.stdout, stderr: r.stderr };
|
||||||
}
|
}
|
||||||
@@ -1016,7 +1017,6 @@ describe('api-coverage CLI — NO_INPUT / UNAVAILABLE (ADR-3889 Phase 3, #3907)'
|
|||||||
const INJECT_STDIN_ERROR = path.join(__dirname, 'helpers', 'inject-stdin-error.cjs');
|
const INJECT_STDIN_ERROR = path.join(__dirname, 'helpers', 'inject-stdin-error.cjs');
|
||||||
const { exitCodeFor } = require('../gsd-core/bin/lib/exit-code-registry.cjs');
|
const { exitCodeFor } = require('../gsd-core/bin/lib/exit-code-registry.cjs');
|
||||||
const { runNode } = require('./helpers/process-seam.cjs');
|
const { runNode } = require('./helpers/process-seam.cjs');
|
||||||
const { PROBE_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
|
||||||
|
|
||||||
function runCliJson(stdin, extraArgs = [], extraEnv = {}) {
|
function runCliJson(stdin, extraArgs = [], extraEnv = {}) {
|
||||||
const r = runNode([CLI, '--json', ...extraArgs], {
|
const r = runNode([CLI, '--json', ...extraArgs], {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ const { generateFragmentName, scaffoldFragment, parseFragment, parseArgs } = (()
|
|||||||
})();
|
})();
|
||||||
const { FRAGMENT_ERROR } = require(path.join(ROOT, 'scripts', 'changeset', 'parse.cjs'));
|
const { FRAGMENT_ERROR } = require(path.join(ROOT, 'scripts', 'changeset', 'parse.cjs'));
|
||||||
const { cleanup } = require('./helpers.cjs');
|
const { cleanup } = require('./helpers.cjs');
|
||||||
|
const { QUICK_SPAWN_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||||
|
|
||||||
const NEW_CJS = path.join(ROOT, 'scripts', 'changeset', 'new.cjs');
|
const NEW_CJS = path.join(ROOT, 'scripts', 'changeset', 'new.cjs');
|
||||||
|
|
||||||
@@ -114,7 +115,7 @@ describe('changeset new: --pr 0 placeholder acceptance (bug #1224)', () => {
|
|||||||
const result = spawnSync(
|
const result = spawnSync(
|
||||||
process.execPath,
|
process.execPath,
|
||||||
[NEW_CJS, '--type', 'Fixed', '--pr', '0', '--body', 'placeholder for pr-zero.', '--repo', isolatedDir],
|
[NEW_CJS, '--type', 'Fixed', '--pr', '0', '--body', 'placeholder for pr-zero.', '--repo', isolatedDir],
|
||||||
{ encoding: 'utf8', timeout: 10000 },
|
{ encoding: 'utf8', timeout: QUICK_SPAWN_TIMEOUT_MS },
|
||||||
);
|
);
|
||||||
|
|
||||||
// The bug: old main() did `if (!opts.pr)` → exit 2. Fixed: exit 0.
|
// The bug: old main() did `if (!opts.pr)` → exit 2. Fixed: exit 0.
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const { spawnSync } = require('node:child_process');
|
|||||||
|
|
||||||
const { createTempDir, cleanup } = require('./helpers.cjs');
|
const { createTempDir, cleanup } = require('./helpers.cjs');
|
||||||
const { copyScriptWithDeps } = require('./helpers/copy-script-fixture.cjs');
|
const { copyScriptWithDeps } = require('./helpers/copy-script-fixture.cjs');
|
||||||
|
const { GENERATOR_SCRIPT_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||||
|
|
||||||
const REPO_ROOT = path.resolve(__dirname, '..');
|
const REPO_ROOT = path.resolve(__dirname, '..');
|
||||||
const SCRIPT_REL = path.join('scripts', 'check-glossary-refs.cjs');
|
const SCRIPT_REL = path.join('scripts', 'check-glossary-refs.cjs');
|
||||||
@@ -67,7 +68,7 @@ function run(root, args = []) {
|
|||||||
const res = spawnSync(process.execPath, [path.join(root, SCRIPT_REL), ...args], {
|
const res = spawnSync(process.execPath, [path.join(root, SCRIPT_REL), ...args], {
|
||||||
cwd: root,
|
cwd: root,
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
timeout: 30_000,
|
timeout: GENERATOR_SCRIPT_TIMEOUT_MS,
|
||||||
});
|
});
|
||||||
if (res.error) throw res.error;
|
if (res.error) throw res.error;
|
||||||
return { status: res.status, stdout: res.stdout || '', stderr: res.stderr || '' };
|
return { status: res.status, stdout: res.stdout || '', stderr: res.stderr || '' };
|
||||||
@@ -227,7 +228,7 @@ test('the real script runs cleanly against the real repo without crashing', () =
|
|||||||
const res = spawnSync(process.execPath, [path.join(REPO_ROOT, SCRIPT_REL), '--check'], {
|
const res = spawnSync(process.execPath, [path.join(REPO_ROOT, SCRIPT_REL), '--check'], {
|
||||||
cwd: REPO_ROOT,
|
cwd: REPO_ROOT,
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
timeout: 30_000,
|
timeout: GENERATOR_SCRIPT_TIMEOUT_MS,
|
||||||
});
|
});
|
||||||
assert.equal(res.error, undefined, `spawn must not error: ${res.error}`);
|
assert.equal(res.error, undefined, `spawn must not error: ${res.error}`);
|
||||||
assert.ok(res.status === 0 || res.status === 1, `expected exit 0 or 1, got ${res.status} (stderr: ${res.stderr})`);
|
assert.ok(res.status === 0 || res.status === 1, `expected exit 0 or 1, got ${res.status} (stderr: ${res.stderr})`);
|
||||||
|
|||||||
@@ -794,6 +794,17 @@ describe('hostile IO: uncomputable range, subprocess failure, timeout', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deliberately, impossibly tiny -- NOT a generous-headroom bound like every
|
||||||
|
* other timeout constant in this test suite. Used to FORCE a TIMED_OUT
|
||||||
|
* outcome against an artificially huge git history (see
|
||||||
|
* growHistoryFastImport above), proving "an unreadable-in-time git call
|
||||||
|
* must throw a timeout, never hang." Named and commented distinctly so a
|
||||||
|
* future reader never mistakes this for a real operation-duration budget
|
||||||
|
* and "fixes" it by raising it.
|
||||||
|
*/
|
||||||
|
const IMPOSSIBLY_SHORT_GIT_TIMEOUT_MS = 20;
|
||||||
|
|
||||||
test('git log is bounded by a timeout — row 24', (t) => {
|
test('git log is bounded by a timeout — row 24', (t) => {
|
||||||
const dir = makeTempRepo('gsd-ack-trailer-24-');
|
const dir = makeTempRepo('gsd-ack-trailer-24-');
|
||||||
withCleanup(t, dir);
|
withCleanup(t, dir);
|
||||||
@@ -801,7 +812,9 @@ describe('hostile IO: uncomputable range, subprocess failure, timeout', () => {
|
|||||||
|
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => readAckTrailers({ baseRef: rootSha, headRef: 'HEAD', cwd: dir, timeoutMs: 20 }),
|
() => readAckTrailers({
|
||||||
|
baseRef: rootSha, headRef: 'HEAD', cwd: dir, timeoutMs: IMPOSSIBLY_SHORT_GIT_TIMEOUT_MS,
|
||||||
|
}),
|
||||||
/time/i,
|
/time/i,
|
||||||
'an unreadable-in-time git call must throw a timeout, never hang',
|
'an unreadable-in-time git call must throw a timeout, never hang',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -90,6 +90,56 @@ const {
|
|||||||
resolveBaseline,
|
resolveBaseline,
|
||||||
} = require('./helpers/emitted-baseline.cjs');
|
} = require('./helpers/emitted-baseline.cjs');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* git plumbing via a scratch index against this repo's REAL object
|
||||||
|
* database (never a throwaway fixture) -- run through this file's own
|
||||||
|
* hand-rolled git-spawn helper (never the shared
|
||||||
|
* tests/helpers/git-fixture.cjs). Shares the REAL_REPO_GIT_TIMEOUT_MS class
|
||||||
|
* with tests/no-pending-3212-markers.test.cjs's `git ls-files` call --
|
||||||
|
* promoted to tests/helpers/timeouts.cjs rather than kept file-local once a
|
||||||
|
* second file was found sharing the exact same value and shape.
|
||||||
|
*/
|
||||||
|
const { REAL_REPO_GIT_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* git fixture CONSTRUCTION (init/config/add/commit) against a genuinely
|
||||||
|
* fresh temp repo, via this file's own hand-rolled git-spawn helper --
|
||||||
|
* correction from an earlier pass that conflated this with
|
||||||
|
* REAL_REPO_GIT_TIMEOUT_MS's real-repo-tree class; a Standards-axis review
|
||||||
|
* caught that this site's `repo` is a throwaway mkdtemp fixture
|
||||||
|
* (createTempDir + git init), not the real repo tree. Distinct from the
|
||||||
|
* SHARED tests/helpers/git-fixture.cjs's own GIT_FIXTURE_TIMEOUT_MS
|
||||||
|
* (60000ms, a six-spawn construction sequence): this site rolls its own,
|
||||||
|
* lighter five-spawn sequence at a genuinely different pre-existing bound,
|
||||||
|
* so reusing that shared constant would silently double this site's
|
||||||
|
* budget. No fresh bench data justifies a different number, so the
|
||||||
|
* pre-existing 30000ms literal is preserved exactly under this name.
|
||||||
|
*/
|
||||||
|
const FRESH_FIXTURE_GIT_TIMEOUT_MS = 30_000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* node:test's own per-test timeout option (NOT a subprocess spawn bound) --
|
||||||
|
* bounds the whole test body for this file's two heaviest tests: a real
|
||||||
|
* worktree checkout, `npm run build:lib`, a full multi-runtime install
|
||||||
|
* pass, and real git resolution. A completely different mechanism from
|
||||||
|
* every spawnSync/execFileSync timeout in this file or in
|
||||||
|
* tests/helpers/timeouts.cjs. No fresh bench data justifies a different
|
||||||
|
* number, so the pre-existing 480000ms literal is preserved exactly.
|
||||||
|
*/
|
||||||
|
const HEAVY_REAL_TREE_TEST_TIMEOUT_MS = 480_000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the exact same script as the shared BUILD_TIMEOUT_MS constant
|
||||||
|
* (scripts/build-hooks.js) but at 4x that constant's bound. This site
|
||||||
|
* sits inside "differential attribution over the real tree", the single
|
||||||
|
* heaviest test in the suite, where elevated system load plausibly
|
||||||
|
* justifies the wider margin -- not equalized to the lighter shared norm
|
||||||
|
* without bench data. Coincides numerically with INSTALL_TIMEOUT_MS (a
|
||||||
|
* full installer run, an unrelated operation) -- kept separate. No fresh
|
||||||
|
* bench data justifies a different number, so the pre-existing 120000ms
|
||||||
|
* literal is preserved exactly.
|
||||||
|
*/
|
||||||
|
const BUILD_HOOKS_UNDER_LOAD_TIMEOUT_MS = 120_000;
|
||||||
|
|
||||||
const SHA_A = 'a'.repeat(40);
|
const SHA_A = 'a'.repeat(40);
|
||||||
const SHA_B = 'b'.repeat(40);
|
const SHA_B = 'b'.repeat(40);
|
||||||
@@ -1425,7 +1475,7 @@ test('an unreadable baseline surfaces an error', () => {
|
|||||||
test(
|
test(
|
||||||
'buildBaselineAtRef resolves a baseline via the in-job build even when the generator '
|
'buildBaselineAtRef resolves a baseline via the in-job build even when the generator '
|
||||||
+ 'script is absent at the ref (#2767 regression)',
|
+ 'script is absent at the ref (#2767 regression)',
|
||||||
{ timeout: 480_000 },
|
{ timeout: HEAVY_REAL_TREE_TEST_TIMEOUT_MS },
|
||||||
(t) => {
|
(t) => {
|
||||||
// Mirrors "differential attribution over the real tree": install output is
|
// Mirrors "differential attribution over the real tree": install output is
|
||||||
// platform-specific on Windows, and this drives the same heavy worktree +
|
// platform-specific on Windows, and this drives the same heavy worktree +
|
||||||
@@ -1476,7 +1526,7 @@ test(
|
|||||||
// closed. Reusing the SAME helper `buildBaselineAtRef` now uses (below) rather than
|
// closed. Reusing the SAME helper `buildBaselineAtRef` now uses (below) rather than
|
||||||
// hand-rolling the flag here keeps the fix from silently diverging per call site.
|
// hand-rolling the flag here keeps the fix from silently diverging per call site.
|
||||||
const run = (...args) => execFileSync('git', [...safeDirArgs(REPO_ROOT), ...args], {
|
const run = (...args) => execFileSync('git', [...safeDirArgs(REPO_ROOT), ...args], {
|
||||||
cwd: REPO_ROOT, encoding: 'utf8', timeout: 30_000, env: gitEnv, stdio: ['ignore', 'pipe', 'pipe'],
|
cwd: REPO_ROOT, encoding: 'utf8', timeout: REAL_REPO_GIT_TIMEOUT_MS, env: gitEnv, stdio: ['ignore', 'pipe', 'pipe'],
|
||||||
}).trim();
|
}).trim();
|
||||||
|
|
||||||
const headSha = run('rev-parse', 'HEAD');
|
const headSha = run('rev-parse', 'HEAD');
|
||||||
@@ -1492,7 +1542,7 @@ test(
|
|||||||
// otherwise this test would prove nothing.
|
// otherwise this test would prove nothing.
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => execFileSync('git', [...safeDirArgs(REPO_ROOT), 'cat-file', '-e', `${syntheticSha}:scripts/gen-emitted-baseline.cjs`], {
|
() => execFileSync('git', [...safeDirArgs(REPO_ROOT), 'cat-file', '-e', `${syntheticSha}:scripts/gen-emitted-baseline.cjs`], {
|
||||||
cwd: REPO_ROOT, encoding: 'utf8', timeout: 30_000, stdio: 'pipe',
|
cwd: REPO_ROOT, encoding: 'utf8', timeout: REAL_REPO_GIT_TIMEOUT_MS, stdio: 'pipe',
|
||||||
}),
|
}),
|
||||||
/./,
|
/./,
|
||||||
'the synthetic ref must genuinely lack the generator script for this test to prove anything',
|
'the synthetic ref must genuinely lack the generator script for this test to prove anything',
|
||||||
@@ -1936,7 +1986,7 @@ test('baseline families are enumerated from the ref, not from the current regist
|
|||||||
// this same process just created with `mkdtempSync` + `git init`, so its owner is
|
// this same process just created with `mkdtempSync` + `git init`, so its owner is
|
||||||
// always the uid running the test regardless of container — it is never the
|
// always the uid running the test regardless of container — it is never the
|
||||||
// externally-mounted repo path the dubious-ownership check reacts to.
|
// externally-mounted repo path the dubious-ownership check reacts to.
|
||||||
const run = (...args) => execFileSync('git', args, { cwd: repo, encoding: 'utf8', timeout: 30_000 });
|
const run = (...args) => execFileSync('git', args, { cwd: repo, encoding: 'utf8', timeout: FRESH_FIXTURE_GIT_TIMEOUT_MS });
|
||||||
|
|
||||||
run('init', '--quiet', '-b', 'main');
|
run('init', '--quiet', '-b', 'main');
|
||||||
run('config', 'user.email', 'test@example.invalid');
|
run('config', 'user.email', 'test@example.invalid');
|
||||||
@@ -2050,7 +2100,7 @@ test('property: reported added/dropped are exactly the set differences', () => {
|
|||||||
// the working-tree fixtures, which would be whatever this PR's author regenerated;
|
// the working-tree fixtures, which would be whatever this PR's author regenerated;
|
||||||
// comparing against those would be vacuous.
|
// comparing against those would be vacuous.
|
||||||
|
|
||||||
test('differential attribution over the real tree', { timeout: 480_000 }, async (t) => {
|
test('differential attribution over the real tree', { timeout: HEAVY_REAL_TREE_TEST_TIMEOUT_MS }, async (t) => {
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
// Mirrors the golden harness: install output is platform-specific on Windows
|
// Mirrors the golden harness: install output is platform-specific on Windows
|
||||||
// (backslash paths), so parity is asserted on macOS + Linux. An explicit t.skip,
|
// (backslash paths), so parity is asserted on macOS + Linux. An explicit t.skip,
|
||||||
@@ -2062,7 +2112,7 @@ test('differential attribution over the real tree', { timeout: 480_000 }, async
|
|||||||
// hooks/dist is gitignored and built (DEFECT.HOOKS-DIST-SCOPED-CI): the scoped CI
|
// hooks/dist is gitignored and built (DEFECT.HOOKS-DIST-SCOPED-CI): the scoped CI
|
||||||
// lane does not run build:hooks, so a real install there would emit no hooks/ dir.
|
// lane does not run build:hooks, so a real install there would emit no hooks/ dir.
|
||||||
// Build idempotently, exactly as the golden harness does.
|
// Build idempotently, exactly as the golden harness does.
|
||||||
execFileSync(process.execPath, [BUILD_SCRIPT], { encoding: 'utf-8', stdio: 'pipe', timeout: 120_000 });
|
execFileSync(process.execPath, [BUILD_SCRIPT], { encoding: 'utf-8', stdio: 'pipe', timeout: BUILD_HOOKS_UNDER_LOAD_TIMEOUT_MS });
|
||||||
|
|
||||||
// The base ref is not universally available. The gsd-test runner shallow-clones and
|
// The base ref is not universally available. The gsd-test runner shallow-clones and
|
||||||
// merges base+head, so no `origin/*` remote-tracking ref exists in the container —
|
// merges base+head, so no `origin/*` remote-tracking ref exists in the container —
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ const { execFileSync } = require('node:child_process');
|
|||||||
|
|
||||||
const { createTempDir, cleanup } = require('./helpers.cjs');
|
const { createTempDir, cleanup } = require('./helpers.cjs');
|
||||||
const { serializeIndex, buildFreshIndex, checkReport, REASON } = require('../scripts/gen-context-index.cjs');
|
const { serializeIndex, buildFreshIndex, checkReport, REASON } = require('../scripts/gen-context-index.cjs');
|
||||||
|
const { GENERATOR_SCRIPT_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||||
|
|
||||||
const ROOT = path.resolve(__dirname, '..');
|
const ROOT = path.resolve(__dirname, '..');
|
||||||
const SCRIPT = path.join(ROOT, 'scripts', 'gen-context-index.cjs');
|
const SCRIPT = path.join(ROOT, 'scripts', 'gen-context-index.cjs');
|
||||||
@@ -71,7 +72,7 @@ function runGenContextIndex(args, paths = {}) {
|
|||||||
cwd: ROOT,
|
cwd: ROOT,
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
stdio: ['pipe', 'pipe', 'pipe'],
|
stdio: ['pipe', 'pipe', 'pipe'],
|
||||||
timeout: 30000,
|
timeout: GENERATOR_SCRIPT_TIMEOUT_MS,
|
||||||
});
|
});
|
||||||
return { code: 0, stdout, stderr: '' };
|
return { code: 0, stdout, stderr: '' };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const path = require('node:path');
|
|||||||
const { execFileSync } = require('node:child_process');
|
const { execFileSync } = require('node:child_process');
|
||||||
|
|
||||||
const { createTempDir, cleanup } = require('./helpers.cjs');
|
const { createTempDir, cleanup } = require('./helpers.cjs');
|
||||||
|
const { GENERATOR_SCRIPT_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||||
const {
|
const {
|
||||||
buildErrorCodeRows,
|
buildErrorCodeRows,
|
||||||
renderErrorCodesRegion,
|
renderErrorCodesRegion,
|
||||||
@@ -54,7 +55,7 @@ function runGenHealthDocs(args, cwd = ROOT) {
|
|||||||
cwd,
|
cwd,
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
stdio: ['pipe', 'pipe', 'pipe'],
|
stdio: ['pipe', 'pipe', 'pipe'],
|
||||||
timeout: 30000,
|
timeout: GENERATOR_SCRIPT_TIMEOUT_MS,
|
||||||
});
|
});
|
||||||
return { code: 0, stdout, stderr: '' };
|
return { code: 0, stdout, stderr: '' };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ const path = require('node:path');
|
|||||||
const { execFileSync } = require('node:child_process');
|
const { execFileSync } = require('node:child_process');
|
||||||
|
|
||||||
const { createTempDir, cleanup } = require('./helpers.cjs');
|
const { createTempDir, cleanup } = require('./helpers.cjs');
|
||||||
|
const { GENERATOR_SCRIPT_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||||
const {
|
const {
|
||||||
buildFreshManifest,
|
buildFreshManifest,
|
||||||
writeManifestAtomically,
|
writeManifestAtomically,
|
||||||
@@ -90,7 +91,7 @@ function runGenSectionManifest(args, cwd = ROOT) {
|
|||||||
cwd,
|
cwd,
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
stdio: ['pipe', 'pipe', 'pipe'],
|
stdio: ['pipe', 'pipe', 'pipe'],
|
||||||
timeout: 30000,
|
timeout: GENERATOR_SCRIPT_TIMEOUT_MS,
|
||||||
});
|
});
|
||||||
return { code: 0, stdout, stderr: '' };
|
return { code: 0, stdout, stderr: '' };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ const path = require('node:path');
|
|||||||
|
|
||||||
const { createTempDir, cleanup } = require('./helpers.cjs');
|
const { createTempDir, cleanup } = require('./helpers.cjs');
|
||||||
const { runNode } = require('./helpers/process-seam.cjs');
|
const { runNode } = require('./helpers/process-seam.cjs');
|
||||||
|
const { GENERATOR_SCRIPT_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||||
const gen = require('../scripts/gen-state-md-docs.cjs');
|
const gen = require('../scripts/gen-state-md-docs.cjs');
|
||||||
const { splitLines, detectEol, joinLines } = require('../gsd-core/bin/lib/text-lines.cjs');
|
const { splitLines, detectEol, joinLines } = require('../gsd-core/bin/lib/text-lines.cjs');
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ function seedCleanTree(dir) {
|
|||||||
function runGen(args, root) {
|
function runGen(args, root) {
|
||||||
const fullArgs = [SCRIPT, ...args];
|
const fullArgs = [SCRIPT, ...args];
|
||||||
if (root !== undefined) fullArgs.push('--root', root);
|
if (root !== undefined) fullArgs.push('--root', root);
|
||||||
const r = runNode(fullArgs, { timeoutMs: 30000 });
|
const r = runNode(fullArgs, { timeoutMs: GENERATOR_SCRIPT_TIMEOUT_MS });
|
||||||
return { code: r.exitCode, stdout: r.stdout, stderr: r.stderr };
|
return { code: r.exitCode, stdout: r.stdout, stderr: r.stderr };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -224,6 +224,47 @@ const SCAN_USAGE_ERROR_TIMEOUT_MS = 5000;
|
|||||||
*/
|
*/
|
||||||
const MALFORMED_INPUT_HOOK_TIMEOUT_MS = 5000;
|
const MALFORMED_INPUT_HOOK_TIMEOUT_MS = 5000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single `scripts/*.cjs` generator or lint script (gen-adr-index.cjs,
|
||||||
|
* check-glossary-refs.cjs, gen-context-index.cjs, and siblings), spawned
|
||||||
|
* directly and once against a small temp fixture repo -- no fan-out.
|
||||||
|
*
|
||||||
|
* Deliberately NOT `BUILD_TIMEOUT_MS`, despite the coincidentally-matching
|
||||||
|
* value: that constant's own doc comment scopes it specifically to
|
||||||
|
* `scripts/build-hooks.js` ("not a full project build"), and none of this
|
||||||
|
* norm's sites run that script. Reusing a constant for its number while
|
||||||
|
* ignoring what its comment actually describes is exactly the trap this
|
||||||
|
* migration exists to avoid -- see `SEAM_DEFAULT_TIMEOUT_MS` and
|
||||||
|
* `SCAN_USAGE_ERROR_TIMEOUT_MS` for the same reasoning applied elsewhere in
|
||||||
|
* this file.
|
||||||
|
*
|
||||||
|
* Shared across 7 files in batch #4520 of the ad hoc timeout literal
|
||||||
|
* migration, epic #4445 -- every site independently arrived at this exact
|
||||||
|
* value -- that is why it lives here rather than as a file-local constant.
|
||||||
|
*/
|
||||||
|
const GENERATOR_SCRIPT_TIMEOUT_MS = 30000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A git plumbing command (or a short scratch-index sequence of them) run
|
||||||
|
* against the REAL, current repo tree -- never a throwaway mkdtemp fixture.
|
||||||
|
* Distinct from `GIT_TIMEOUT_MS` (15000ms, plumbing reads against a small
|
||||||
|
* fixture repo) and `GIT_FIXTURE_TIMEOUT_MS` (60000ms, the shared helper's
|
||||||
|
* own multi-spawn fixture-CONSTRUCTION sequence) -- this norm's sites
|
||||||
|
* either read the real object database directly (`git ls-files`) or build a
|
||||||
|
* synthetic commit on a scratch index against it, which is heavier than a
|
||||||
|
* tiny-fixture read but not the shared helper's own six-spawn construction
|
||||||
|
* class. Explicitly NOT for fixture-repo CONSTRUCTION (init/config/add/commit
|
||||||
|
* against a throwaway mkdtemp repo) -- tests/emitted-attribution.test.cjs's
|
||||||
|
* own file-local `FRESH_FIXTURE_GIT_TIMEOUT_MS` covers that shape instead,
|
||||||
|
* after an earlier pass conflated the two and a Standards-axis review caught
|
||||||
|
* it.
|
||||||
|
*
|
||||||
|
* Shared across 2 files in batch #4520 of the ad hoc timeout literal
|
||||||
|
* migration, epic #4445 -- every site independently arrived at this exact
|
||||||
|
* value -- that is why it lives here rather than as a file-local constant.
|
||||||
|
*/
|
||||||
|
const REAL_REPO_GIT_TIMEOUT_MS = 30000;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
PROBE_TIMEOUT_MS,
|
PROBE_TIMEOUT_MS,
|
||||||
HOOK_FANOUT_TIMEOUT_MS,
|
HOOK_FANOUT_TIMEOUT_MS,
|
||||||
@@ -238,4 +279,6 @@ module.exports = {
|
|||||||
LOOP_HOOK_POINT_CLI_TIMEOUT_MS,
|
LOOP_HOOK_POINT_CLI_TIMEOUT_MS,
|
||||||
SCAN_USAGE_ERROR_TIMEOUT_MS,
|
SCAN_USAGE_ERROR_TIMEOUT_MS,
|
||||||
MALFORMED_INPUT_HOOK_TIMEOUT_MS,
|
MALFORMED_INPUT_HOOK_TIMEOUT_MS,
|
||||||
|
GENERATOR_SCRIPT_TIMEOUT_MS,
|
||||||
|
REAL_REPO_GIT_TIMEOUT_MS,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ const os = require('node:os');
|
|||||||
const path = require('node:path');
|
const path = require('node:path');
|
||||||
const { runNode } = require('./helpers/process-seam.cjs');
|
const { runNode } = require('./helpers/process-seam.cjs');
|
||||||
const { gitOrThrow } = require('./helpers/git-fixture.cjs');
|
const { gitOrThrow } = require('./helpers/git-fixture.cjs');
|
||||||
|
const { GENERATOR_SCRIPT_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||||
|
|
||||||
const GUARD_SCRIPT = path.resolve(__dirname, '..', 'scripts', 'lint-docs-command-form.cjs');
|
const GUARD_SCRIPT = path.resolve(__dirname, '..', 'scripts', 'lint-docs-command-form.cjs');
|
||||||
|
|
||||||
@@ -60,7 +61,7 @@ function runGuard(cwd) {
|
|||||||
const r = runNode([GUARD_SCRIPT], {
|
const r = runNode([GUARD_SCRIPT], {
|
||||||
cwd,
|
cwd,
|
||||||
env: { ...process.env, GSD_LINT_DOCS_COMMAND_FORM_REPO_ROOT: cwd },
|
env: { ...process.env, GSD_LINT_DOCS_COMMAND_FORM_REPO_ROOT: cwd },
|
||||||
timeoutMs: 30_000,
|
timeoutMs: GENERATOR_SCRIPT_TIMEOUT_MS,
|
||||||
});
|
});
|
||||||
return { status: r.exitCode, stdout: r.stdout, stderr: r.stderr };
|
return { status: r.exitCode, stdout: r.stdout, stderr: r.stderr };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ const { test } = require('node:test');
|
|||||||
const assert = require('node:assert/strict');
|
const assert = require('node:assert/strict');
|
||||||
const path = require('node:path');
|
const path = require('node:path');
|
||||||
const { execFileSync } = require('node:child_process');
|
const { execFileSync } = require('node:child_process');
|
||||||
|
const { REAL_REPO_GIT_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||||
|
|
||||||
const ROOT = path.resolve(__dirname, '..');
|
const ROOT = path.resolve(__dirname, '..');
|
||||||
const MARKER = 'pending #3212';
|
const MARKER = 'pending #3212';
|
||||||
@@ -38,7 +39,7 @@ function listTrackedFiles() {
|
|||||||
const stdout = execFileSync('git', ['-c', 'safe.directory=*', 'ls-files'], {
|
const stdout = execFileSync('git', ['-c', 'safe.directory=*', 'ls-files'], {
|
||||||
cwd: ROOT,
|
cwd: ROOT,
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
timeout: 30000,
|
timeout: REAL_REPO_GIT_TIMEOUT_MS,
|
||||||
});
|
});
|
||||||
return stdout
|
return stdout
|
||||||
.split(/\r?\n/)
|
.split(/\r?\n/)
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ const path = require('node:path');
|
|||||||
const { execFileSync } = require('node:child_process');
|
const { execFileSync } = require('node:child_process');
|
||||||
|
|
||||||
const { cleanup, TEST_ENV_BASE } = require('./helpers.cjs');
|
const { cleanup, TEST_ENV_BASE } = require('./helpers.cjs');
|
||||||
|
const { LOOP_HOOK_POINT_CLI_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
|
||||||
|
|
||||||
const TOOLS_PATH = path.join(__dirname, '..', 'gsd-core', 'bin', 'gsd-tools.cjs');
|
const TOOLS_PATH = path.join(__dirname, '..', 'gsd-core', 'bin', 'gsd-tools.cjs');
|
||||||
const FIXTURES_ROOT = path.join(__dirname, 'fixtures', 'representative');
|
const FIXTURES_ROOT = path.join(__dirname, 'fixtures', 'representative');
|
||||||
@@ -59,7 +60,7 @@ function runTools(args, cwd) {
|
|||||||
cwd,
|
cwd,
|
||||||
encoding: 'utf-8',
|
encoding: 'utf-8',
|
||||||
env: { ...process.env, ...TEST_ENV_BASE },
|
env: { ...process.env, ...TEST_ENV_BASE },
|
||||||
timeout: 60000,
|
timeout: LOOP_HOOK_POINT_CLI_TIMEOUT_MS,
|
||||||
});
|
});
|
||||||
return { success: true, output: stdout.trim(), error: '' };
|
return { success: true, output: stdout.trim(), error: '' };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
Reference in New Issue
Block a user