172 lines
6.0 KiB
TypeScript
172 lines
6.0 KiB
TypeScript
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
|
import * as plugins from '../ts/plugins.js';
|
|
import * as paths from '../ts/paths.js';
|
|
import * as fs from 'fs/promises';
|
|
|
|
// Import tspm client
|
|
import { tspmIpcClient } from '../ts/client/tspm.ipcclient.js';
|
|
|
|
// Test process that will crash
|
|
const CRASH_SCRIPT = `
|
|
setInterval(() => {
|
|
console.log('[test] Process is running...');
|
|
}, 1000);
|
|
|
|
setTimeout(() => {
|
|
console.error('[test] About to crash with non-zero exit code!');
|
|
process.exit(42);
|
|
}, 3000);
|
|
`;
|
|
|
|
tap.test('should create crash logs when process crashes', async (tools) => {
|
|
const crashScriptPath = plugins.path.join(paths.tspmDir, 'test-crash-script.js');
|
|
const crashLogsDir = plugins.path.join(paths.tspmDir, 'crashlogs');
|
|
|
|
// Clean up any existing crash logs
|
|
try {
|
|
await fs.rm(crashLogsDir, { recursive: true, force: true });
|
|
} catch {}
|
|
|
|
// Write the crash script
|
|
await fs.writeFile(crashScriptPath, CRASH_SCRIPT);
|
|
|
|
// Start the daemon
|
|
console.log('Starting daemon...');
|
|
const daemonResult = await tools.runCommand('tsx ts/cli/tspm.cli.ts daemon start');
|
|
expect(daemonResult.exitCode).toEqual(0);
|
|
|
|
// Wait for daemon to be ready
|
|
await tools.wait(2000);
|
|
|
|
// Add a process that will crash
|
|
console.log('Adding crash test process...');
|
|
const addResult = await tools.runCommand(`tsx ts/cli/tspm.cli.ts add "node ${crashScriptPath}" --name crash-test`);
|
|
expect(addResult.exitCode).toEqual(0);
|
|
|
|
// Extract process ID from output
|
|
const idMatch = addResult.stdout.match(/Process added with ID: (\d+)/);
|
|
expect(idMatch).toBeTruthy();
|
|
const processId = parseInt(idMatch![1]);
|
|
|
|
// Start the process
|
|
console.log('Starting process that will crash...');
|
|
const startResult = await tools.runCommand(`tsx ts/cli/tspm.cli.ts start ${processId}`);
|
|
expect(startResult.exitCode).toEqual(0);
|
|
|
|
// Wait for the process to crash (it crashes after 3 seconds)
|
|
console.log('Waiting for process to crash...');
|
|
await tools.wait(5000);
|
|
|
|
// Check if crash log was created
|
|
console.log('Checking for crash log...');
|
|
const crashLogFiles = await fs.readdir(crashLogsDir).catch(() => []);
|
|
console.log(`Found ${crashLogFiles.length} crash log files:`, crashLogFiles);
|
|
|
|
// Should have at least one crash log
|
|
expect(crashLogFiles.length).toBeGreaterThan(0);
|
|
|
|
// Find the crash log for our test process
|
|
const testCrashLog = crashLogFiles.find(file => file.includes('crash-test'));
|
|
expect(testCrashLog).toBeTruthy();
|
|
|
|
// Read and verify crash log content
|
|
const crashLogPath = plugins.path.join(crashLogsDir, testCrashLog!);
|
|
const crashLogContent = await fs.readFile(crashLogPath, 'utf-8');
|
|
|
|
console.log('Crash log content:');
|
|
console.log(crashLogContent);
|
|
|
|
// Verify crash log contains expected information
|
|
expect(crashLogContent).toIncludeIgnoreCase('crash report');
|
|
expect(crashLogContent).toIncludeIgnoreCase('exit code: 42');
|
|
expect(crashLogContent).toIncludeIgnoreCase('About to crash');
|
|
|
|
// Stop the process
|
|
console.log('Cleaning up...');
|
|
await tools.runCommand(`tsx ts/cli/tspm.cli.ts delete ${processId}`);
|
|
|
|
// Stop the daemon
|
|
await tools.runCommand('tsx ts/cli/tspm.cli.ts daemon stop');
|
|
|
|
// Clean up test file
|
|
await fs.unlink(crashScriptPath).catch(() => {});
|
|
});
|
|
|
|
tap.test('should create crash logs when process is killed', async (tools) => {
|
|
const killScriptPath = plugins.path.join(paths.tspmDir, 'test-kill-script.js');
|
|
const crashLogsDir = plugins.path.join(paths.tspmDir, 'crashlogs');
|
|
|
|
// Write a script that runs indefinitely
|
|
const KILL_SCRIPT = `
|
|
setInterval(() => {
|
|
console.log('[test] Process is running and will be killed...');
|
|
}, 500);
|
|
`;
|
|
|
|
await fs.writeFile(killScriptPath, KILL_SCRIPT);
|
|
|
|
// Start the daemon
|
|
console.log('Starting daemon...');
|
|
const daemonResult = await tools.runCommand('tsx ts/cli/tspm.cli.ts daemon start');
|
|
expect(daemonResult.exitCode).toEqual(0);
|
|
|
|
// Wait for daemon to be ready
|
|
await tools.wait(2000);
|
|
|
|
// Add a process that we'll kill
|
|
console.log('Adding kill test process...');
|
|
const addResult = await tools.runCommand(`tsx ts/cli/tspm.cli.ts add "node ${killScriptPath}" --name kill-test`);
|
|
expect(addResult.exitCode).toEqual(0);
|
|
|
|
// Extract process ID
|
|
const idMatch = addResult.stdout.match(/Process added with ID: (\d+)/);
|
|
expect(idMatch).toBeTruthy();
|
|
const processId = parseInt(idMatch![1]);
|
|
|
|
// Start the process
|
|
console.log('Starting process to be killed...');
|
|
const startResult = await tools.runCommand(`tsx ts/cli/tspm.cli.ts start ${processId}`);
|
|
expect(startResult.exitCode).toEqual(0);
|
|
|
|
// Wait for process to run a bit
|
|
await tools.wait(2000);
|
|
|
|
// Get the actual PID of the running process
|
|
const statusResult = await tools.runCommand(`tsx ts/cli/tspm.cli.ts describe ${processId}`);
|
|
const pidMatch = statusResult.stdout.match(/pid:\s+(\d+)/);
|
|
|
|
if (pidMatch) {
|
|
const pid = parseInt(pidMatch[1]);
|
|
console.log(`Killing process with PID ${pid}...`);
|
|
|
|
// Kill the process with SIGTERM
|
|
await tools.runCommand(`kill -TERM ${pid}`);
|
|
|
|
// Wait for crash log to be created
|
|
await tools.wait(3000);
|
|
|
|
// Check for crash log
|
|
console.log('Checking for crash log from killed process...');
|
|
const crashLogFiles = await fs.readdir(crashLogsDir).catch(() => []);
|
|
const killCrashLog = crashLogFiles.find(file => file.includes('kill-test'));
|
|
|
|
if (killCrashLog) {
|
|
const crashLogPath = plugins.path.join(crashLogsDir, killCrashLog);
|
|
const crashLogContent = await fs.readFile(crashLogPath, 'utf-8');
|
|
|
|
console.log('Kill crash log content:');
|
|
console.log(crashLogContent);
|
|
|
|
// Verify it contains signal information
|
|
expect(crashLogContent).toIncludeIgnoreCase('signal: SIGTERM');
|
|
}
|
|
}
|
|
|
|
// Clean up
|
|
console.log('Cleaning up...');
|
|
await tools.runCommand(`tsx ts/cli/tspm.cli.ts delete ${processId}`);
|
|
await tools.runCommand('tsx ts/cli/tspm.cli.ts daemon stop');
|
|
await fs.unlink(killScriptPath).catch(() => {});
|
|
});
|
|
|
|
export default tap.start(); |