Skip to main content
Glama
test-priority-system.js17.9 kB
#!/usr/bin/env node // Comprehensive Priority System Testing Script // Tests all numerical priority system features including core functions, // dependency management, priority inheritance, and advanced algorithms const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process'); // Colors for output const colors = { red: '\033[0;31m', green: '\033[0;32m', yellow: '\033[1;33m', blue: '\033[0;34m', purple: '\033[0;35m', cyan: '\033[0;36m', reset: '\033[0m' }; class PrioritySystemTestRunner { constructor() { this.totalTests = 0; this.passedTests = 0; this.failedTests = 0; this.failedDetails = []; this.acfRoot = path.join(__dirname, '..', '..'); this.testWorkspace = '/tmp/test_priority_system'; this.core = null; this.PriorityEngine = null; this.DependencyManager = null; } log(message, color = 'reset') { console.log(`${colors[color]}${message}${colors.reset}`); } async setup() { this.log('\n🔧 Setting up Priority System Test Environment...', 'blue'); // Clean and create test workspace if (fs.existsSync(this.testWorkspace)) { fs.rmSync(this.testWorkspace, { recursive: true, force: true }); } fs.mkdirSync(this.testWorkspace, { recursive: true }); // Change to ACF root directory process.chdir(this.acfRoot); // Load modules try { this.core = require(path.join(this.acfRoot, 'src', 'core.js')); this.PriorityEngine = require(path.join(this.acfRoot, 'src', 'priority_engine.js')); this.DependencyManager = require(path.join(this.acfRoot, 'src', 'dependency_manager.js')); this.log('✅ Modules loaded successfully', 'green'); } catch (error) { this.log(`❌ Failed to load modules: ${error.message}`, 'red'); throw error; } // Initialize test project try { this.core.initProject(this.testWorkspace, 'Priority System Test', 'Testing numerical priority system'); this.log('✅ Test project initialized', 'green'); } catch (error) { this.log(`❌ Failed to initialize test project: ${error.message}`, 'red'); throw error; } } async runTest(testName, testFunction) { this.totalTests++; try { this.log(`\n🧪 Running: ${testName}`, 'cyan'); await testFunction(); this.passedTests++; this.log(`✅ PASSED: ${testName}`, 'green'); } catch (error) { this.failedTests++; this.failedDetails.push({ test: testName, error: error.message }); this.log(`❌ FAILED: ${testName} - ${error.message}`, 'red'); } } assert(condition, message) { if (!condition) { throw new Error(message); } } assertEqual(actual, expected, message) { if (actual !== expected) { throw new Error(`${message}: expected ${expected}, got ${actual}`); } } assertRange(value, min, max, message) { if (value < min || value > max) { throw new Error(`${message}: expected value between ${min} and ${max}, got ${value}`); } } // Test Core Priority Functions async testCorePriorityFunctions() { // Test normalizePriority this.assertEqual(this.core.normalizePriority('low'), 300, 'Low priority normalization'); this.assertEqual(this.core.normalizePriority('medium'), 500, 'Medium priority normalization'); this.assertEqual(this.core.normalizePriority('high'), 700, 'High priority normalization'); this.assertEqual(this.core.normalizePriority('critical'), 900, 'Critical priority normalization'); this.assertEqual(this.core.normalizePriority(850), 850, 'Numeric priority passthrough'); this.assertEqual(this.core.normalizePriority('850'), 850, 'String numeric priority conversion'); // Test getDisplayPriority this.assertEqual(this.core.getDisplayPriority('high'), 'high', 'String priority display'); this.assertEqual(this.core.getDisplayPriority(750), 750, 'Numeric priority display'); // Test getPriorityString this.assertEqual(this.core.getPriorityString(300), 'low', 'Low priority string conversion'); this.assertEqual(this.core.getPriorityString(500), 'medium', 'Medium priority string conversion'); this.assertEqual(this.core.getPriorityString(700), 'high', 'High priority string conversion'); this.assertEqual(this.core.getPriorityString(900), 'critical', 'Critical priority string conversion'); this.assertEqual(this.core.getPriorityString(850), 'critical', 'Custom numeric priority string maps to critical'); } // Test Task Creation with Priorities async testTaskCreationWithPriorities() { // Test string priority task creation const stringResult = this.core.addTask(this.testWorkspace, { title: 'String Priority Task', description: 'Testing string priority', priority: 'high' }); this.assert(stringResult.success, 'String priority task creation should succeed'); // Test numeric priority task creation const numericResult = this.core.addTask(this.testWorkspace, { title: 'Numeric Priority Task', description: 'Testing numeric priority', priority: '850' }); this.assert(numericResult.success, 'Numeric priority task creation should succeed'); // Verify priorities were set correctly const tasks = this.core.readTasks(this.testWorkspace); const stringTask = tasks.tasks.find(t => t.title === 'String Priority Task'); const numericTask = tasks.tasks.find(t => t.title === 'Numeric Priority Task'); this.assertEqual(stringTask.priority, 700, 'String priority task should have numeric priority 700'); this.assertEqual(numericTask.priority, 850, 'Numeric priority task should have priority 850'); } // Test Priority Uniqueness async testPriorityUniqueness() { // Create multiple tasks with same priority for (let i = 0; i < 5; i++) { this.core.addTask(this.testWorkspace, { title: `Duplicate Priority Task ${i}`, description: 'Testing priority uniqueness', priority: '600' }); } const tasks = this.core.readTasks(this.testWorkspace); const duplicateTasks = tasks.tasks.filter(t => t.title.includes('Duplicate Priority Task')); // Check that all tasks have unique priorities const priorities = duplicateTasks.map(t => t.priority); const uniquePriorities = new Set(priorities); this.assertEqual(priorities.length, uniquePriorities.size, 'All tasks should have unique priorities'); // Check that priorities are in reasonable range around 600 priorities.forEach(priority => { this.assertRange(priority, 580, 620, 'Priority should be near target value'); }); } // Test Dependency Management async testDependencyManagement() { // Create tasks with dependencies const taskA = this.core.addTask(this.testWorkspace, { title: 'Task A - Foundation', description: 'Base task', priority: '500' }); const taskB = this.core.addTask(this.testWorkspace, { title: 'Task B - Depends on A', description: 'Depends on Task A', priority: '400', dependsOn: taskA.taskId.toString() }); const taskC = this.core.addTask(this.testWorkspace, { title: 'Task C - Depends on B', description: 'Depends on Task B', priority: '300', dependsOn: taskB.taskId.toString() }); // Test dependency boost const recalcResult = this.core.recalculatePriorities(this.testWorkspace, { applyDependencyBoosts: true, applyAdvancedDependencies: true }); this.assert(recalcResult.success, 'Priority recalculation should succeed'); // Verify that Task A got priority boost (it has dependents) const updatedTasks = this.core.readTasks(this.testWorkspace); const updatedTaskA = updatedTasks.tasks.find(t => t.id === taskA.taskId); this.assert(updatedTaskA.priority > 500, 'Task A should have received priority boost'); } // Test Priority Engine async testPriorityEngine() { const engine = new this.PriorityEngine(); // Create test tasks const testTasks = [ { id: 1, priority: 500, dependsOn: [], status: 'todo', createdAt: new Date().toISOString() }, { id: 2, priority: 600, dependsOn: [1], status: 'todo', createdAt: new Date().toISOString() }, { id: 3, priority: 700, dependsOn: [1], status: 'todo', createdAt: new Date().toISOString() } ]; const tasksData = { tasks: testTasks }; // Test priority recalculation const adjustments = engine.recalculateAllPriorities(tasksData); this.assert(Array.isArray(adjustments), 'Adjustments should be an array'); // Test priority statistics const stats = engine.getPriorityStatistics(testTasks); this.assertEqual(stats.count, 3, 'Statistics should count all tasks'); // Note: After recalculation, priorities may have changed due to dependency boosts this.assert(stats.min >= 500, 'Minimum priority should be at least 500'); this.assert(stats.max >= 700, 'Maximum priority should be at least 700'); } // Test Dependency Manager async testDependencyManager() { const depManager = new this.DependencyManager(); // Create test tasks with complex dependencies const testTasks = [ { id: 1, priority: 500, dependsOn: [], status: 'todo', title: 'Root Task' }, { id: 2, priority: 400, dependsOn: [1], status: 'todo', title: 'Level 1 Task A' }, { id: 3, priority: 400, dependsOn: [1], status: 'todo', title: 'Level 1 Task B' }, { id: 4, priority: 300, dependsOn: [2, 3], status: 'todo', title: 'Level 2 Task' }, { id: 5, priority: 200, dependsOn: [4], status: 'todo', title: 'Final Task' } ]; // Test dependency graph building const graph = depManager.buildDependencyGraph(testTasks); this.assert(graph.forward.has(1), 'Dependency graph should have forward mapping'); this.assert(graph.reverse.has(5), 'Dependency graph should have reverse mapping'); // Test dependency analysis const analysis = depManager.getDependencyAnalysis(testTasks); this.assertEqual(analysis.totalTasks, 5, 'Analysis should count all tasks'); this.assertEqual(analysis.rootTasks, 1, 'Should identify 1 root task'); this.assertEqual(analysis.leafTasks, 1, 'Should identify 1 leaf task'); this.assert(analysis.criticalPaths > 0, 'Should find critical paths'); // Test blocking task detection const adjustments = depManager.enhancePrioritiesWithDependencies(testTasks); this.assert(Array.isArray(adjustments), 'Should return adjustments array'); } // Test CLI Priority Commands async testCLIPriorityCommands() { const taskManagerPath = path.join(this.acfRoot, 'bin', 'acf'); try { // Test priority-stats command const statsOutput = execSync(`${taskManagerPath} priority-stats`, { cwd: this.testWorkspace, encoding: 'utf8', timeout: 10000 }); this.assert(statsOutput.includes('Priority Statistics'), 'Priority stats should show statistics'); // Test dependency-analysis command const analysisOutput = execSync(`${taskManagerPath} dependency-analysis`, { cwd: this.testWorkspace, encoding: 'utf8', timeout: 10000 }); this.assert(analysisOutput.includes('Dependency Analysis'), 'Dependency analysis should show analysis'); // Test bump command on a fresh, dedicated task to avoid uniqueness side-effects const created = this.core.addTask(this.testWorkspace, { title: 'CLI Bump Test', description: 'Isolated CLI bump test', priority: '600' }); const firstTaskId = created.taskId; const originalPriority = 600; execSync(`${taskManagerPath} bump ${firstTaskId} -a 50`, { cwd: this.testWorkspace, timeout: 10000 }); const updatedTasks = this.core.readTasks(this.testWorkspace); const updatedTask = updatedTasks.tasks.find(t => t.id === firstTaskId); const minExpected = Math.min(1000, originalPriority + 1); this.assert(updatedTask.priority >= minExpected && updatedTask.priority <= 1000, 'Bump command should increase priority without exceeding cap'); } catch (error) { throw new Error(`CLI command failed: ${error.message}`); } } // Test Performance async testPerformance() { this.log('🚀 Running performance tests...', 'yellow'); // Create many tasks for performance testing const startTime = Date.now(); for (let i = 0; i < 100; i++) { this.core.addTask(this.testWorkspace, { title: `Performance Test Task ${i}`, description: `Performance testing task ${i}`, priority: Math.floor(Math.random() * 1000) + 1, dependsOn: i > 0 ? [Math.floor(Math.random() * i) + 1].toString() : undefined }); } const creationTime = Date.now() - startTime; this.log(`📊 Created 100 tasks in ${creationTime}ms`, 'blue'); // Test priority recalculation performance const recalcStartTime = Date.now(); const recalcResult = this.core.recalculatePriorities(this.testWorkspace); const recalcTime = Date.now() - recalcStartTime; this.log(`📊 Recalculated priorities in ${recalcTime}ms`, 'blue'); this.assert(recalcResult.success, 'Priority recalculation should succeed with many tasks'); this.assert(recalcTime < 5000, 'Priority recalculation should complete within 5 seconds'); } async cleanup() { this.log('\n🧹 Cleaning up test environment...', 'blue'); if (fs.existsSync(this.testWorkspace)) { fs.rmSync(this.testWorkspace, { recursive: true, force: true }); } this.log('✅ Cleanup completed', 'green'); } async runAllTests() { try { await this.setup(); this.log('\n🎯 Starting Priority System Comprehensive Tests', 'purple'); this.log('=' .repeat(60), 'purple'); await this.runTest('Core Priority Functions', () => this.testCorePriorityFunctions()); await this.runTest('Task Creation with Priorities', () => this.testTaskCreationWithPriorities()); await this.runTest('Priority Uniqueness', () => this.testPriorityUniqueness()); await this.runTest('Dependency Management', () => this.testDependencyManagement()); await this.runTest('Priority Engine', () => this.testPriorityEngine()); await this.runTest('Dependency Manager', () => this.testDependencyManager()); await this.runTest('CLI Priority Commands', () => this.testCLIPriorityCommands()); await this.runTest('Performance Tests', () => this.testPerformance()); await this.cleanup(); // Print summary this.log('\n📊 TEST SUMMARY', 'purple'); this.log('=' .repeat(60), 'purple'); this.log(`Total Tests: ${this.totalTests}`, 'blue'); this.log(`Passed: ${this.passedTests}`, 'green'); this.log(`Failed: ${this.failedTests}`, this.failedTests > 0 ? 'red' : 'green'); if (this.failedTests > 0) { this.log('\n❌ FAILED TESTS:', 'red'); this.failedDetails.forEach(failure => { this.log(` • ${failure.test}: ${failure.error}`, 'red'); }); } const successRate = ((this.passedTests / this.totalTests) * 100).toFixed(1); this.log(`\nSuccess Rate: ${successRate}%`, successRate >= 90 ? 'green' : 'yellow'); if (this.failedTests === 0) { this.log('\n🎉 ALL TESTS PASSED! Priority system is working perfectly!', 'green'); } return this.failedTests === 0; } catch (error) { this.log(`\n💥 Test setup failed: ${error.message}`, 'red'); await this.cleanup(); return false; } } } // Run tests if this file is executed directly if (require.main === module) { const runner = new PrioritySystemTestRunner(); runner.runAllTests().then(success => { process.exit(success ? 0 : 1); }).catch(error => { console.error('Test runner failed:', error); process.exit(1); }); } module.exports = PrioritySystemTestRunner;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/FutureAtoms/agentic-control-framework'

If you have feedback or need assistance with the MCP directory API, please join our Discord server