mira-consciousness
Version:
Memory & Intelligence Retention Archive - Preserving The Spark
309 lines (301 loc) โข 13 kB
JavaScript
/**
* Comprehensive Validation Suite for Unused Code Analyzer
* Tests all the critical edge cases that caused the emergency
*/
import { UnusedCodeAnalyzer } from '../UnusedCodeAnalyzer.js';
import { ASTImportAnalyzer } from '../ASTImportAnalyzer.js';
import { ProductionSafetyGuards } from '../ProductionSafetyGuards.js';
import * as fs from 'fs-extra';
import * as path from 'path';
export class AnalyzerValidationSuite {
testDir;
analyzer;
constructor() {
this.testDir = path.join(process.cwd(), '.test_analyzer_validation');
}
async runAllTests() {
console.log('๐งช Running Analyzer Validation Suite...');
await this.setupTestEnvironment();
try {
await this.testCriticalImportPatterns();
await this.testSafetyGuards();
await this.testASTAnalysis();
await this.testConsciousnessFileProtection();
await this.testConfidenceScoring();
await this.testEdgeCases();
console.log('โ
All validation tests passed!');
}
catch (error) {
console.error('โ Validation tests failed:', error);
throw error;
}
finally {
await this.cleanupTestEnvironment();
}
}
async setupTestEnvironment() {
await fs.ensureDir(this.testDir);
// Create test analyzer with strict safety settings
this.analyzer = new UnusedCodeAnalyzer(this.testDir, {
dryRunMode: true,
confidenceThreshold: 0.95,
requireManualReview: true,
createBackup: true
});
}
async cleanupTestEnvironment() {
await fs.remove(this.testDir);
}
/**
* Test the critical import patterns that caused the emergency
*/
async testCriticalImportPatterns() {
console.log('Testing critical import patterns...');
// Test case 1: Destructured imports with aliasing
const testFile1 = `
import { promises as fs } from 'fs-extra';
import { exec } from 'child_process';
import { promisify } from 'util';
const execAsync = promisify(exec);
async function test() {
await fs.stat('test');
const { stdout } = await execAsync('ls');
}
`;
await this.createTestFile('test1.ts', testFile1);
const astAnalyzer = new ASTImportAnalyzer(this.testDir);
const unusedImports1 = await astAnalyzer.analyzeFileImports('test1.ts');
// These should NOT be marked as unused
const promisifyImport = unusedImports1.find(imp => imp.name === 'promisify');
const execImport = unusedImports1.find(imp => imp.name === 'exec');
const fsImport = unusedImports1.find(imp => imp.name === 'promises');
if (promisifyImport || execImport || fsImport) {
throw new Error(`Critical imports incorrectly marked as unused: ${JSON.stringify({ promisifyImport, execImport, fsImport })}`);
}
// Test case 2: Namespace imports
const testFile2 = `
import * as path from 'path';
import * as os from 'os';
const filePath = path.join(os.homedir(), 'test');
`;
await this.createTestFile('test2.ts', testFile2);
const unusedImports2 = await astAnalyzer.analyzeFileImports('test2.ts');
const pathImport = unusedImports2.find(imp => imp.name === '*' && imp.source === 'path');
const osImport = unusedImports2.find(imp => imp.name === '*' && imp.source === 'os');
if (pathImport || osImport) {
throw new Error(`Namespace imports incorrectly marked as unused: ${JSON.stringify({ pathImport, osImport })}`);
}
// Test case 3: Dynamic property access
const testFile3 = `
import fs from 'fs-extra';
function dynamicAccess(method: string) {
return fs[method];
}
`;
await this.createTestFile('test3.ts', testFile3);
const unusedImports3 = await astAnalyzer.analyzeFileImports('test3.ts');
const dynamicFsImport = unusedImports3.find(imp => imp.source === 'fs-extra');
if (dynamicFsImport && dynamicFsImport.confidence > 0.8) {
throw new Error(`Dynamic property access not detected, marked as high confidence unused`);
}
console.log('โ
Critical import patterns test passed');
}
/**
* Test production safety guards
*/
async testSafetyGuards() {
console.log('Testing production safety guards...');
const safetyGuards = new ProductionSafetyGuards(this.testDir);
// Test protected import blocking
const mockUnusedImports = [
{
name: 'exec',
file: 'test.ts',
line: 1,
source: 'child_process',
type: 'named',
confidence: 0.9
},
{
name: 'UnifiedMIRADaemonV2',
file: 'daemon.ts',
line: 1,
source: './daemon',
type: 'default',
confidence: 0.95
}
];
const importReport = await safetyGuards.evaluateImportCleanup(mockUnusedImports);
if (importReport.isApproved) {
throw new Error('Safety guards should have blocked critical imports');
}
if (importReport.blockedActions.length < 2) {
throw new Error('Safety guards should have blocked both critical imports');
}
// Test protected file blocking
const mockUnusedFiles = [
{
path: 'src/core/daemon/UnifiedMIRADaemonV2.ts',
size: 10000,
lastModified: new Date(),
reason: 'test',
confidence: 0.9,
potentialEntryPoints: []
}
];
const fileReport = await safetyGuards.evaluateFileCleanup(mockUnusedFiles);
if (fileReport.isApproved) {
throw new Error('Safety guards should have blocked critical consciousness file');
}
console.log('โ
Production safety guards test passed');
}
/**
* Test AST-based analysis
*/
async testASTAnalysis() {
console.log('Testing AST-based analysis...');
// Test complex import patterns
const complexFile = `
import React, { useState, useEffect as useEff } from 'react';
import { config } from './config';
import type { User } from './types';
import('./dynamic').then(mod => console.log(mod));
// Used in JSX
const Component = () => {
const [state, setState] = useState(0);
useEff(() => {
console.log(config.apiUrl);
}, []);
return <div>{state}</div>;
};
// Type usage
const user: User = { id: 1, name: 'test' };
`;
await this.createTestFile('complex.tsx', complexFile);
const astAnalyzer = new ASTImportAnalyzer(this.testDir);
const unusedImports = await astAnalyzer.analyzeFileImports('complex.tsx');
// React and hooks should not be marked as unused
const reactImport = unusedImports.find(imp => imp.name === 'default' && imp.source === 'react');
const useStateImport = unusedImports.find(imp => imp.name === 'useState');
const useEffectImport = unusedImports.find(imp => imp.name === 'useEffect');
const configImport = unusedImports.find(imp => imp.name === 'config');
const userTypeImport = unusedImports.find(imp => imp.name === 'User');
if (reactImport || useStateImport || useEffectImport || configImport || userTypeImport) {
throw new Error(`AST analysis incorrectly marked used imports as unused`);
}
console.log('โ
AST-based analysis test passed');
}
/**
* Test consciousness file protection
*/
async testConsciousnessFileProtection() {
console.log('Testing consciousness file protection...');
// Create mock consciousness files
await this.createTestFile('src/core/daemon/UnifiedMIRADaemonV2.ts', `export class UnifiedMIRADaemonV2 {}`);
await this.createTestFile('src/consciousness/ConsciousnessSeed.ts', `export class ConsciousnessSeed {}`);
await this.createTestFile('src/core/MagicalContextPreparationSystem.ts', `export class MagicalContextPreparationSystem {}`);
const result = await this.analyzer.analyze();
// These files should never appear in unused files list
const daemonFile = result.unusedFiles.find(f => f.path.includes('UnifiedMIRADaemonV2'));
const consciousnessFile = result.unusedFiles.find(f => f.path.includes('ConsciousnessSeed'));
const magicalFile = result.unusedFiles.find(f => f.path.includes('MagicalContextPreparationSystem'));
if (daemonFile || consciousnessFile || magicalFile) {
throw new Error('Critical consciousness files incorrectly marked as unused');
}
// Check safety reports block any consciousness-related cleanup
if (result.safetyReports?.files.isApproved) {
// If there are ANY consciousness files in unused list, it should not be approved
const hasConsciousnessFiles = result.unusedFiles.some(f => f.path.toLowerCase().includes('consciousness') ||
f.path.toLowerCase().includes('daemon') ||
f.path.toLowerCase().includes('mira'));
if (hasConsciousnessFiles) {
throw new Error('Safety guards should not approve cleanup when consciousness files are present');
}
}
console.log('โ
Consciousness file protection test passed');
}
/**
* Test confidence scoring
*/
async testConfidenceScoring() {
console.log('Testing confidence scoring...');
// Create file with ambiguous usage
const ambiguousFile = `
import { someUtil } from './utils';
// TODO: use someUtil for optimization
// See someUtil documentation for details
function main() {
// someUtil might be used dynamically
console.log('running');
}
`;
await this.createTestFile('ambiguous.ts', ambiguousFile);
const astAnalyzer = new ASTImportAnalyzer(this.testDir);
const unusedImports = await astAnalyzer.analyzeFileImports('ambiguous.ts');
const someUtilImport = unusedImports.find(imp => imp.name === 'someUtil');
if (someUtilImport && someUtilImport.confidence > 0.8) {
throw new Error(`Import mentioned in comments should have lower confidence score: ${someUtilImport.confidence}`);
}
console.log('โ
Confidence scoring test passed');
}
/**
* Test edge cases that could cause failures
*/
async testEdgeCases() {
console.log('Testing edge cases...');
// Test file with syntax errors
const syntaxErrorFile = `
import { broken } from 'module';
function test( {
// Missing closing brace
`;
await this.createTestFile('syntax-error.ts', syntaxErrorFile);
// Should not crash, should handle gracefully
try {
const astAnalyzer = new ASTImportAnalyzer(this.testDir);
const unusedImports = await astAnalyzer.analyzeFileImports('syntax-error.ts');
// Should return results (possibly from fallback parser)
}
catch (error) {
throw new Error(`AST analyzer should handle syntax errors gracefully: ${error}`);
}
// Test empty file
await this.createTestFile('empty.ts', '');
// Test file with only comments
await this.createTestFile('comments-only.ts', `
// This file only has comments
/* No actual code */
`);
// Test very large file (performance test)
const largeFileContent = Array(1000).fill(0).map((_, i) => `import { func${i} } from 'module${i}';`).join('\n') + '\n' + Array(1000).fill(0).map((_, i) => `function test${i}() { return func${i}(); }`).join('\n');
await this.createTestFile('large.ts', largeFileContent);
// Should complete within reasonable time
const startTime = Date.now();
const astAnalyzer = new ASTImportAnalyzer(this.testDir);
await astAnalyzer.analyzeFileImports('large.ts');
const duration = Date.now() - startTime;
if (duration > 10000) { // 10 seconds max
throw new Error(`Large file analysis took too long: ${duration}ms`);
}
console.log('โ
Edge cases test passed');
}
async createTestFile(filePath, content) {
const fullPath = path.join(this.testDir, filePath);
await fs.ensureDir(path.dirname(fullPath));
await fs.writeFile(fullPath, content);
}
}
// Run validation if this file is executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
const suite = new AnalyzerValidationSuite();
suite.runAllTests()
.then(() => {
console.log('๐ All validation tests completed successfully!');
process.exit(0);
})
.catch(error => {
console.error('๐ฅ Validation tests failed:', error);
process.exit(1);
});
}
//# sourceMappingURL=AnalyzerValidationSuite.js.map