import { describe, it, expect, beforeEach } from 'vitest'; import os from 'node:os'; import fs from 'node:fs'; import path from 'node:path'; import { writePidfile, readPidfile, cleanPidfile, isProcessAlive } from '../pidfile.js'; describe('pidfile management', () => { let testDir: string; beforeEach(() => { testDir = path.join(os.tmpdir(), `visionl-pidfile-test-${Date.now()}-${Math.random().toString(36).slice(2)}`); // clean up before in case previous run left files try { fs.rmSync(testDir, { recursive: true, force: true }); } catch { /* ignore */ } fs.mkdirSync(testDir, { recursive: true }); }); it('writePidfile writes pid and port files, readPidfile reads them back', () => { writePidfile(12345, 9527, testDir); const result = readPidfile(testDir); expect(result).toEqual({ pid: 12345, port: 9527 }); }); it('readPidfile returns null when pidfile does not exist', () => { const result = readPidfile(testDir); expect(result).toBeNull(); }); it('readPidfile returns null when pidfile has invalid content', () => { writePidfile(12345, 9527, testDir); // overwrite with invalid data fs.writeFileSync(path.join(testDir, 'daemon.pid'), 'not-a-number'); const result = readPidfile(testDir); expect(result).toBeNull(); }); it('cleanPidfile removes both pid and port files', () => { writePidfile(12345, 9527, testDir); cleanPidfile(testDir); expect(fs.existsSync(path.join(testDir, 'daemon.pid'))).toBe(false); expect(fs.existsSync(path.join(testDir, 'daemon.port'))).toBe(false); }); it('cleanPidfile is safe when files do not exist', () => { // should not throw expect(() => cleanPidfile(testDir)).not.toThrow(); }); it('isProcessAlive returns true for the current process', () => { expect(isProcessAlive(process.pid)).toBe(true); }); it('isProcessAlive returns false for a non-existent PID', () => { expect(isProcessAlive(99999999)).toBe(false); }); });