148 lines
4.5 KiB
TypeScript
148 lines
4.5 KiB
TypeScript
#!/usr/bin/env tsx
|
|
|
|
import { CrashLogManager } from '../ts/daemon/crashlogmanager.js';
|
|
import type { IProcessLog } from '../ts/shared/protocol/ipc.types.js';
|
|
import * as plugins from '../ts/plugins.js';
|
|
import * as paths from '../ts/paths.js';
|
|
import * as fs from 'fs/promises';
|
|
|
|
async function testCrashLogManager() {
|
|
console.log('🧪 Testing CrashLogManager directly...\n');
|
|
|
|
const crashLogManager = new CrashLogManager();
|
|
const crashLogsDir = plugins.path.join(paths.tspmDir, 'crashlogs');
|
|
|
|
// Clean up any existing crash logs
|
|
console.log('📁 Cleaning up existing crash logs...');
|
|
try {
|
|
await fs.rm(crashLogsDir, { recursive: true, force: true });
|
|
} catch {}
|
|
|
|
// Create test logs
|
|
const testLogs: IProcessLog[] = [
|
|
{
|
|
timestamp: Date.now() - 5000,
|
|
message: '[TEST] Process starting up...',
|
|
type: 'stdout'
|
|
},
|
|
{
|
|
timestamp: Date.now() - 4000,
|
|
message: '[TEST] Initializing components...',
|
|
type: 'stdout'
|
|
},
|
|
{
|
|
timestamp: Date.now() - 3000,
|
|
message: '[TEST] Running main loop...',
|
|
type: 'stdout'
|
|
},
|
|
{
|
|
timestamp: Date.now() - 2000,
|
|
message: '[TEST] Warning: Memory usage high',
|
|
type: 'stderr'
|
|
},
|
|
{
|
|
timestamp: Date.now() - 1000,
|
|
message: '[TEST] Error: Unhandled exception occurred!',
|
|
type: 'stderr'
|
|
},
|
|
{
|
|
timestamp: Date.now() - 500,
|
|
message: '[TEST] Fatal: Process crashing with exit code 42',
|
|
type: 'stderr'
|
|
}
|
|
];
|
|
|
|
// Test saving a crash log
|
|
console.log('💾 Saving crash log...');
|
|
await crashLogManager.saveCrashLog(
|
|
1 as any, // ProcessId
|
|
'test-process',
|
|
testLogs,
|
|
42, // exit code
|
|
null, // signal
|
|
3, // restart count
|
|
1024 * 1024 * 50 // 50MB memory usage
|
|
);
|
|
|
|
// 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) {
|
|
console.error('❌ No crash logs were created!');
|
|
process.exit(1);
|
|
}
|
|
|
|
// Read and display the crash log
|
|
const crashLogFile = crashLogFiles[0];
|
|
const crashLogPath = plugins.path.join(crashLogsDir, crashLogFile);
|
|
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 content
|
|
const checks = [
|
|
{ text: 'CRASH REPORT', found: crashLogContent.includes('CRASH REPORT') },
|
|
{ text: 'Exit Code: 42', found: crashLogContent.includes('Exit Code: 42') },
|
|
{ text: 'Restart Attempt: 3/10', found: crashLogContent.includes('Restart Attempt: 3/10') },
|
|
{ text: 'Memory Usage: 50 MB', found: crashLogContent.includes('Memory Usage: 50 MB') },
|
|
{ text: 'Fatal: Process crashing', found: crashLogContent.includes('Fatal: Process crashing') }
|
|
];
|
|
|
|
console.log('\n✅ Verification:');
|
|
checks.forEach(check => {
|
|
console.log(` ${check.found ? '✓' : '✗'} Contains "${check.text}"`);
|
|
});
|
|
|
|
const allChecksPassed = checks.every(c => c.found);
|
|
|
|
// Test rotation (create 100+ logs to test limit)
|
|
console.log('\n🔄 Testing rotation (creating 105 crash logs)...');
|
|
for (let i = 2; i <= 105; i++) {
|
|
await crashLogManager.saveCrashLog(
|
|
i as any,
|
|
`test-process-${i}`,
|
|
testLogs,
|
|
i,
|
|
null,
|
|
1,
|
|
1024 * 1024 * 10
|
|
);
|
|
// Small delay to ensure different timestamps
|
|
await new Promise(resolve => setTimeout(resolve, 10));
|
|
}
|
|
|
|
// Check that we have exactly 100 logs (rotation working)
|
|
const finalLogFiles = await fs.readdir(crashLogsDir);
|
|
console.log(` After rotation: ${finalLogFiles.length} crash logs (should be 100)`);
|
|
|
|
if (finalLogFiles.length !== 100) {
|
|
console.error(`❌ Rotation failed! Expected 100 logs, got ${finalLogFiles.length}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
// Verify oldest logs were deleted (test-process should be gone)
|
|
const hasOriginal = finalLogFiles.some(f => f.includes('_1_test-process.log'));
|
|
if (hasOriginal) {
|
|
console.error('❌ Rotation failed! Oldest log still exists');
|
|
process.exit(1);
|
|
}
|
|
|
|
if (allChecksPassed) {
|
|
console.log('\n✅ All crash log tests passed!');
|
|
} else {
|
|
console.log('\n❌ Some crash log tests failed!');
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
// Run the test
|
|
testCrashLogManager().catch(error => {
|
|
console.error('❌ Test failed:', error);
|
|
process.exit(1);
|
|
}); |