3baba3b7bc
Replace the hand-rolled `new Promise((resolve) => execFile(…, cb))` wrappers in
probe / ytdlp (×2) / ffmpeg / indexer.probeFlat / download.probeMeta with one
lib/exec.ts execFileAsync returning a normalized
{ok,stdout,stderr,timedOut,error} that never rejects. Each caller keeps its own
error mapping (timedOut -> "Timed out …" vs stderr) and JSON parsing; behaviour
is unchanged. windowsHide defaults on; per-call timeout/maxBuffer preserved.
Foundation for CC4/CC5 — the stdout line-buffer half lands with SIMP5, the
net.request half with SIMP16, at which point those checkboxes close.
Unit-tested (exec.test.ts) against the node binary: ok / stderr+nonzero-exit /
missing-binary / timeout. typecheck + 262 tests + eslint + prettier green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
42 lines
1.5 KiB
TypeScript
42 lines
1.5 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import { execFileAsync } from '../src/main/lib/exec'
|
|
|
|
// Exercised against the Node binary itself so the test needs no fixtures and is
|
|
// deterministic. Covers the contract the six migrated spawn sites rely on
|
|
// (SIMP2/CC4/CC5): normalized ok/stdout/stderr, never-rejects, and the timedOut flag.
|
|
describe('execFileAsync (SIMP2/CC4/CC5)', () => {
|
|
it('resolves ok with stdout on a clean exit', async () => {
|
|
const r = await execFileAsync(process.execPath, ['-e', 'process.stdout.write("hello")'])
|
|
expect(r.ok).toBe(true)
|
|
expect(r.stdout).toBe('hello')
|
|
expect(r.timedOut).toBe(false)
|
|
expect(r.error).toBeUndefined()
|
|
})
|
|
|
|
it('captures stderr and reports not-ok on a non-zero exit', async () => {
|
|
const r = await execFileAsync(process.execPath, [
|
|
'-e',
|
|
'process.stderr.write("boom"); process.exit(2)'
|
|
])
|
|
expect(r.ok).toBe(false)
|
|
expect(r.stderr).toContain('boom')
|
|
expect(r.error).toBeInstanceOf(Error)
|
|
expect(r.timedOut).toBe(false)
|
|
})
|
|
|
|
it('never rejects — a missing binary resolves not-ok with an error', async () => {
|
|
const r = await execFileAsync('definitely-not-a-real-binary-xyz', ['--version'])
|
|
expect(r.ok).toBe(false)
|
|
expect(r.error).toBeDefined()
|
|
expect(r.timedOut).toBe(false)
|
|
})
|
|
|
|
it('flags timedOut when the timeout kills the process', async () => {
|
|
const r = await execFileAsync(process.execPath, ['-e', 'setTimeout(() => {}, 5000)'], {
|
|
timeout: 100
|
|
})
|
|
expect(r.ok).toBe(false)
|
|
expect(r.timedOut).toBe(true)
|
|
})
|
|
})
|