Spaces:
Sleeping
Sleeping
| """ | |
| Test to ensure PlayerState slots are complete. | |
| This test prevents the class of bugs where dynamic attributes are lost during state copying | |
| because they aren't declared in __slots__. | |
| """ | |
| import numpy as np | |
| import pytest | |
| from engine.game.player_state import PlayerState | |
| class TestPlayerStateSlotCompleteness: | |
| """Verify all attributes are properly declared in __slots__.""" | |
| def test_no_dynamic_attributes_after_init(self): | |
| """PlayerState should have no __dict__ (pure __slots__ class).""" | |
| ps = PlayerState(0) | |
| # __slots__ classes should not have __dict__ unless explicitly added | |
| # However, if parent class doesn't use __slots__, __dict__ may exist but be empty | |
| if hasattr(ps, "__dict__"): | |
| assert len(ps.__dict__) == 0, f"PlayerState has dynamic attributes not in __slots__: {ps.__dict__}" | |
| def test_all_slots_have_default_values(self): | |
| """All slots should be initialized in __init__.""" | |
| ps = PlayerState(0) | |
| for slot in PlayerState.__slots__: | |
| assert hasattr(ps, slot), f"Slot '{slot}' not initialized in __init__" | |
| def test_copy_preserves_all_slots(self): | |
| """copy() should preserve all slot values.""" | |
| ps1 = PlayerState(0) | |
| # Modify some values to non-default | |
| ps1.hand = [1, 2, 3] | |
| ps1.tapped_members[0] = True | |
| ps1.rested_members[1] = True | |
| ps1.performance_abilities_processed = True | |
| ps1.revealed_hand = True | |
| ps1.deck_refreshed_this_turn = True | |
| ps1.baton_touch_count = 5 | |
| # Copy | |
| ps2 = ps1.copy() | |
| # Verify all values copied | |
| assert ps2.hand == [1, 2, 3] | |
| assert ps2.tapped_members[0] == True | |
| assert ps2.rested_members[1] == True | |
| assert ps2.performance_abilities_processed == True | |
| assert ps2.revealed_hand == True | |
| assert ps2.deck_refreshed_this_turn == True | |
| assert ps2.baton_touch_count == 5 | |
| # Verify copies are independent (deep copy for mutable types) | |
| ps2.hand.append(4) | |
| assert ps1.hand == [1, 2, 3], "hand should be deep copied" | |
| ps2.tapped_members[0] = False | |
| assert ps1.tapped_members[0] == True, "numpy arrays should be deep copied" | |
| def test_reset_clears_all_mutable_state(self): | |
| """_reset() should restore all slots to defaults.""" | |
| ps = PlayerState(0) | |
| # Modify state | |
| ps.hand = [1, 2, 3] | |
| ps.performance_abilities_processed = True | |
| ps.revealed_hand = True | |
| ps.rested_members[0] = True | |
| # Reset | |
| ps._reset(0) | |
| # Verify reset | |
| assert ps.hand == [] | |
| assert ps.performance_abilities_processed == False | |
| assert ps.revealed_hand == False | |
| assert not np.any(ps.rested_members) | |
| if __name__ == "__main__": | |
| pytest.main([__file__, "-v"]) | |