""" Tests for the personality matrix system. """ import pytest import torch import numpy as np from datetime import datetime, timedelta from lyra.personality.matrix import PersonalityMatrix, PersonalityTrait from lyra.personality.traits import OCEANTraits, MyersBriggsType, MyersBriggsAnalyzer from tests.conftest import assert_tensor_shape, assert_tensor_range class TestPersonalityTrait: """Tests for individual personality traits.""" def test_trait_initialization(self): """Test trait initialization with default values.""" trait = PersonalityTrait("test_trait", 0.7) assert trait.name == "test_trait" assert trait.value == 0.7 assert trait.variance == 0.1 assert trait.adaptation_rate == 0.01 assert len(trait.change_history) == 0 assert trait.stability == 0.8 def test_trait_evolution(self): """Test trait evolution with influence.""" trait = PersonalityTrait("test_trait", 0.5, adaptation_rate=0.1) original_value = trait.value # Positive influence trait.evolve(0.5, "positive_interaction") assert trait.value > original_value assert len(trait.change_history) == 1 assert trait.change_history[0][1] == "positive_interaction" # Negative influence trait.evolve(-0.3, "negative_feedback") assert len(trait.change_history) == 2 def test_trait_value_bounds(self): """Test that trait values stay within bounds [0, 1].""" trait = PersonalityTrait("test_trait", 0.9) # Try to exceed upper bound trait.evolve(1.0, "extreme_positive") assert 0.0 <= trait.value <= 1.0 # Try to exceed lower bound trait.value = 0.1 trait.evolve(-1.0, "extreme_negative") assert 0.0 <= trait.value <= 1.0 class TestOCEANTraits: """Tests for OCEAN personality traits.""" def test_ocean_initialization(self, sample_ocean_traits): """Test OCEAN traits initialization.""" traits = sample_ocean_traits assert 0.0 <= traits.openness <= 1.0 assert 0.0 <= traits.conscientiousness <= 1.0 assert 0.0 <= traits.extraversion <= 1.0 assert 0.0 <= traits.agreeableness <= 1.0 assert 0.0 <= traits.neuroticism <= 1.0 def test_ocean_to_tensor(self, sample_ocean_traits, device): """Test conversion to tensor.""" tensor = sample_ocean_traits.to_tensor(device) assert_tensor_shape(tensor, (5,), "OCEAN tensor") assert_tensor_range(tensor, 0.0, 1.0, "OCEAN values") def test_ocean_to_dict(self, sample_ocean_traits): """Test conversion to dictionary.""" trait_dict = sample_ocean_traits.to_dict() expected_keys = [ 'openness', 'conscientiousness', 'extraversion', 'agreeableness', 'neuroticism', 'openness_variance', 'conscientiousness_variance', 'extraversion_variance', 'agreeableness_variance', 'neuroticism_variance' ] for key in expected_keys: assert key in trait_dict assert isinstance(trait_dict[key], float) def test_situational_modification(self, sample_ocean_traits): """Test situational personality modifications.""" original_traits = sample_ocean_traits modified_traits = original_traits.apply_situational_modification('stress', 1.0) # Stress should increase neuroticism assert modified_traits.neuroticism >= original_traits.neuroticism # Should stay within bounds assert 0.0 <= modified_traits.neuroticism <= 1.0 class TestMyersBriggsAnalyzer: """Tests for Myers-Briggs analysis.""" def test_analyzer_initialization(self): """Test analyzer initialization.""" analyzer = MyersBriggsAnalyzer() assert hasattr(analyzer, 'mb_mappings') assert len(analyzer.mb_mappings) == 4 # E_I, S_N, T_F, J_P def test_type_analysis(self, sample_ocean_traits): """Test Myers-Briggs type determination.""" analyzer = MyersBriggsAnalyzer() mb_type = analyzer.analyze_type(sample_ocean_traits) assert isinstance(mb_type, MyersBriggsType) assert len(mb_type.value) == 4 assert all(c in "ENTJFPS" for c in mb_type.value) def test_type_characteristics(self): """Test getting type characteristics.""" analyzer = MyersBriggsAnalyzer() characteristics = analyzer.get_type_characteristics(MyersBriggsType.ENFP) expected_keys = [ 'communication_style', 'decision_making', 'social_tendencies', 'stress_response', 'learning_preference', 'humor_style' ] for key in expected_keys: assert key in characteristics assert isinstance(characteristics[key], str) class TestPersonalityMatrix: """Tests for the personality matrix system.""" @pytest.mark.asyncio async def test_matrix_initialization(self, device): """Test personality matrix initialization.""" matrix = PersonalityMatrix(device=device, enable_self_modification=True) assert matrix.device == device assert matrix.enable_self_modification is True assert isinstance(matrix.ocean_traits, OCEANTraits) assert isinstance(matrix.mb_type, MyersBriggsType) assert len(matrix.custom_traits) > 0 @pytest.mark.asyncio async def test_matrix_forward_pass(self, personality_matrix, sample_context_embedding, sample_emotional_tensor): """Test personality matrix forward pass.""" weights, info = personality_matrix( context_embedding=sample_context_embedding, emotional_state=sample_emotional_tensor ) assert_tensor_shape(weights, (1, 10), "personality weights") assert isinstance(info, dict) assert 'current_ocean' in info assert 'myers_briggs' in info assert 'custom_traits' in info @pytest.mark.asyncio async def test_personality_evolution_from_interaction(self, personality_matrix): """Test personality evolution from interaction.""" original_traits = personality_matrix.ocean_traits.to_dict() # Simulate positive interaction personality_matrix.evolve_from_interaction( interaction_type='support', user_feedback=0.9, emotional_context={'joy': 0.8}, conversation_success=0.8 ) # Check that evolution occurred new_traits = personality_matrix.ocean_traits.to_dict() assert personality_matrix.evolution.total_interactions == 1 assert len(personality_matrix.evolution.evolution_history) == 1 @pytest.mark.asyncio async def test_conscious_personality_modification(self, personality_matrix): """Test conscious personality modification.""" original_openness = personality_matrix.ocean_traits.openness # Consciously modify openness result = personality_matrix.consciously_modify_trait( 'openness', 0.8, 'self-directed_growth' ) assert result is True assert personality_matrix.ocean_traits.openness != original_openness @pytest.mark.asyncio async def test_relationship_dynamics_update(self, personality_matrix): """Test relationship dynamics tracking.""" user_id = "test_user_123" # First interaction personality_matrix.evolve_from_interaction( interaction_type='casual', user_feedback=0.7, emotional_context={'curiosity': 0.6}, user_id=user_id, conversation_success=0.7 ) assert user_id in personality_matrix.relationship_dynamics rel_data = personality_matrix.relationship_dynamics[user_id] assert rel_data['interaction_count'] == 1 assert rel_data['familiarity'] > 0 @pytest.mark.asyncio async def test_personality_summary(self, personality_matrix): """Test personality summary generation.""" summary = personality_matrix.get_personality_summary() required_keys = [ 'ocean_traits', 'myers_briggs_type', 'custom_traits', 'evolution_stats', 'self_awareness', 'relationship_count' ] for key in required_keys: assert key in summary assert isinstance(summary['ocean_traits'], dict) assert isinstance(summary['custom_traits'], dict) @pytest.mark.asyncio async def test_personality_persistence(self, personality_matrix, temp_directory): """Test saving and loading personality state.""" save_path = temp_directory / "personality_test.json" # Modify personality and save personality_matrix.ocean_traits.openness = 0.9 personality_matrix.custom_traits['humor_level'].value = 0.8 personality_matrix.save_personality(save_path) assert save_path.exists() # Create new matrix and load new_matrix = PersonalityMatrix(device=personality_matrix.device) new_matrix.load_personality(save_path) assert abs(new_matrix.ocean_traits.openness - 0.9) < 0.01 assert abs(new_matrix.custom_traits['humor_level'].value - 0.8) < 0.01 @pytest.mark.asyncio async def test_personality_simulation(self, personality_matrix): """Test personality development simulation.""" original_interactions = personality_matrix.evolution.total_interactions # Run short simulation simulation_result = personality_matrix.simulate_personality_development(days=3) assert 'simulation_days' in simulation_result assert 'final_personality' in simulation_result assert 'development_log' in simulation_result # Should have more interactions assert personality_matrix.evolution.total_interactions > original_interactions def test_personality_matrix_device_handling(self, device): """Test proper device handling.""" matrix = PersonalityMatrix(device=device) assert matrix.device == device # Test with CUDA if available if torch.cuda.is_available(): cuda_device = torch.device("cuda:0") cuda_matrix = PersonalityMatrix(device=cuda_device) assert cuda_matrix.device == cuda_device @pytest.mark.asyncio async def test_self_awareness_updates(self, personality_matrix): """Test self-awareness metric updates.""" original_awareness = personality_matrix.self_awareness.copy() # Multiple successful interactions should increase self-awareness for _ in range(5): personality_matrix.evolve_from_interaction( interaction_type='analytical', user_feedback=0.8, emotional_context={'curiosity': 0.7}, conversation_success=0.8 ) # Check that some aspect of self-awareness improved new_awareness = personality_matrix.self_awareness awareness_increased = any( new_awareness[key] > original_awareness[key] for key in original_awareness.keys() ) assert awareness_increased