import { expect, tap } from '@git.zone/tstest/tapbundle'; import * as tspm from '../ts/index.js'; import * as path from 'path'; import * as fs from 'fs/promises'; import { TspmDaemon } from '../ts/classes.daemon.js'; // Test daemon server functionality tap.test('TspmDaemon creation', async () => { const daemon = new TspmDaemon(); expect(daemon).toBeInstanceOf(TspmDaemon); }); tap.test('Daemon PID file management', async (tools) => { const testDir = path.join(process.cwd(), '.nogit'); const testPidFile = path.join(testDir, 'test-daemon.pid'); // Create directory if it doesn't exist await fs.mkdir(testDir, { recursive: true }); // Clean up any existing test file await fs.unlink(testPidFile).catch(() => {}); // Test writing PID file await fs.writeFile(testPidFile, process.pid.toString()); const pidContent = await fs.readFile(testPidFile, 'utf-8'); expect(parseInt(pidContent)).toEqual(process.pid); // Clean up await fs.unlink(testPidFile); }); tap.test('Daemon socket path generation', async () => { const daemon = new TspmDaemon(); // Access private property for testing (normally wouldn't do this) const socketPath = (daemon as any).socketPath; expect(socketPath).toInclude('tspm.sock'); }); tap.test('Daemon shutdown handlers', async (tools) => { const daemon = new TspmDaemon(); // Test that shutdown handlers are registered const sigintListeners = process.listeners('SIGINT'); const sigtermListeners = process.listeners('SIGTERM'); // We expect at least one listener for each signal // (Note: in actual test we won't start the daemon to avoid side effects) expect(sigintListeners.length).toBeGreaterThanOrEqual(0); expect(sigtermListeners.length).toBeGreaterThanOrEqual(0); }); tap.test('Daemon process info tracking', async () => { const daemon = new TspmDaemon(); const tspmInstance = (daemon as any).tspmInstance; expect(tspmInstance).toBeDefined(); expect(tspmInstance.processes).toBeInstanceOf(Map); expect(tspmInstance.processConfigs).toBeInstanceOf(Map); expect(tspmInstance.processInfo).toBeInstanceOf(Map); }); tap.test('Daemon heartbeat monitoring setup', async (tools) => { const daemon = new TspmDaemon(); // Test heartbeat interval property exists const heartbeatInterval = (daemon as any).heartbeatInterval; expect(heartbeatInterval).toEqual(null); // Should be null before start }); tap.test('Daemon shutdown state management', async () => { const daemon = new TspmDaemon(); const isShuttingDown = (daemon as any).isShuttingDown; expect(isShuttingDown).toEqual(false); }); tap.test('Daemon memory usage reporting', async () => { const memUsage = process.memoryUsage(); expect(memUsage.heapUsed).toBeGreaterThan(0); expect(memUsage.heapTotal).toBeGreaterThan(0); expect(memUsage.rss).toBeGreaterThan(0); }); tap.test('Daemon CPU usage calculation', async () => { const cpuUsage = process.cpuUsage(); expect(cpuUsage.user).toBeGreaterThanOrEqual(0); expect(cpuUsage.system).toBeGreaterThanOrEqual(0); // Test conversion to seconds const cpuSeconds = cpuUsage.user / 1000000; expect(cpuSeconds).toBeGreaterThanOrEqual(0); }); tap.test('Daemon uptime calculation', async () => { const startTime = Date.now(); // Wait a bit await new Promise((resolve) => setTimeout(resolve, 100)); const uptime = Date.now() - startTime; expect(uptime).toBeGreaterThanOrEqual(100); expect(uptime).toBeLessThan(200); }); export default tap.start();