"""Tests for EncryptionService - T12. Tests for AES-256-GCM encryption service using cryptography.fernet. """ import pytest from cryptography.fernet import InvalidToken pytestmark = [pytest.mark.unit, pytest.mark.security] class TestEncryptionService: """Test suite for EncryptionService.""" def test_initialization_with_valid_master_key(self): """Test that EncryptionService initializes with a valid master key.""" # Arrange & Act from src.openrouter_monitor.services.encryption import EncryptionService service = EncryptionService("test-encryption-key-32bytes-long") # Assert assert service is not None assert service._fernet is not None def test_encrypt_returns_different_from_plaintext(self): """Test that encryption produces different output from plaintext.""" # Arrange from src.openrouter_monitor.services.encryption import EncryptionService service = EncryptionService("test-encryption-key-32bytes-long") plaintext = "sensitive-api-key-12345" # Act encrypted = service.encrypt(plaintext) # Assert assert encrypted != plaintext assert isinstance(encrypted, str) assert len(encrypted) > 0 def test_encrypt_decrypt_roundtrip_returns_original(self): """Test that encrypt followed by decrypt returns original plaintext.""" # Arrange from src.openrouter_monitor.services.encryption import EncryptionService service = EncryptionService("test-encryption-key-32bytes-long") plaintext = "my-secret-api-key-abc123" # Act encrypted = service.encrypt(plaintext) decrypted = service.decrypt(encrypted) # Assert assert decrypted == plaintext def test_encrypt_produces_different_ciphertext_each_time(self): """Test that encrypting same plaintext produces different ciphertexts.""" # Arrange from src.openrouter_monitor.services.encryption import EncryptionService service = EncryptionService("test-encryption-key-32bytes-long") plaintext = "same-text-every-time" # Act encrypted1 = service.encrypt(plaintext) encrypted2 = service.encrypt(plaintext) # Assert assert encrypted1 != encrypted2 def test_decrypt_with_wrong_key_raises_invalid_token(self): """Test that decrypting with wrong key raises InvalidToken.""" # Arrange from src.openrouter_monitor.services.encryption import EncryptionService service1 = EncryptionService("correct-key-32-chars-long!!!") service2 = EncryptionService("wrong-key-32-chars-long!!!!!") plaintext = "secret-data" encrypted = service1.encrypt(plaintext) # Act & Assert with pytest.raises(InvalidToken): service2.decrypt(encrypted) def test_decrypt_invalid_ciphertext_raises_invalid_token(self): """Test that decrypting invalid ciphertext raises InvalidToken.""" # Arrange from src.openrouter_monitor.services.encryption import EncryptionService service = EncryptionService("test-encryption-key-32bytes-long") # Act & Assert with pytest.raises(InvalidToken): service.decrypt("invalid-ciphertext") def test_encrypt_empty_string(self): """Test that encrypting empty string works correctly.""" # Arrange from src.openrouter_monitor.services.encryption import EncryptionService service = EncryptionService("test-encryption-key-32bytes-long") plaintext = "" # Act encrypted = service.encrypt(plaintext) decrypted = service.decrypt(encrypted) # Assert assert decrypted == plaintext def test_encrypt_unicode_characters(self): """Test that encrypting unicode characters works correctly.""" # Arrange from src.openrouter_monitor.services.encryption import EncryptionService service = EncryptionService("test-encryption-key-32bytes-long") plaintext = "🔑 API Key: 日本語-test-ñ" # Act encrypted = service.encrypt(plaintext) decrypted = service.decrypt(encrypted) # Assert assert decrypted == plaintext def test_encrypt_special_characters(self): """Test that encrypting special characters works correctly.""" # Arrange from src.openrouter_monitor.services.encryption import EncryptionService service = EncryptionService("test-encryption-key-32bytes-long") plaintext = "!@#$%^&*()_+-=[]{}|;':\",./<>?" # Act encrypted = service.encrypt(plaintext) decrypted = service.decrypt(encrypted) # Assert assert decrypted == plaintext def test_encrypt_long_text(self): """Test that encrypting long text works correctly.""" # Arrange from src.openrouter_monitor.services.encryption import EncryptionService service = EncryptionService("test-encryption-key-32bytes-long") plaintext = "a" * 10000 # Act encrypted = service.encrypt(plaintext) decrypted = service.decrypt(encrypted) # Assert assert decrypted == plaintext def test_encrypt_non_string_raises_type_error(self): """Test that encrypting non-string raises TypeError.""" # Arrange from src.openrouter_monitor.services.encryption import EncryptionService service = EncryptionService("test-encryption-key-32bytes-long") # Act & Assert with pytest.raises(TypeError, match="plaintext must be a string"): service.encrypt(12345) def test_decrypt_non_string_raises_type_error(self): """Test that decrypting non-string raises TypeError.""" # Arrange from src.openrouter_monitor.services.encryption import EncryptionService service = EncryptionService("test-encryption-key-32bytes-long") # Act & Assert with pytest.raises(TypeError, match="ciphertext must be a string"): service.decrypt(12345)