137 lines
4.7 KiB
TypeScript
137 lines
4.7 KiB
TypeScript
#!/usr/bin/env tsx
|
||
|
||
import * as plugins from '../ts/plugins.js';
|
||
import * as paths from '../ts/paths.js';
|
||
import * as fs from 'fs/promises';
|
||
import { execSync } from 'child_process';
|
||
|
||
// 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);
|
||
`;
|
||
|
||
async function testCrashLog() {
|
||
console.log('🧪 Testing crash log functionality...\n');
|
||
|
||
const crashScriptPath = plugins.path.join(paths.tspmDir, 'test-crash-script.js');
|
||
const crashLogsDir = plugins.path.join(paths.tspmDir, 'crashlogs');
|
||
|
||
try {
|
||
// Clean up any existing crash logs
|
||
console.log('📁 Cleaning up existing crash logs...');
|
||
try {
|
||
await fs.rm(crashLogsDir, { recursive: true, force: true });
|
||
} catch {}
|
||
|
||
// Write the crash script
|
||
console.log('📝 Writing test crash script...');
|
||
await fs.writeFile(crashScriptPath, CRASH_SCRIPT);
|
||
|
||
// Stop any existing daemon
|
||
console.log('🛑 Stopping any existing daemon...');
|
||
try {
|
||
execSync('tsx ts/cli.ts daemon stop', { stdio: 'inherit' });
|
||
} catch {}
|
||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||
|
||
// Start the daemon
|
||
console.log('🚀 Starting daemon...');
|
||
execSync('tsx ts/cli.ts daemon start', { stdio: 'inherit' });
|
||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||
|
||
// Add a process that will crash
|
||
console.log('➕ Adding crash test process...');
|
||
const addOutput = execSync(`tsx ts/cli.ts add "node ${crashScriptPath}" --name crash-test`, { encoding: 'utf-8' });
|
||
console.log(addOutput);
|
||
|
||
// Extract process ID from output
|
||
const idMatch = addOutput.match(/Process added with ID: (\d+)/);
|
||
if (!idMatch) {
|
||
throw new Error('Could not extract process ID from output');
|
||
}
|
||
const processId = parseInt(idMatch[1]);
|
||
console.log(` Process ID: ${processId}`);
|
||
|
||
// Start the process
|
||
console.log('▶️ Starting process that will crash...');
|
||
execSync(`tsx ts/cli.ts start ${processId}`, { stdio: 'inherit' });
|
||
|
||
// Wait for the process to crash (it crashes after 3 seconds)
|
||
console.log('⏳ Waiting for process to crash...');
|
||
await new Promise(resolve => setTimeout(resolve, 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.forEach(file => console.log(` - ${file}`));
|
||
|
||
if (crashLogFiles.length === 0) {
|
||
throw new Error('No crash logs were created!');
|
||
}
|
||
|
||
// Find the crash log for our test process
|
||
const testCrashLog = crashLogFiles.find(file => file.includes('crash-test'));
|
||
if (!testCrashLog) {
|
||
throw new Error('Could not find crash log for test process');
|
||
}
|
||
|
||
// Read and display crash log content
|
||
const crashLogPath = plugins.path.join(crashLogsDir, testCrashLog);
|
||
const crashLogContent = await fs.readFile(crashLogPath, 'utf-8');
|
||
|
||
console.log('\n📋 Crash log content:');
|
||
console.log('─'.repeat(60));
|
||
console.log(crashLogContent);
|
||
console.log('─'.repeat(60));
|
||
|
||
// Verify crash log contains expected information
|
||
const checks = [
|
||
{ text: 'CRASH REPORT', found: crashLogContent.includes('CRASH REPORT') },
|
||
{ text: 'Exit Code: 42', found: crashLogContent.includes('Exit Code: 42') },
|
||
{ text: 'About to crash', found: crashLogContent.includes('About to crash') },
|
||
{ text: 'Process is running', found: crashLogContent.includes('Process is running') }
|
||
];
|
||
|
||
console.log('\n✅ Verification:');
|
||
checks.forEach(check => {
|
||
console.log(` ${check.found ? '✓' : '✗'} Contains "${check.text}"`);
|
||
});
|
||
|
||
const allChecksPassed = checks.every(c => c.found);
|
||
|
||
// Clean up
|
||
console.log('\n🧹 Cleaning up...');
|
||
execSync(`tsx ts/cli.ts delete ${processId}`, { stdio: 'inherit' });
|
||
execSync('tsx ts/cli.ts daemon stop', { stdio: 'inherit' });
|
||
await fs.unlink(crashScriptPath).catch(() => {});
|
||
|
||
if (allChecksPassed) {
|
||
console.log('\n✅ All crash log tests passed!');
|
||
} else {
|
||
console.log('\n❌ Some crash log tests failed!');
|
||
process.exit(1);
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error('\n❌ Test failed:', error);
|
||
|
||
// Clean up on error
|
||
try {
|
||
execSync('tsx ts/cli.ts daemon stop', { stdio: 'inherit' });
|
||
await fs.unlink(crashScriptPath).catch(() => {});
|
||
} catch {}
|
||
|
||
process.exit(1);
|
||
}
|
||
}
|
||
|
||
// Run the test
|
||
testCrashLog(); |