diff --git a/tests/boundary/cli/cliSetup.test.ts b/tests/boundary/cli/cliSetup.test.ts index c1592e063b..93fe9ba1d4 100644 --- a/tests/boundary/cli/cliSetup.test.ts +++ b/tests/boundary/cli/cliSetup.test.ts @@ -1,4 +1,5 @@ -import { execFile } from "node:child_process"; +import { createVerifierCommands } from "../../../scripts/lib/verify-commands.mjs"; +import { withVerifierCleanup } from "../../../scripts/lib/verifier-cleanup.mjs"; import { access, lstat, @@ -10,9 +11,8 @@ import { writeFile, } from "node:fs/promises"; import { dirname, join, resolve } from "node:path"; -import { promisify } from "node:util"; import { spawn } from "@lydell/node-pty"; -import { describe, expect, it } from "vitest"; +import { describe, expect, it, onTestFinished } from "vitest"; import { z } from "zod"; import { parse as parseToml } from "smol-toml"; @@ -20,7 +20,18 @@ import type { SetupResult } from "../../../src/application/SetupTypes.js"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; import { cliTest, type TestCli } from "../../support/cli/cliFixture.js"; -const execute = promisify(execFile); +const execute = async ( + command: string, + arguments_: readonly string[], + options: { readonly cwd: string; readonly env: NodeJS.ProcessEnv }, +) => { + const commands = await createVerifierCommands(); + onTestFinished(() => commands.close()); + return withVerifierCleanup( + () => commands.exec(command, arguments_, { ...options, timeout: 15_000 }), + [() => commands.close()], + ); +}; const decisionMarker = "REA_SETUP_DECISION:"; const isolatedSetupEnvironment = (home: string) => ({ HOME: home, diff --git a/tests/boundary/cli/cliStartupImports.test.ts b/tests/boundary/cli/cliStartupImports.test.ts index 83aeb55b9a..bcfa9b769d 100644 --- a/tests/boundary/cli/cliStartupImports.test.ts +++ b/tests/boundary/cli/cliStartupImports.test.ts @@ -1,15 +1,14 @@ +import { createVerifierCommands } from "../../../scripts/lib/verify-commands.mjs"; +import { withVerifierCleanup } from "../../../scripts/lib/verifier-cleanup.mjs"; import { Client } from "@modelcontextprotocol/client"; import { StdioClientTransport } from "@modelcontextprotocol/client/stdio"; -import { execFile } from "node:child_process"; import { mkdir, writeFile } from "node:fs/promises"; import { join } from "node:path"; -import { promisify } from "node:util"; -import { describe, expect, it } from "vitest"; +import { describe, expect, it, onTestFinished } from "vitest"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; -const execute = promisify(execFile); const MARKER = "REA_TEST_RESOLVED "; // Dependencies and composition modules used by one command family; startup // must not resolve them just to register the complete command catalog. @@ -161,10 +160,16 @@ const resolvedMarkers = (stderr: string): ReadonlySet => const resolvedPackages = async ( arguments_: readonly string[], ): Promise> => { - const { stderr } = await execute( - process.execPath, - [`--import=${RESOLUTION_HOOK}`, ...arguments_], - { cwd: process.cwd(), maxBuffer: 16 * 1_024 * 1_024 }, + const commands = await createVerifierCommands(); + onTestFinished(() => commands.close()); + const { stderr } = await withVerifierCleanup( + () => + commands.exec( + process.execPath, + [`--import=${RESOLUTION_HOOK}`, ...arguments_], + { cwd: process.cwd(), maxBuffer: 16 * 1_024 * 1_024, timeout: 15_000 }, + ), + [() => commands.close()], ); return resolvedMarkers(stderr); }; diff --git a/tests/boundary/filesystem/interfaceBuilderBundle.test.ts b/tests/boundary/filesystem/interfaceBuilderBundle.test.ts index 3a26d9760b..cc88f4864e 100644 --- a/tests/boundary/filesystem/interfaceBuilderBundle.test.ts +++ b/tests/boundary/filesystem/interfaceBuilderBundle.test.ts @@ -1,11 +1,11 @@ +import { createVerifierCommands } from "../../../scripts/lib/verify-commands.mjs"; +import { withVerifierCleanup } from "../../../scripts/lib/verifier-cleanup.mjs"; import { binaryKeyedArchiveUidShapes } from "../../fixtures/keyedArchiveUidShapes.js"; -import { execFile } from "node:child_process"; import { mkdir, symlink, writeFile } from "node:fs/promises"; import { join } from "node:path"; -import { promisify } from "node:util"; import { buildBinary } from "plist"; -import { describe, expect, it, vi } from "vitest"; +import { describe, expect, it, onTestFinished, vi } from "vitest"; import { analyzeInterfaceBuilderBundle } from "../../../src/artifacts/apple/InterfaceBuilderAnalysis.js"; import { DirectoryArtifactReader } from "../../../src/artifacts/DirectoryArtifactReader.js"; @@ -27,7 +27,21 @@ import { } from "../../fixtures/interfaceBuilderEncoding.js"; import { cliTest } from "../../support/cli/cliFixture.js"; -const compile = promisify(execFile); +const compile = async ( + command: string, + arguments_: readonly string[], + options: { readonly timeout?: number } = {}, +): Promise => { + const commands = await createVerifierCommands(); + onTestFinished(() => commands.close()); + await withVerifierCleanup( + () => + commands.exec(command, arguments_, { + timeout: options.timeout ?? 90_000, + }), + [() => commands.close()], + ); +}; type PlistValue = | string diff --git a/tests/fixtures/ibtool.ts b/tests/fixtures/ibtool.ts index c7aef773f5..24cfc32f52 100644 --- a/tests/fixtures/ibtool.ts +++ b/tests/fixtures/ibtool.ts @@ -7,5 +7,7 @@ import { spawnSync } from "node:child_process"; */ export const xcodeIbtoolAvailable = process.platform === "darwin" && - spawnSync("/usr/bin/xcrun", ["--find", "ibtool"], { stdio: "ignore" }) - .status === 0; + spawnSync("/usr/bin/xcrun", ["--find", "ibtool"], { + stdio: "ignore", + timeout: 5_000, + }).status === 0; diff --git a/tests/fixtures/interfaceBuilderEncoding.ts b/tests/fixtures/interfaceBuilderEncoding.ts index cc95db5fa9..321a8b36d3 100644 --- a/tests/fixtures/interfaceBuilderEncoding.ts +++ b/tests/fixtures/interfaceBuilderEncoding.ts @@ -1,10 +1,10 @@ -import { execFile } from "node:child_process"; +import { createVerifierCommands } from "../../scripts/lib/verify-commands.mjs"; +import { withVerifierCleanup } from "../../scripts/lib/verifier-cleanup.mjs"; import { createHash } from "node:crypto"; import { mkdir, readFile, writeFile } from "node:fs/promises"; import { join } from "node:path"; -import { promisify } from "node:util"; -import { expect } from "vitest"; +import { expect, onTestFinished } from "vitest"; import { z } from "zod"; import { analyzeInterfaceBuilderBundle } from "../../src/artifacts/apple/InterfaceBuilderAnalysis.js"; @@ -56,11 +56,21 @@ let nativeEncodingFixtures: Promise | undefined; const produceNativeEncodingFixtures = async (): Promise => { const directory = await createTestTempDirectory("rea-ib-native-encodings-"); - await promisify(execFile)("/usr/bin/xcrun", [ - "swift", - "tests/conformance/native/interface-builder-encoding.swift", - directory, - ]); + const commands = await createVerifierCommands(); + onTestFinished(() => commands.close()); + await withVerifierCleanup( + () => + commands.exec( + "/usr/bin/xcrun", + [ + "swift", + "tests/conformance/native/interface-builder-encoding.swift", + directory, + ], + { timeout: 90_000 }, + ), + [() => commands.close()], + ); const oracle = oracleSchema.parse( JSON.parse(await readFile(join(directory, "oracle.json"), "utf8")), ); diff --git a/tests/fixtures/javascriptArtifactTypeScriptDialect.ts b/tests/fixtures/javascriptArtifactTypeScriptDialect.ts index 07a257b05a..31b00745b7 100644 --- a/tests/fixtures/javascriptArtifactTypeScriptDialect.ts +++ b/tests/fixtures/javascriptArtifactTypeScriptDialect.ts @@ -1,12 +1,12 @@ +import { createVerifierCommands } from "../../scripts/lib/verify-commands.mjs"; +import { withVerifierCleanup } from "../../scripts/lib/verifier-cleanup.mjs"; import { createHash } from "node:crypto"; -import { execFile } from "node:child_process"; import { mkdir, readFile, writeFile } from "node:fs/promises"; import { join, resolve } from "node:path"; -import { promisify } from "node:util"; import { createPackageWithOptions } from "@electron/asar"; import { parse } from "@babel/parser"; -import { expect } from "vitest"; +import { expect, onTestFinished } from "vitest"; import type { JavaScriptApplicationGraph } from "../../src/domain/javascript/javascriptApplicationGraph.js"; import { createTestTempDirectory } from "./temporaryDirectory.js"; @@ -59,8 +59,6 @@ export const typeScriptDialectCases = [ }, ] as const; -const execute = promisify(execFile); - /** Establish syntax and emitted bytes with the actual locked native compiler. */ export const expectValidTypeScriptInput = async ( path: string, @@ -76,21 +74,31 @@ export const expectValidTypeScriptInput = async ( const output = join(directory, "emitted"); // --noCheck isolates syntax/emit from ambient React/Node/module type facts. // This supplemental oracle does not claim complete TypeScript type validity. - await execute(process.execPath, [ - compiler, - "--ignoreConfig", - "--noCheck", - "--allowJs", - "--target", - "es2022", - "--module", - "esnext", - "--jsx", - "preserve", - "--outDir", - output, - input, - ]); + const commands = await createVerifierCommands(); + onTestFinished(() => commands.close()); + await withVerifierCleanup( + () => + commands.exec( + process.execPath, + [ + compiler, + "--ignoreConfig", + "--noCheck", + "--allowJs", + "--target", + "es2022", + "--module", + "esnext", + "--jsx", + "preserve", + "--outDir", + output, + input, + ], + { timeout: 15_000 }, + ), + [() => commands.close()], + ); const suffix = path.endsWith(".mts") ? ".mjs" : path.endsWith(".cts")