EU-Utility/tests/test_comprehensive.py

294 lines
8.7 KiB
Python

"""
Comprehensive test suite for EU-Utility
Run with: pytest tests/ -v
"""
import pytest
import sys
import os
# Add project to path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
class TestCoreServices:
"""Test suite for core services."""
def test_event_bus_singleton(self):
"""Test EventBus is singleton."""
from core.event_bus import get_event_bus
bus1 = get_event_bus()
bus2 = get_event_bus()
assert bus1 is bus2
def test_event_publish_subscribe(self):
"""Test event publishing and subscribing."""
from core.event_bus import get_event_bus, SkillGainEvent
bus = get_event_bus()
received = []
def handler(event):
received.append(event)
sub_id = bus.subscribe_typed(SkillGainEvent, handler)
event = SkillGainEvent(skill_name="Rifle", skill_value=25.0, gain_amount=0.01)
bus.publish(event)
# Give async time to process
import time
time.sleep(0.1)
assert len(received) == 1
assert received[0].skill_name == "Rifle"
bus.unsubscribe(sub_id)
def test_nexus_api_singleton(self):
"""Test NexusAPI is singleton."""
from core.nexus_api import get_nexus_api
api1 = get_nexus_api()
api2 = get_nexus_api()
assert api1 is api2
def test_data_store_operations(self):
"""Test DataStore operations."""
from core.data_store import get_data_store
store = get_data_store()
# Test save and load
store.save("test_plugin", "test_key", {"value": 42})
data = store.load("test_plugin", "test_key", None)
assert data == {"value": 42}
# Test delete
store.delete("test_plugin", "test_key")
data = store.load("test_plugin", "test_key", None)
assert data is None
class TestPluginAPI:
"""Test suite for PluginAPI."""
def test_plugin_api_singleton(self):
"""Test PluginAPI is singleton."""
from core.plugin_api import get_api
api1 = get_api()
api2 = get_api()
assert api1 is api2
def test_api_registration(self):
"""Test API endpoint registration."""
from core.plugin_api import get_api, APIEndpoint, APIType
api = get_api()
def test_handler():
return "test"
endpoint = APIEndpoint(
name="test_api",
api_type=APIType.CUSTOM,
description="Test API",
handler=test_handler,
plugin_id="test_plugin",
version="1.0.0"
)
result = api.register_api(endpoint)
assert result is True
# Cleanup
api.unregister_api("test_plugin", "test_api")
class TestSecurity:
"""Test suite for security features."""
def test_path_traversal_protection(self):
"""Test path traversal is blocked."""
from core.security_utils import validate_path
# Valid path
assert validate_path("/safe/path/file.txt", "/safe/path") is True
# Path traversal attempt
assert validate_path("/safe/path/../../../etc/passwd", "/safe/path") is False
# Null byte injection
assert validate_path("/safe/path/file.txt\x00.jpg", "/safe/path") is False
def test_input_sanitization(self):
"""Test input sanitization."""
from core.security_utils import sanitize_input
# Script tag removal
assert "<script>" not in sanitize_input("<script>alert('xss')</script>")
# SQL injection prevention
assert "'" not in sanitize_input("'; DROP TABLE users; --")
class TestThemeManager:
"""Test suite for theme system."""
def test_theme_manager_singleton(self):
"""Test ThemeManager is singleton."""
from core.theme_manager import theme_manager
from core.theme_manager import ThemeManager
tm1 = ThemeManager()
tm2 = ThemeManager()
assert tm1 is tm2
def test_theme_getters(self):
"""Test theme retrieval."""
from core.theme_manager import theme_manager
dark_theme = theme_manager.get_theme('dark')
assert 'bg_primary' in dark_theme
assert 'accent' in dark_theme
light_theme = theme_manager.get_theme('light')
assert light_theme['bg_primary'] != dark_theme['bg_primary']
def test_stylesheet_generation(self):
"""Test QSS stylesheet generation."""
from core.theme_manager import theme_manager
stylesheet = theme_manager.get_stylesheet('dark')
assert 'background-color' in stylesheet
assert 'color' in stylesheet
class TestUtilities:
"""Test suite for utility functions."""
def test_ped_formatting(self):
"""Test PED formatting."""
from plugins.base_plugin import BasePlugin
class TestPlugin(BasePlugin):
name = "Test"
version = "1.0.0"
author = "Test"
description = "Test"
plugin = TestPlugin(None, {})
assert "PED" in plugin.format_ped(123.45)
assert "PEC" in plugin.format_pec(50)
def test_dpp_calculation(self):
"""Test DPP calculation."""
from plugins.base_plugin import BasePlugin
class TestPlugin(BasePlugin):
name = "Test"
version = "1.0.0"
author = "Test"
description = "Test"
plugin = TestPlugin(None, {})
# DPP = damage / ((ammo * 0.01 + decay) / 100)
dpp = plugin.calculate_dpp(50, 100, 2.5)
assert dpp > 0
def test_markup_calculation(self):
"""Test markup calculation."""
from plugins.base_plugin import BasePlugin
class TestPlugin(BasePlugin):
name = "Test"
version = "1.0.0"
author = "Test"
description = "Test"
plugin = TestPlugin(None, {})
markup = plugin.calculate_markup(150, 100)
assert markup == 150.0 # 150% markup
class TestPluginLoading:
"""Test suite for plugin loading."""
def test_plugin_discovery(self):
"""Test plugin discovery."""
import os
plugins_dir = os.path.join(os.path.dirname(__file__), '..', 'plugins')
if os.path.exists(plugins_dir):
plugin_dirs = [d for d in os.listdir(plugins_dir)
if os.path.isdir(os.path.join(plugins_dir, d))
and not d.startswith('_')]
# Should have multiple plugins
assert len(plugin_dirs) > 5
def test_plugin_structure(self):
"""Test plugin directory structure."""
import os
plugins_dir = os.path.join(os.path.dirname(__file__), '..', 'plugins')
if os.path.exists(plugins_dir):
for plugin_name in os.listdir(plugins_dir):
plugin_path = os.path.join(plugins_dir, plugin_name)
if os.path.isdir(plugin_path) and not plugin_name.startswith('_'):
# Check for required files
init_file = os.path.join(plugin_path, '__init__.py')
plugin_file = os.path.join(plugin_path, 'plugin.py')
if os.path.exists(plugin_file):
assert os.path.exists(init_file) or os.path.exists(plugin_file)
# Integration tests
@pytest.mark.integration
def test_full_plugin_lifecycle():
"""Integration test: full plugin lifecycle."""
from plugins.base_plugin import BasePlugin
lifecycle_events = []
class LifecyclePlugin(BasePlugin):
name = "LifecycleTest"
version = "1.0.0"
author = "Test"
description = "Test lifecycle"
def initialize(self):
lifecycle_events.append('initialize')
def get_ui(self):
lifecycle_events.append('get_ui')
return None
def on_show(self):
lifecycle_events.append('on_show')
def on_hide(self):
lifecycle_events.append('on_hide')
def shutdown(self):
lifecycle_events.append('shutdown')
# Test lifecycle
plugin = LifecyclePlugin(None, {})
plugin.initialize()
plugin.get_ui()
plugin.on_show()
plugin.on_hide()
plugin.shutdown()
assert 'initialize' in lifecycle_events
assert 'shutdown' in lifecycle_events
if __name__ == '__main__':
pytest.main([__file__, '-v'])