Skip to main content
Glama

Prompt Auto-Optimizer MCP

by sloth-wq
integration.test.ts12.2 kB
/** * Integration Tests for GEPA Resilience System */ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { ResilienceSystem, CircuitBreakerFactory, RetryManager, GracefulDegradationManager, TimeoutManager, executeLLMWithResilience, executeDatabaseWithResilience, executeComputationWithResilience } from './index'; describe('GEPA Resilience System Integration', () => { let resilience: ResilienceSystem; beforeEach(() => { resilience = ResilienceSystem.getInstance(); }); afterEach(async () => { await resilience.emergencyShutdown('Test cleanup'); }); describe('Full Protection Integration', () => { it('should handle successful operations with full protection', async () => { const operation = vi.fn().mockResolvedValue('success'); const result = await resilience.executeWithFullProtection(operation, { serviceName: 'test-service', context: { name: 'test-operation', priority: 'medium' } }); expect(result).toBe('success'); expect(operation).toHaveBeenCalledOnce(); }); it('should apply circuit breaker protection', async () => { let callCount = 0; const failingOperation = vi.fn().mockImplementation(() => { callCount++; if (callCount <= 5) { throw new Error('Service failure'); } return 'success'; }); // Should eventually open circuit breaker for (let i = 0; i < 3; i++) { try { await resilience.executeWithFullProtection(failingOperation, { serviceName: 'failing-service', context: { name: 'test', priority: 'low' } }); } catch (error) { // Expected failures } } // Circuit should be open now, operation should be rejected without calling const preCallCount = callCount; try { await resilience.executeWithFullProtection(failingOperation, { serviceName: 'failing-service', context: { name: 'test', priority: 'low' } }); } catch (error) { expect(error.message).toContain('Circuit breaker'); } // Verify circuit breaker prevented the call expect(callCount).toBe(preCallCount); }); it('should apply retry logic with exponential backoff', async () => { const operation = vi.fn() .mockRejectedValueOnce(new Error('Temporary failure')) .mockRejectedValueOnce(new Error('Another temporary failure')) .mockResolvedValue('success'); const startTime = Date.now(); const result = await resilience.executeWithFullProtection(operation, { serviceName: 'retry-service', retryPolicy: 'generic', context: { name: 'test', priority: 'medium' } }); const elapsed = Date.now() - startTime; expect(result).toBe('success'); expect(operation).toHaveBeenCalledTimes(3); expect(elapsed).toBeGreaterThan(1000); // Should have delays }); it('should apply timeout protection', async () => { const slowOperation = vi.fn().mockImplementation( () => new Promise(resolve => setTimeout(resolve, 10000)) ); await expect( resilience.executeWithFullProtection(slowOperation, { serviceName: 'slow-service', timeoutConfig: 'generic', context: { name: 'slow-test', priority: 'low' } }) ).rejects.toThrow(); expect(slowOperation).toHaveBeenCalledOnce(); }, 35000); it('should use fallback values when all else fails', async () => { const failingOperation = vi.fn().mockRejectedValue(new Error('Total failure')); const result = await resilience.executeWithFullProtection(failingOperation, { serviceName: 'fallback-service', fallbackValue: 'fallback-result', context: { name: 'test', priority: 'low' } }); expect(result).toBe('fallback-result'); }); }); describe('Service-Specific Resilience Helpers', () => { it('should handle LLM operations with appropriate resilience', async () => { const llmOperation = vi.fn().mockResolvedValue({ content: 'LLM response', model: 'claude', tokens: { prompt: 100, completion: 50, total: 150 }, finishReason: 'stop', latency: 1000, timestamp: new Date() }); const result = await executeLLMWithResilience(llmOperation, { context: { name: 'test-llm', priority: 'high' } }); expect(result.content).toBe('LLM response'); expect(llmOperation).toHaveBeenCalledOnce(); }); it('should handle database operations with database-specific settings', async () => { const dbOperation = vi.fn().mockResolvedValue([{ id: 1, data: 'test' }]); const result = await executeDatabaseWithResilience(dbOperation, { context: { name: 'db-query', priority: 'medium' } }); expect(result).toEqual([{ id: 1, data: 'test' }]); expect(dbOperation).toHaveBeenCalledOnce(); }); it('should handle computations with computation-specific settings', async () => { const computation = vi.fn().mockResolvedValue(42); const result = await executeComputationWithResilience(computation, { context: { name: 'calculation', priority: 'low' } }); expect(result).toBe(42); expect(computation).toHaveBeenCalledOnce(); }); }); describe('System Health and Metrics', () => { it('should provide comprehensive system metrics', async () => { // Execute some operations to generate metrics const operation = vi.fn().mockResolvedValue('test'); await resilience.executeWithFullProtection(operation, { serviceName: 'metrics-test', context: { name: 'test', priority: 'medium' } }); const metrics = await resilience.getResilienceMetrics(); expect(metrics).toHaveProperty('circuitBreakers'); expect(metrics).toHaveProperty('retryStats'); expect(metrics).toHaveProperty('systemHealth'); expect(metrics).toHaveProperty('activeTimeouts'); }); it('should provide system status assessment', async () => { const status = await resilience.getSystemStatus(); expect(status).toHaveProperty('status'); expect(status).toHaveProperty('components'); expect(status).toHaveProperty('metrics'); expect(status).toHaveProperty('recommendations'); expect(['healthy', 'degraded', 'critical']).toContain(status.status); }); }); describe('Component Integration', () => { it('should coordinate between circuit breakers and retry manager', async () => { let attemptCount = 0; const operation = vi.fn().mockImplementation(() => { attemptCount++; if (attemptCount <= 2) { throw new Error('Retryable error'); } return 'success'; }); const result = await resilience.executeWithFullProtection(operation, { serviceName: 'coordination-test', retryPolicy: 'generic', circuitBreaker: true, context: { name: 'test', priority: 'medium' } }); expect(result).toBe('success'); expect(attemptCount).toBe(3); // 1 initial + 2 retries }); it('should handle cascading failures gracefully', async () => { const operations = Array.from({ length: 10 }, (_, i) => vi.fn().mockRejectedValue(new Error(`Failure ${i}`)) ); const results = await Promise.allSettled( operations.map((op, i) => resilience.executeWithFullProtection(op, { serviceName: `cascade-test-${i}`, fallbackValue: `fallback-${i}`, context: { name: `test-${i}`, priority: 'low' } }) ) ); // Should not crash the system expect(results).toHaveLength(10); // At least some should use fallback values const fulfilled = results.filter(r => r.status === 'fulfilled'); expect(fulfilled.length).toBeGreaterThan(0); }); }); describe('Error Handling', () => { it('should provide user-friendly error messages', async () => { const networkError = new Error('ECONNRESET: Connection reset by peer'); const operation = vi.fn().mockRejectedValue(networkError); try { await resilience.executeWithFullProtection(operation, { serviceName: 'error-test', context: { name: 'test', priority: 'medium' } }); } catch (error) { // Should still throw, but with potential circuit breaker context expect(error).toBeInstanceOf(Error); } }); it('should handle abort signals properly', async () => { const controller = new AbortController(); const operation = vi.fn().mockImplementation(async (signal) => { // Simulate some work await new Promise(resolve => setTimeout(resolve, 100)); if (signal?.aborted) { throw new Error('Operation aborted'); } return 'success'; }); // Start operation const promise = resilience.executeWithFullProtection(operation, { serviceName: 'abort-test', context: { name: 'test', priority: 'medium' } }); // Abort immediately controller.abort(); // Should handle abort gracefully await expect(promise).rejects.toThrow(); }); }); describe('Performance Under Load', () => { it('should handle concurrent operations efficiently', async () => { const operation = vi.fn().mockImplementation(async () => { await new Promise(resolve => setTimeout(resolve, 10)); return Math.random(); }); const startTime = Date.now(); const promises = Array.from({ length: 20 }, (_, i) => resilience.executeWithFullProtection(operation, { serviceName: `concurrent-test-${i % 3}`, // Mix of services context: { name: `concurrent-${i}`, priority: 'medium' } }) ); const results = await Promise.all(promises); const elapsed = Date.now() - startTime; expect(results).toHaveLength(20); expect(elapsed).toBeLessThan(5000); // Should complete reasonably fast expect(operation).toHaveBeenCalledTimes(20); }); }); }); describe('Individual Component Integration', () => { afterEach(async () => { await CircuitBreakerFactory.cleanup(); await RetryManager.getInstance().cleanup(); await GracefulDegradationManager.getInstance().cleanup(); await TimeoutManager.getInstance().cleanup(); }); it('should integrate circuit breaker with timeout manager', async () => { const timeoutManager = TimeoutManager.getInstance(); const circuitBreaker = CircuitBreakerFactory.createServiceCircuitBreaker('timeout-test'); const slowOperation = () => new Promise(resolve => setTimeout(resolve, 2000)); // Should timeout and trigger circuit breaker failure await expect( timeoutManager.executeWithTimeout( async () => await circuitBreaker.execute(slowOperation), 'generic', { name: 'slow-test', priority: 'low', canAbort: true } ) ).rejects.toThrow(); const metrics = circuitBreaker.getMetrics(); expect(metrics.failureCount).toBeGreaterThan(0); }); it('should integrate retry manager with graceful degradation', async () => { const retryManager = RetryManager.getInstance(); const degradationManager = GracefulDegradationManager.getInstance(); let callCount = 0; const operation = vi.fn().mockImplementation(async () => { callCount++; if (callCount <= 2) { throw new Error('Database connection failed'); } return 'database result'; }); const result = await degradationManager.executeWithFallback( 'test-db-service', async () => { return await retryManager.executeWithRetry( operation, 'trajectory-store', { name: 'db-operation', priority: 'medium', canAbort: true } ); }, { name: 'test-context' }, 'fallback-data' ); expect(result).toBe('database result'); expect(callCount).toBe(3); // 1 initial + 2 retries }); });

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/sloth-wq/prompt-auto-optimizer-mcp'

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