✅ Phase 3: Decision Framework Tests - Decision engine functionality tests - Voting system tests (majority, weighted, unanimous) - Consensus algorithm tests - Agent lifecycle management tests - Integration tests for decision processes ✅ Phase 4: Autonomous Decision Making Tests - Autonomous decision engine tests - Learning system tests (experience-based learning) - Policy engine tests (compliance evaluation) - Self-correction mechanism tests - Goal-oriented behavior tests - Full autonomous cycle integration tests ✅ Phase 5: Computer Vision Integration Tests - Vision processor tests (object detection, scene analysis, OCR) - Multi-modal integration tests - Context integration tests - Visual reasoning tests (spatial, temporal) - Performance metrics tests - End-to-end vision pipeline tests ✅ Test Infrastructure - Comprehensive test runner for all phases - Mock implementations for testing - Performance testing capabilities - Integration test coverage - Phase-based test organization 🚀 All Phase Tests Now Implemented and Ready for Execution!
533 lines
19 KiB
Python
533 lines
19 KiB
Python
"""
|
|
Phase 4: Autonomous Decision Making Tests
|
|
Tests for autonomous systems, learning, and adaptation
|
|
"""
|
|
|
|
import pytest
|
|
import asyncio
|
|
import json
|
|
from datetime import datetime, timedelta
|
|
from unittest.mock import Mock, AsyncMock
|
|
from typing import Dict, List, Any, Optional
|
|
|
|
# Mock imports for testing
|
|
class MockAutonomousEngine:
|
|
def __init__(self):
|
|
self.policies = {}
|
|
self.decisions = []
|
|
self.learning_data = {}
|
|
self.performance_metrics = {}
|
|
|
|
async def make_autonomous_decision(self, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Make autonomous decision based on context"""
|
|
decision_id = f"auto_decision_{len(self.decisions)}"
|
|
decision = {
|
|
'decision_id': decision_id,
|
|
'context': context,
|
|
'action': self._determine_action(context),
|
|
'reasoning': self._generate_reasoning(context),
|
|
'confidence': self._calculate_confidence(context),
|
|
'timestamp': datetime.utcnow().isoformat()
|
|
}
|
|
self.decisions.append(decision)
|
|
return decision
|
|
|
|
def _determine_action(self, context: Dict[str, Any]) -> str:
|
|
"""Determine action based on context"""
|
|
if context.get('system_load', 0) > 0.8:
|
|
return 'scale_resources'
|
|
elif context.get('error_rate', 0) > 0.1:
|
|
return 'trigger_recovery'
|
|
elif context.get('task_queue_size', 0) > 100:
|
|
return 'allocate_more_agents'
|
|
else:
|
|
return 'maintain_status'
|
|
|
|
def _generate_reasoning(self, context: Dict[str, Any]) -> str:
|
|
"""Generate reasoning for decision"""
|
|
return f"Based on system metrics: load={context.get('system_load', 0)}, errors={context.get('error_rate', 0)}"
|
|
|
|
def _calculate_confidence(self, context: Dict[str, Any]) -> float:
|
|
"""Calculate confidence in decision"""
|
|
# Simple confidence calculation based on data quality
|
|
has_metrics = all(key in context for key in ['system_load', 'error_rate'])
|
|
return 0.9 if has_metrics else 0.6
|
|
|
|
class MockLearningSystem:
|
|
def __init__(self):
|
|
self.experience_buffer = []
|
|
self.performance_history = []
|
|
self.adaptations = {}
|
|
|
|
async def learn_from_experience(self, experience: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Learn from experience"""
|
|
experience_id = f"exp_{len(self.experience_buffer)}"
|
|
learning_data = {
|
|
'experience_id': experience_id,
|
|
'experience': experience,
|
|
'lessons_learned': self._extract_lessons(experience),
|
|
'performance_impact': self._calculate_impact(experience),
|
|
'timestamp': datetime.utcnow().isoformat()
|
|
}
|
|
self.experience_buffer.append(learning_data)
|
|
return learning_data
|
|
|
|
def _extract_lessons(self, experience: Dict[str, Any]) -> List[str]:
|
|
"""Extract lessons from experience"""
|
|
lessons = []
|
|
if experience.get('success', False):
|
|
lessons.append("Action was successful")
|
|
if experience.get('performance_gain', 0) > 0:
|
|
lessons.append("Performance improved")
|
|
return lessons
|
|
|
|
def _calculate_impact(self, experience: Dict[str, Any]) -> float:
|
|
"""Calculate performance impact"""
|
|
return experience.get('performance_gain', 0.0)
|
|
|
|
async def adapt_behavior(self, adaptation_data: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Adapt behavior based on learning"""
|
|
adaptation_id = f"adapt_{len(self.adaptations)}"
|
|
adaptation = {
|
|
'adaptation_id': adaptation_id,
|
|
'type': adaptation_data.get('type', 'parameter_adjustment'),
|
|
'changes': adaptation_data.get('changes', {}),
|
|
'expected_improvement': adaptation_data.get('expected_improvement', 0.1),
|
|
'timestamp': datetime.utcnow().isoformat()
|
|
}
|
|
self.adaptations[adaptation_id] = adaptation
|
|
return adaptation
|
|
|
|
class MockPolicyEngine:
|
|
def __init__(self):
|
|
self.policies = {
|
|
'resource_management': {
|
|
'max_cpu_usage': 0.8,
|
|
'max_memory_usage': 0.85,
|
|
'auto_scale_threshold': 0.7
|
|
},
|
|
'error_handling': {
|
|
'max_error_rate': 0.05,
|
|
'retry_attempts': 3,
|
|
'recovery_timeout': 300
|
|
},
|
|
'task_management': {
|
|
'max_queue_size': 1000,
|
|
'task_timeout': 600,
|
|
'priority_weights': {'high': 1.0, 'normal': 0.5, 'low': 0.2}
|
|
}
|
|
}
|
|
|
|
async def evaluate_policy_compliance(self, decision: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Evaluate if decision complies with policies"""
|
|
compliance_score = self._calculate_compliance(decision)
|
|
violations = self._find_violations(decision)
|
|
|
|
return {
|
|
'decision_id': decision.get('decision_id'),
|
|
'compliance_score': compliance_score,
|
|
'violations': violations,
|
|
'approved': compliance_score >= 0.8 and len(violations) == 0,
|
|
'timestamp': datetime.utcnow().isoformat()
|
|
}
|
|
|
|
def _calculate_compliance(self, decision: Dict[str, Any]) -> float:
|
|
"""Calculate policy compliance score"""
|
|
# Simplified compliance calculation
|
|
base_score = 1.0
|
|
if decision.get('action') == 'scale_resources':
|
|
# Check resource management policy
|
|
base_score -= 0.1 # Small penalty for resource scaling
|
|
return max(0.0, base_score)
|
|
|
|
def _find_violations(self, decision: Dict[str, Any]) -> List[str]:
|
|
"""Find policy violations"""
|
|
violations = []
|
|
context = decision.get('context', {})
|
|
|
|
# Check resource limits
|
|
if context.get('system_load', 0) > self.policies['resource_management']['max_cpu_usage']:
|
|
violations.append("CPU usage exceeds policy limit")
|
|
|
|
return violations
|
|
|
|
class TestAutonomousEngine:
|
|
"""Test autonomous decision making engine"""
|
|
|
|
def setup_method(self):
|
|
self.autonomous_engine = MockAutonomousEngine()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_autonomous_decision_making(self):
|
|
"""Test basic autonomous decision making"""
|
|
context = {
|
|
'system_load': 0.9,
|
|
'error_rate': 0.02,
|
|
'task_queue_size': 50,
|
|
'active_agents': 5
|
|
}
|
|
|
|
decision = await self.autonomous_engine.make_autonomous_decision(context)
|
|
|
|
assert decision['action'] == 'scale_resources'
|
|
assert decision['confidence'] > 0.5
|
|
assert 'reasoning' in decision
|
|
assert 'timestamp' in decision
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_decision_with_high_error_rate(self):
|
|
"""Test decision making with high error rate"""
|
|
context = {
|
|
'system_load': 0.4,
|
|
'error_rate': 0.15,
|
|
'task_queue_size': 30,
|
|
'active_agents': 3
|
|
}
|
|
|
|
decision = await self.autonomous_engine.make_autonomous_decision(context)
|
|
|
|
assert decision['action'] == 'trigger_recovery'
|
|
assert 'error_rate' in decision['reasoning']
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_decision_with_task_queue_pressure(self):
|
|
"""Test decision making with task queue pressure"""
|
|
context = {
|
|
'system_load': 0.6,
|
|
'error_rate': 0.03,
|
|
'task_queue_size': 150,
|
|
'active_agents': 4
|
|
}
|
|
|
|
decision = await self.autonomous_engine.make_autonomous_decision(context)
|
|
|
|
assert decision['action'] == 'allocate_more_agents'
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_decision_with_normal_conditions(self):
|
|
"""Test decision making with normal conditions"""
|
|
context = {
|
|
'system_load': 0.5,
|
|
'error_rate': 0.02,
|
|
'task_queue_size': 25,
|
|
'active_agents': 4
|
|
}
|
|
|
|
decision = await self.autonomous_engine.make_autonomous_decision(context)
|
|
|
|
assert decision['action'] == 'maintain_status'
|
|
assert decision['confidence'] > 0.8
|
|
|
|
class TestLearningSystem:
|
|
"""Test learning and adaptation system"""
|
|
|
|
def setup_method(self):
|
|
self.learning_system = MockLearningSystem()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_learning_from_successful_experience(self):
|
|
"""Test learning from successful experience"""
|
|
experience = {
|
|
'action': 'scale_resources',
|
|
'success': True,
|
|
'performance_gain': 0.15,
|
|
'context': {'system_load': 0.9}
|
|
}
|
|
|
|
learning_result = await self.learning_system.learn_from_experience(experience)
|
|
|
|
assert learning_result['experience_id'].startswith('exp_')
|
|
assert 'lessons_learned' in learning_result
|
|
assert learning_result['performance_impact'] == 0.15
|
|
assert 'Action was successful' in learning_result['lessons_learned']
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_learning_from_failure(self):
|
|
"""Test learning from failed experience"""
|
|
experience = {
|
|
'action': 'scale_resources',
|
|
'success': False,
|
|
'performance_gain': -0.05,
|
|
'context': {'system_load': 0.9}
|
|
}
|
|
|
|
learning_result = await self.learning_system.learn_from_experience(experience)
|
|
|
|
assert learning_result['experience_id'].startswith('exp_')
|
|
assert learning_result['performance_impact'] == -0.05
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_behavior_adaptation(self):
|
|
"""Test behavior adaptation based on learning"""
|
|
adaptation_data = {
|
|
'type': 'threshold_adjustment',
|
|
'changes': {'scale_threshold': 0.75, 'error_threshold': 0.08},
|
|
'expected_improvement': 0.1
|
|
}
|
|
|
|
adaptation = await self.learning_system.adapt_behavior(adaptation_data)
|
|
|
|
assert adaptation['type'] == 'threshold_adjustment'
|
|
assert adaptation['expected_improvement'] == 0.1
|
|
assert 'scale_threshold' in adaptation['changes']
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_experience_accumulation(self):
|
|
"""Test accumulation of experiences over time"""
|
|
experiences = [
|
|
{'action': 'scale_resources', 'success': True, 'performance_gain': 0.1},
|
|
{'action': 'allocate_agents', 'success': True, 'performance_gain': 0.05},
|
|
{'action': 'trigger_recovery', 'success': False, 'performance_gain': -0.02}
|
|
]
|
|
|
|
for exp in experiences:
|
|
await self.learning_system.learn_from_experience(exp)
|
|
|
|
assert len(self.learning_system.experience_buffer) == 3
|
|
assert all(exp['experience_id'].startswith('exp_') for exp in self.learning_system.experience_buffer)
|
|
|
|
class TestPolicyEngine:
|
|
"""Test policy engine for autonomous decisions"""
|
|
|
|
def setup_method(self):
|
|
self.policy_engine = MockPolicyEngine()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_policy_compliance_evaluation(self):
|
|
"""Test policy compliance evaluation"""
|
|
decision = {
|
|
'decision_id': 'test_decision_001',
|
|
'action': 'scale_resources',
|
|
'context': {
|
|
'system_load': 0.7,
|
|
'error_rate': 0.03,
|
|
'task_queue_size': 50
|
|
}
|
|
}
|
|
|
|
compliance = await self.policy_engine.evaluate_policy_compliance(decision)
|
|
|
|
assert compliance['decision_id'] == 'test_decision_001'
|
|
assert 'compliance_score' in compliance
|
|
assert 'violations' in compliance
|
|
assert 'approved' in compliance
|
|
assert 'timestamp' in compliance
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_policy_violation_detection(self):
|
|
"""Test detection of policy violations"""
|
|
decision = {
|
|
'decision_id': 'test_decision_002',
|
|
'action': 'scale_resources',
|
|
'context': {
|
|
'system_load': 0.9, # Exceeds policy limit
|
|
'error_rate': 0.03,
|
|
'task_queue_size': 50
|
|
}
|
|
}
|
|
|
|
compliance = await self.policy_engine.evaluate_policy_compliance(decision)
|
|
|
|
assert len(compliance['violations']) > 0
|
|
assert any('CPU usage' in violation for violation in compliance['violations'])
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_policy_approval(self):
|
|
"""Test policy approval for compliant decisions"""
|
|
decision = {
|
|
'decision_id': 'test_decision_003',
|
|
'action': 'maintain_status',
|
|
'context': {
|
|
'system_load': 0.5,
|
|
'error_rate': 0.02,
|
|
'task_queue_size': 25
|
|
}
|
|
}
|
|
|
|
compliance = await self.policy_engine.evaluate_policy_compliance(decision)
|
|
|
|
assert compliance['approved'] is True
|
|
assert compliance['compliance_score'] >= 0.8
|
|
|
|
class TestSelfCorrectionMechanism:
|
|
"""Test self-correction mechanisms"""
|
|
|
|
def setup_method(self):
|
|
self.autonomous_engine = MockAutonomousEngine()
|
|
self.learning_system = MockLearningSystem()
|
|
self.policy_engine = MockPolicyEngine()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_automatic_error_correction(self):
|
|
"""Test automatic error correction"""
|
|
# Simulate error condition
|
|
context = {
|
|
'system_load': 0.9,
|
|
'error_rate': 0.12, # High error rate
|
|
'task_queue_size': 50
|
|
}
|
|
|
|
# Make initial decision
|
|
decision = await self.autonomous_engine.make_autonomous_decision(context)
|
|
|
|
# Simulate error in execution
|
|
error_experience = {
|
|
'action': decision['action'],
|
|
'success': False,
|
|
'error_type': 'resource_exhaustion',
|
|
'performance_gain': -0.1
|
|
}
|
|
|
|
# Learn from error
|
|
learning_result = await self.learning_system.learn_from_experience(error_experience)
|
|
|
|
# Adapt behavior
|
|
adaptation_data = {
|
|
'type': 'resource_threshold_adjustment',
|
|
'changes': {'scale_threshold': 0.8},
|
|
'expected_improvement': 0.15
|
|
}
|
|
|
|
adaptation = await self.learning_system.adapt_behavior(adaptation_data)
|
|
|
|
# Verify self-correction
|
|
assert decision['action'] == 'trigger_recovery'
|
|
assert learning_result['experience_id'].startswith('exp_')
|
|
assert adaptation['type'] == 'resource_threshold_adjustment'
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_performance_optimization(self):
|
|
"""Test performance optimization through learning"""
|
|
# Initial performance
|
|
initial_context = {
|
|
'system_load': 0.7,
|
|
'error_rate': 0.05,
|
|
'task_queue_size': 80
|
|
}
|
|
|
|
decision = await self.autonomous_engine.make_autonomous_decision(initial_context)
|
|
|
|
# Simulate successful execution with performance gain
|
|
success_experience = {
|
|
'action': decision['action'],
|
|
'success': True,
|
|
'performance_gain': 0.2
|
|
}
|
|
|
|
learning_result = await self.learning_system.learn_from_experience(success_experience)
|
|
|
|
# Adapt to optimize further
|
|
adaptation_data = {
|
|
'type': 'performance_optimization',
|
|
'changes': {'aggressive_scaling': True},
|
|
'expected_improvement': 0.1
|
|
}
|
|
|
|
adaptation = await self.learning_system.adapt_behavior(adaptation_data)
|
|
|
|
# Verify optimization
|
|
assert learning_result['performance_impact'] == 0.2
|
|
assert adaptation['type'] == 'performance_optimization'
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_goal_oriented_behavior(self):
|
|
"""Test goal-oriented autonomous behavior"""
|
|
# Define goals
|
|
goals = {
|
|
'primary_goal': 'maintain_system_stability',
|
|
'secondary_goals': ['optimize_performance', 'minimize_errors'],
|
|
'constraints': ['resource_limits', 'policy_compliance']
|
|
}
|
|
|
|
# Simulate goal-oriented decision making
|
|
context = {
|
|
'system_load': 0.6,
|
|
'error_rate': 0.04,
|
|
'task_queue_size': 60,
|
|
'goals': goals
|
|
}
|
|
|
|
decision = await self.autonomous_engine.make_autonomous_decision(context)
|
|
|
|
# Evaluate against goals
|
|
compliance = await self.policy_engine.evaluate_policy_compliance(decision)
|
|
|
|
# Verify goal alignment
|
|
assert decision['action'] in ['maintain_status', 'allocate_more_agents']
|
|
assert compliance['approved'] is True # Should be policy compliant
|
|
|
|
# Integration tests
|
|
class TestAutonomousIntegration:
|
|
"""Integration tests for autonomous systems"""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_full_autonomous_cycle(self):
|
|
"""Test complete autonomous decision cycle"""
|
|
autonomous_engine = MockAutonomousEngine()
|
|
learning_system = MockLearningSystem()
|
|
policy_engine = MockPolicyEngine()
|
|
|
|
# Step 1: Make autonomous decision
|
|
context = {
|
|
'system_load': 0.85,
|
|
'error_rate': 0.08,
|
|
'task_queue_size': 120
|
|
}
|
|
|
|
decision = await autonomous_engine.make_autonomous_decision(context)
|
|
|
|
# Step 2: Evaluate policy compliance
|
|
compliance = await policy_engine.evaluate_policy_compliance(decision)
|
|
|
|
# Step 3: Execute and learn from result
|
|
execution_result = {
|
|
'action': decision['action'],
|
|
'success': compliance['approved'],
|
|
'performance_gain': 0.1 if compliance['approved'] else -0.05
|
|
}
|
|
|
|
learning_result = await learning_system.learn_from_experience(execution_result)
|
|
|
|
# Step 4: Adapt if needed
|
|
if not compliance['approved']:
|
|
adaptation = await learning_system.adapt_behavior({
|
|
'type': 'policy_compliance',
|
|
'changes': {'more_conservative_thresholds': True}
|
|
})
|
|
|
|
# Verify complete cycle
|
|
assert decision['decision_id'].startswith('auto_decision_')
|
|
assert 'compliance_score' in compliance
|
|
assert learning_result['experience_id'].startswith('exp_')
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_multi_goal_optimization(self):
|
|
"""Test optimization across multiple goals"""
|
|
goals = {
|
|
'stability': {'weight': 0.4, 'target': 0.95},
|
|
'performance': {'weight': 0.3, 'target': 0.8},
|
|
'efficiency': {'weight': 0.3, 'target': 0.75}
|
|
}
|
|
|
|
contexts = [
|
|
{'system_load': 0.7, 'error_rate': 0.05, 'goals': goals},
|
|
{'system_load': 0.8, 'error_rate': 0.06, 'goals': goals},
|
|
{'system_load': 0.6, 'error_rate': 0.04, 'goals': goals}
|
|
]
|
|
|
|
autonomous_engine = MockAutonomousEngine()
|
|
decisions = []
|
|
|
|
for context in contexts:
|
|
decision = await autonomous_engine.make_autonomous_decision(context)
|
|
decisions.append(decision)
|
|
|
|
# Verify multi-goal consideration
|
|
assert len(decisions) == 3
|
|
for decision in decisions:
|
|
assert 'action' in decision
|
|
assert 'confidence' in decision
|
|
|
|
if __name__ == '__main__':
|
|
pytest.main([__file__])
|