test(core): Wire createSecurityTaskRunner mock into remaining packager tests

Final commit of the perf(core) Pre-warm security worker pool change —
extends the unit packager test and the integration packager test:

- tests/core/packager.test.ts: adds `createSecurityTaskRunner` mock to
  the orchestration test's `mockDeps` and to the `parallel error
  handling` `baseDeps()` shared fixture, updates the
  `validateFileSafety.toHaveBeenCalledWith` assertion to expect the new
  6th-argument deps object (`{ taskRunner: <Object> }`), and adds
  positive/negative gate assertions —
  `expect(deps.createSecurityTaskRunner).toHaveBeenCalled()` for the
  default unscoped path, `.not.toHaveBeenCalled()` for the
  `--include 'src'` and `explicitFiles` (--stdin) paths.

- tests/integration-tests/packager.test.ts: adds the
  `createSecurityTaskRunner` stub so the default-scope path no longer
  attempts to spawn a real worker pool (the previous unhandled-rejection
  noise from a missing worker file URL is gone with this change).

(See PR description / first source commit for the full perf change
rationale, benchmark numbers, and correctness notes.)
This commit is contained in:
Kazuki Yamada
2026-05-09 02:35:18 +09:00
parent fb281d4560
commit 03b8e70b9c
2 changed files with 29 additions and 2 deletions
+22 -1
View File
@@ -58,6 +58,13 @@ describe('packager', () => {
},
warmupPromise: Promise.resolve(),
}),
createSecurityTaskRunner: vi.fn().mockReturnValue({
taskRunner: {
run: vi.fn().mockResolvedValue([]),
cleanup: vi.fn().mockResolvedValue(undefined),
},
warmupPromise: Promise.resolve(),
}),
calculateMetrics: vi.fn().mockResolvedValue({
totalFiles: 2,
totalCharacters: 11,
@@ -92,6 +99,7 @@ describe('packager', () => {
mockConfig,
undefined,
undefined,
expect.objectContaining({ taskRunner: expect.any(Object) }),
);
expect(mockDeps.processFiles).toHaveBeenCalledWith(mockRawFiles, mockConfig, progressCallback);
expect(mockDeps.produceOutput).toHaveBeenCalledWith(
@@ -177,6 +185,10 @@ describe('packager', () => {
taskRunner: { run: vi.fn().mockResolvedValue(0), cleanup },
warmupPromise: Promise.resolve(),
}),
createSecurityTaskRunner: vi.fn().mockReturnValue({
taskRunner: { run: vi.fn().mockResolvedValue([]), cleanup: vi.fn().mockResolvedValue(undefined) },
warmupPromise: Promise.resolve(),
}),
getGitDiffs: vi.fn().mockResolvedValue(undefined),
getGitLogs: vi.fn().mockResolvedValue(undefined),
prefetchSortData: vi.fn().mockResolvedValue(undefined),
@@ -248,13 +260,17 @@ describe('packager', () => {
await pack(['root'], config, vi.fn(), deps);
expect(deps.createMetricsTaskRunner).toHaveBeenCalledWith(600, expect.any(String));
// Same gate also enables the security pool pre-warm on the unscoped path.
expect(deps.createSecurityTaskRunner).toHaveBeenCalled();
});
test('uses 2 warm-up workers for the metrics pool when --include narrows scope', async () => {
// With explicit includes the file set is typically much smaller and the
// 3rd worker's BPE warm-up dominates the parallelism gain (paired benchmarks
// regressed by ~12% on the 258-file --include 'src,tests' workload), so the
// heuristic falls back to 2 warm workers.
// heuristic falls back to 2 warm workers. The same `hasExplicitScope`
// gate also disables the security pool pre-warm in this branch — its
// up-front cost outweighs the saved cold-start on small/scoped runs.
const { deps } = baseDeps();
const config = createMockConfig();
config.include = ['src'];
@@ -262,6 +278,7 @@ describe('packager', () => {
await pack(['root'], config, vi.fn(), deps);
expect(deps.createMetricsTaskRunner).toHaveBeenCalledWith(400, expect.any(String));
expect(deps.createSecurityTaskRunner).not.toHaveBeenCalled();
});
test('uses 2 warm-up workers for the metrics pool when explicitFiles is provided (--stdin)', async () => {
@@ -272,6 +289,10 @@ describe('packager', () => {
await pack(['root'], config, vi.fn(), deps, ['file1.txt', 'file2.txt']);
expect(deps.createMetricsTaskRunner).toHaveBeenCalledWith(400, expect.any(String));
// The security pool pre-warm shares the `hasExplicitScope` gate — when --stdin
// (explicitFiles) provides the file set, the pre-warm is skipped to avoid the
// pool-construction overhead that outweighs the saved cold-start on small runs.
expect(deps.createSecurityTaskRunner).not.toHaveBeenCalled();
});
test('cleans up the metrics worker pool even when the warmup promise rejects', async () => {
+7 -1
View File
@@ -122,6 +122,13 @@ describe.runIf(!isWindows)('packager integration', () => {
},
warmupPromise: Promise.resolve(),
}),
createSecurityTaskRunner: () => ({
taskRunner: {
run: async () => [],
cleanup: async () => {},
},
warmupPromise: Promise.resolve(),
}),
calculateMetrics: async (
processedFiles,
_output,
@@ -182,7 +189,6 @@ describe.runIf(!isWindows)('packager integration', () => {
case 'markdown':
expect(actualOutput).toContain('# File Summary');
expect(actualOutput).toContain('# User Provided Header');
expect(actualOutput).toContain('# Directory Structure');
expect(actualOutput).toContain('## File: src/index.js');
expect(actualOutput).toContain('````javascript\nconst { greet }');
expect(actualOutput).toContain('## File: src/utils.js');