diff --git a/src/test/main_test.ts b/src/test/main_test.ts index f2c70c6..e107b23 100644 --- a/src/test/main_test.ts +++ b/src/test/main_test.ts @@ -6,8 +6,6 @@ import path from 'node:path'; import {spawnSync} from 'node:child_process'; const isWindows = os.platform() === 'win32'; -const fixturesDir = path.join(import.meta.dirname, '../../test/fixtures'); -const distDir = path.join(import.meta.dirname, '../../dist'); const variants = [ {name: 'async', x, isAsync: true}, @@ -368,79 +366,44 @@ if (!isWindows) { }); test('resolves when grandchild holds piped stdout open', async () => { - const dir = fs.mkdtempSync( - path.join(os.tmpdir(), 'tinyexec-grandchild-') - ); - const runnerScript = path.join(dir, 'runner.mjs'); - const distPath = JSON.stringify(path.join(distDir, 'main.mjs')); - const fixturePath = JSON.stringify( - path.join(fixturesDir, 'grandchild.mjs') - ); - - fs.writeFileSync( - runnerScript, - `import { x } from ${distPath} - const result = await x('node', [${fixturePath}]) - process.stdout.write(JSON.stringify({ stdout: result.stdout, exitCode: result.exitCode })) - ` - ); - - try { - const proc = spawnSync('node', [runnerScript], { - timeout: 10000, + const proc = spawnSync( + 'node', + ['test/fixtures/spawn_grandchild.mjs', 'grandchild.mjs'], + { + timeout: 3_000, encoding: 'utf8', killSignal: 'SIGKILL', stdio: ['pipe', 'pipe', 'pipe'] - }); + } + ); - expect(proc.signal).not.toBe('SIGKILL'); - expect(proc.status).toBe(0); - const parsed = JSON.parse(proc.stdout.trim()); - expect(parsed.exitCode).toBe(0); - expect(parsed.stdout).toBe('output\n'); - } finally { - spawnSync('pkill', ['-f', 'tinyexec-test-grandchild']); - fs.rmSync(dir, {recursive: true, force: true}); - } + expect(proc.signal).not.toBe('SIGKILL'); + expect(proc.status).toBe(0); + const parsed = JSON.parse(proc.stdout.trim()); + expect(parsed.exitCode).toBe(0); + expect(parsed.stdout).toBe('line1\nline2\n'); + + spawnSync('pkill', ['-f', 'grandchild.mjs']); }); test('iterator completes when grandchild holds piped stdout open', async () => { - const dir = fs.mkdtempSync( - path.join(os.tmpdir(), 'tinyexec-grandchild-') - ); - const runnerScript = path.join(dir, 'runner.mjs'); - const distPath = JSON.stringify(path.join(distDir, 'main.mjs')); - const fixturePath = JSON.stringify( - path.join(fixturesDir, 'grandchild_multiline.mjs') - ); - - fs.writeFileSync( - runnerScript, - `import { x } from ${distPath} - const lines = [] - for await (const line of x('node', [${fixturePath}])) { - lines.push(line) - } - process.stdout.write(JSON.stringify(lines)) - ` - ); - - try { - const proc = spawnSync('node', [runnerScript], { - timeout: 10000, + const proc = spawnSync( + 'node', + ['test/fixtures/spawn_grandchild_iterator.mjs'], + { + timeout: 3_000, encoding: 'utf8', killSignal: 'SIGKILL', stdio: ['pipe', 'pipe', 'pipe'] - }); + } + ); - expect(proc.signal).not.toBe('SIGKILL'); - expect(proc.status).toBe(0); - const parsed = JSON.parse(proc.stdout.trim()); - expect(parsed).toEqual(['line1', 'line2']); - } finally { - spawnSync('pkill', ['-f', 'tinyexec-test-grandchild']); - fs.rmSync(dir, {recursive: true, force: true}); - } + expect(proc.signal).not.toBe('SIGKILL'); + expect(proc.status).toBe(0); + const parsed = JSON.parse(proc.stdout.trim()); + expect(parsed).toEqual(['line1', 'line2']); + + spawnSync('pkill', ['-f', 'grandchild.mjs']); }); }); diff --git a/test/fixtures/grandchild.mjs b/test/fixtures/grandchild.mjs index 52ef8ab..6dcfd67 100644 --- a/test/fixtures/grandchild.mjs +++ b/test/fixtures/grandchild.mjs @@ -1,13 +1,9 @@ import {spawn} from 'node:child_process'; -// Spawn a grandchild that inherits the piped stdout fd, simulating -// tsserver inheriting eslint's piped streams. Short timeout to avoid -// blocking test teardown. -spawn( - process.argv[0], - ['-e', 'setTimeout(() => void 0, 3000)'], - {stdio: ['ignore', 1, 'ignore']} -); +spawn(process.argv[0], ['-e', 'setTimeout(() => void 0, 10_000)'], { + stdio: ['ignore', 1, 'ignore'] +}); -console.log('output'); +console.log('line1'); +console.log('line2'); process.exit(0); diff --git a/test/fixtures/grandchild_multiline.mjs b/test/fixtures/grandchild_multiline.mjs deleted file mode 100644 index 253e1e2..0000000 --- a/test/fixtures/grandchild_multiline.mjs +++ /dev/null @@ -1,11 +0,0 @@ -import {spawn} from 'node:child_process'; - -spawn( - process.argv[0], - ['-e', 'setTimeout(() => void 0, 3000)'], - {stdio: ['ignore', 1, 'ignore']} -); - -console.log('line1'); -console.log('line2'); -process.exit(0); diff --git a/test/fixtures/spawn_grandchild.mjs b/test/fixtures/spawn_grandchild.mjs new file mode 100644 index 0000000..6c18314 --- /dev/null +++ b/test/fixtures/spawn_grandchild.mjs @@ -0,0 +1,10 @@ +import path from 'node:path'; +import {exec} from '../../dist/main.mjs'; + +const childScript = path.join(import.meta.dirname, 'grandchild.mjs'); + +const result = await exec('node', [childScript]); + +process.stdout.write( + JSON.stringify({stdout: result.stdout, exitCode: result.exitCode}) +); diff --git a/test/fixtures/spawn_grandchild_iterator.mjs b/test/fixtures/spawn_grandchild_iterator.mjs new file mode 100644 index 0000000..84c9b3d --- /dev/null +++ b/test/fixtures/spawn_grandchild_iterator.mjs @@ -0,0 +1,12 @@ +import path from 'node:path'; +import {exec} from '../../dist/main.mjs'; + +const childScript = path.join(import.meta.dirname, 'grandchild.mjs'); + +const lines = []; + +for await (const line of exec('node', [childScript])) { + lines.push(line); +} + +process.stdout.write(JSON.stringify(lines));