refactor(cli): centralize daemon errno parsing and add utility tests
What changed: - extracted shared readNodeErrnoCode helper in local daemon process control code - updated isProcessRunning and signalProcess to use the shared helper - added packages/cli/tests/18-local-daemon-utils.test.ts covering resolveTcpHostFromListen cases (numeric, host:port, unix sockets, empty/non-host) Why: - removes duplicated low-level error-shape branching and keeps errno handling consistent in one place - adds deterministic coverage for pure listen parsing logic without depending on daemon runtime state Accomplishments for next agent: - this area now has a focused utility test entry that runs fast and is independent of daemon availability - full workspace typecheck is clean after this change Challenges / notes for next agent: - packages/cli/tests/03-daemon.test.ts can be environment-sensitive when a daemon is already running (baseline in this workspace did not reliably represent daemon not running) - existing unstaged change remains in scripts/codex-refactor-loop.sh and was intentionally left untouched
This commit is contained in:
@@ -169,12 +169,20 @@ function sleep(ms: number): Promise<void> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function readNodeErrnoCode(error: unknown): string | undefined {
|
||||||
|
if (typeof error !== 'object' || error === null || !('code' in error)) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeof error.code === 'string' ? error.code : undefined
|
||||||
|
}
|
||||||
|
|
||||||
function isProcessRunning(pid: number): boolean {
|
function isProcessRunning(pid: number): boolean {
|
||||||
try {
|
try {
|
||||||
process.kill(pid, 0)
|
process.kill(pid, 0)
|
||||||
return true
|
return true
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const code = typeof err === 'object' && err && 'code' in err ? (err as { code?: string }).code : undefined
|
const code = readNodeErrnoCode(err)
|
||||||
if (code === 'EPERM') {
|
if (code === 'EPERM') {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -187,7 +195,7 @@ function signalProcess(pid: number, signal: NodeJS.Signals): boolean {
|
|||||||
process.kill(pid, signal)
|
process.kill(pid, signal)
|
||||||
return true
|
return true
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const code = typeof err === 'object' && err && 'code' in err ? (err as { code?: string }).code : undefined
|
const code = readNodeErrnoCode(err)
|
||||||
if (code === 'ESRCH') {
|
if (code === 'ESRCH') {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env npx tsx
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Phase 18: Local daemon utility tests.
|
||||||
|
*
|
||||||
|
* Tests pure helpers that do not require a running daemon.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import assert from 'node:assert'
|
||||||
|
import { resolveTcpHostFromListen } from '../src/commands/daemon/local-daemon.js'
|
||||||
|
|
||||||
|
console.log('=== Local Daemon Utility Helpers ===\n')
|
||||||
|
|
||||||
|
{
|
||||||
|
console.log('Test 1: resolves numeric listen values to localhost host:port')
|
||||||
|
assert.strictEqual(resolveTcpHostFromListen('6767'), '127.0.0.1:6767')
|
||||||
|
assert.strictEqual(resolveTcpHostFromListen(' 7777 '), '127.0.0.1:7777')
|
||||||
|
console.log('✓ resolves numeric listen values\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
console.log('Test 2: preserves explicit host:port listen values')
|
||||||
|
assert.strictEqual(resolveTcpHostFromListen('localhost:6767'), 'localhost:6767')
|
||||||
|
assert.strictEqual(resolveTcpHostFromListen('0.0.0.0:8080'), '0.0.0.0:8080')
|
||||||
|
console.log('✓ preserves explicit host:port values\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
console.log('Test 3: rejects unix socket listen values')
|
||||||
|
assert.strictEqual(resolveTcpHostFromListen('/tmp/paseo.sock'), null)
|
||||||
|
assert.strictEqual(resolveTcpHostFromListen('unix:///tmp/paseo.sock'), null)
|
||||||
|
console.log('✓ rejects unix socket listen values\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
console.log('Test 4: rejects empty and non-host listen values')
|
||||||
|
assert.strictEqual(resolveTcpHostFromListen(''), null)
|
||||||
|
assert.strictEqual(resolveTcpHostFromListen(' '), null)
|
||||||
|
assert.strictEqual(resolveTcpHostFromListen('localhost'), null)
|
||||||
|
console.log('✓ rejects empty and non-host listen values\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('=== All local daemon utility tests passed ===')
|
||||||
Reference in New Issue
Block a user