- Add core task execution framework - Add LLM integration with DeepSeek - Add text analysis task implementation - Add configuration management - Add tests and documentation
137 lines
4.7 KiB
Python
137 lines
4.7 KiB
Python
import os
|
|
import json
|
|
import pytest
|
|
from pathlib import Path
|
|
from config.secure_config import SecureConfig
|
|
from config.config_loader import load_config, save_api_key
|
|
|
|
@pytest.fixture
|
|
def temp_dir(tmp_path):
|
|
"""Create a temporary directory for test files."""
|
|
return tmp_path
|
|
|
|
@pytest.fixture
|
|
def secure_config(temp_dir):
|
|
"""Create a SecureConfig instance with a temporary key file."""
|
|
return SecureConfig(str(temp_dir / "test_secure.key"))
|
|
|
|
@pytest.fixture
|
|
def test_config_dir(temp_dir, monkeypatch):
|
|
"""Set up a test configuration directory."""
|
|
# Create config directory
|
|
config_dir = temp_dir / "config"
|
|
config_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
# Create test YAML config
|
|
yaml_content = """
|
|
llm:
|
|
provider: openai
|
|
model: gpt-4
|
|
max_tokens: 2000
|
|
temperature: 0.7
|
|
timeout: 30
|
|
api:
|
|
api_base: null
|
|
openai:
|
|
api_base: https://api.openai.com/v1
|
|
"""
|
|
config_path = config_dir / "llm_config.yaml"
|
|
config_path.write_text(yaml_content)
|
|
|
|
# Set up environment for config loader
|
|
monkeypatch.setenv("PYTHONPATH", str(temp_dir))
|
|
monkeypatch.chdir(temp_dir)
|
|
|
|
return temp_dir
|
|
|
|
class TestSecureConfig:
|
|
def test_key_generation(self, secure_config, temp_dir):
|
|
"""Test that encryption key is generated correctly."""
|
|
key_path = temp_dir / "test_secure.key"
|
|
assert key_path.exists()
|
|
if os.name == 'nt': # Windows
|
|
import win32security
|
|
security = win32security.GetFileSecurity(
|
|
str(key_path),
|
|
win32security.DACL_SECURITY_INFORMATION
|
|
)
|
|
dacl = security.GetSecurityDescriptorDacl()
|
|
assert dacl is not None
|
|
# Verify only one ACE exists
|
|
assert dacl.GetAceCount() == 1
|
|
else: # Unix
|
|
assert key_path.stat().st_mode & 0o777 == 0o600 # Check permissions
|
|
|
|
def test_encryption_decryption(self, secure_config):
|
|
"""Test encryption and decryption of values."""
|
|
test_value = "test-api-key-123"
|
|
encrypted = secure_config.encrypt_value(test_value)
|
|
decrypted = secure_config.decrypt_value(encrypted)
|
|
assert decrypted == test_value
|
|
|
|
def test_null_handling(self, secure_config):
|
|
"""Test handling of null/None values."""
|
|
assert secure_config.encrypt_value(None) is None
|
|
assert secure_config.decrypt_value(None) is None
|
|
|
|
def test_invalid_decrypt(self, secure_config):
|
|
"""Test decryption of invalid data."""
|
|
assert secure_config.decrypt_value("invalid-data") is None
|
|
|
|
class TestConfigLoader:
|
|
def test_save_load_api_key(self, test_config_dir, monkeypatch):
|
|
"""Test saving and loading API key."""
|
|
test_api_key = "test-api-key-456"
|
|
save_api_key(test_api_key)
|
|
|
|
# Verify secure.json was created with proper permissions
|
|
secure_json = test_config_dir / "config" / "secure.json"
|
|
assert secure_json.exists()
|
|
|
|
if os.name == 'nt': # Windows
|
|
import win32security
|
|
security = win32security.GetFileSecurity(
|
|
str(secure_json),
|
|
win32security.DACL_SECURITY_INFORMATION
|
|
)
|
|
dacl = security.GetSecurityDescriptorDacl()
|
|
assert dacl is not None
|
|
# Verify only one ACE exists
|
|
assert dacl.GetAceCount() == 1
|
|
else: # Unix
|
|
assert secure_json.stat().st_mode & 0o777 == 0o600
|
|
|
|
# Load config and verify API key
|
|
config = load_config()
|
|
assert config["llm"]["api_key"] == test_api_key
|
|
|
|
def test_config_priority(self, test_config_dir, monkeypatch):
|
|
"""Test configuration priority (env vars > secure storage > yaml)."""
|
|
# Set up different values for each level
|
|
env_api_key = "env-api-key"
|
|
secure_api_key = "secure-api-key"
|
|
|
|
# Save to secure storage
|
|
save_api_key(secure_api_key)
|
|
|
|
# Test without env var
|
|
config = load_config()
|
|
assert config["llm"]["api_key"] == secure_api_key
|
|
|
|
# Test with env var
|
|
monkeypatch.setenv("LLM_API_KEY", env_api_key)
|
|
config = load_config()
|
|
assert config["llm"]["api_key"] == env_api_key
|
|
|
|
def test_api_base_config(self, test_config_dir, monkeypatch):
|
|
"""Test API base URL configuration."""
|
|
# Test default OpenAI base URL
|
|
config = load_config()
|
|
assert config["llm"]["api_base"] == "https://api.openai.com/v1"
|
|
|
|
# Test override with env var
|
|
custom_base = "https://custom-api.example.com"
|
|
monkeypatch.setenv("LLM_API_BASE", custom_base)
|
|
config = load_config()
|
|
assert config["llm"]["api_base"] == custom_base
|