273 lines
11 KiB
Python
273 lines
11 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Test Architecture Compliance After Cleanup
|
|
|
|
This test verifies that the system now follows the correct architecture:
|
|
1. Single, centralized data flow through orchestrator
|
|
2. Dashboard gets data through orchestrator, not direct stream management
|
|
3. UniversalDataAdapter is the only data stream implementation
|
|
4. No conflicting UnifiedDataStream implementations
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
import logging
|
|
from datetime import datetime
|
|
from typing import Dict, Any
|
|
|
|
# Add project root to path
|
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
# Configure logging
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
|
)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
def test_architecture_imports():
|
|
"""Test that correct architecture components can be imported"""
|
|
logger.info("=== Testing Architecture Imports ===")
|
|
|
|
try:
|
|
# Test core architecture components
|
|
from core.orchestrator import TradingOrchestrator
|
|
from core.universal_data_adapter import UniversalDataAdapter, UniversalDataStream
|
|
from core.data_provider import DataProvider
|
|
logger.info("✓ Core architecture components imported successfully")
|
|
|
|
# Test dashboard imports
|
|
from web.clean_dashboard import create_clean_dashboard
|
|
logger.info("✓ Dashboard components imported successfully")
|
|
|
|
# Verify UnifiedDataStream is NOT available (should be removed)
|
|
try:
|
|
import importlib.util
|
|
spec = importlib.util.find_spec("core.unified_data_stream")
|
|
if spec is not None:
|
|
logger.error("✗ Old unified_data_stream module still exists - should have been removed")
|
|
return False
|
|
else:
|
|
logger.info("✓ Old unified_data_stream module correctly removed")
|
|
except Exception as e:
|
|
logger.info("✓ Old unified_data_stream module correctly removed")
|
|
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"✗ Import test failed: {e}")
|
|
return False
|
|
|
|
def test_orchestrator_data_integration():
|
|
"""Test that orchestrator properly integrates with UniversalDataAdapter"""
|
|
logger.info("=== Testing Orchestrator Data Integration ===")
|
|
|
|
try:
|
|
from core.orchestrator import TradingOrchestrator
|
|
from core.universal_data_adapter import UniversalDataAdapter
|
|
from core.data_provider import DataProvider
|
|
|
|
# Create data provider
|
|
data_provider = DataProvider()
|
|
|
|
# Create orchestrator
|
|
orchestrator = TradingOrchestrator(data_provider=data_provider)
|
|
|
|
# Verify orchestrator has universal_adapter
|
|
if not hasattr(orchestrator, 'universal_adapter'):
|
|
logger.error("✗ Orchestrator missing universal_adapter attribute")
|
|
return False
|
|
|
|
if not isinstance(orchestrator.universal_adapter, UniversalDataAdapter):
|
|
logger.error("✗ Orchestrator universal_adapter is not UniversalDataAdapter instance")
|
|
return False
|
|
|
|
logger.info("✓ Orchestrator properly integrated with UniversalDataAdapter")
|
|
|
|
# Test orchestrator data access methods
|
|
if not hasattr(orchestrator, 'get_universal_data_stream'):
|
|
logger.error("✗ Orchestrator missing get_universal_data_stream method")
|
|
return False
|
|
|
|
if not hasattr(orchestrator, 'get_universal_data_for_model'):
|
|
logger.error("✗ Orchestrator missing get_universal_data_for_model method")
|
|
return False
|
|
|
|
logger.info("✓ Orchestrator has required data access methods")
|
|
|
|
# Test data stream access
|
|
try:
|
|
data_stream = orchestrator.get_universal_data_stream()
|
|
logger.info("✓ Orchestrator data stream access working")
|
|
except Exception as e:
|
|
logger.warning(f"⚠ Orchestrator data stream access warning: {e}")
|
|
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"✗ Orchestrator integration test failed: {e}")
|
|
return False
|
|
|
|
def test_dashboard_architecture_compliance():
|
|
"""Test that dashboard follows correct architecture pattern"""
|
|
logger.info("=== Testing Dashboard Architecture Compliance ===")
|
|
|
|
try:
|
|
# Import dashboard components
|
|
from web.clean_dashboard import create_clean_dashboard
|
|
|
|
# Read dashboard source to verify architecture compliance
|
|
dashboard_path = os.path.join(os.path.dirname(__file__), 'web', 'clean_dashboard.py')
|
|
with open(dashboard_path, 'r') as f:
|
|
dashboard_source = f.read()
|
|
|
|
# Verify dashboard uses UniversalDataAdapter, not UnifiedDataStream
|
|
if 'UniversalDataAdapter' not in dashboard_source:
|
|
logger.error("✗ Dashboard not using UniversalDataAdapter")
|
|
return False
|
|
|
|
if 'UnifiedDataStream' in dashboard_source and 'UniversalDataAdapter' not in dashboard_source:
|
|
logger.error("✗ Dashboard still using old UnifiedDataStream")
|
|
return False
|
|
|
|
logger.info("✓ Dashboard using correct UniversalDataAdapter")
|
|
|
|
# Verify dashboard gets data through orchestrator
|
|
if '_get_universal_data_from_orchestrator' not in dashboard_source:
|
|
logger.error("✗ Dashboard not getting data through orchestrator")
|
|
return False
|
|
|
|
logger.info("✓ Dashboard getting data through orchestrator")
|
|
|
|
# Verify dashboard doesn't manage streams directly
|
|
problematic_patterns = [
|
|
'register_consumer',
|
|
'subscribe_to_stream',
|
|
'stream_consumer',
|
|
'add_consumer'
|
|
]
|
|
|
|
for pattern in problematic_patterns:
|
|
if pattern in dashboard_source:
|
|
logger.warning(f"⚠ Dashboard may still have direct stream management: {pattern}")
|
|
|
|
logger.info("✓ Dashboard architecture compliance verified")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"✗ Dashboard architecture test failed: {e}")
|
|
return False
|
|
|
|
def test_data_flow_architecture():
|
|
"""Test the complete data flow architecture"""
|
|
logger.info("=== Testing Complete Data Flow Architecture ===")
|
|
|
|
try:
|
|
from core.data_provider import DataProvider
|
|
from core.universal_data_adapter import UniversalDataAdapter, UniversalDataStream
|
|
from core.orchestrator import TradingOrchestrator
|
|
|
|
# Create the data flow chain
|
|
data_provider = DataProvider()
|
|
universal_adapter = UniversalDataAdapter(data_provider)
|
|
orchestrator = TradingOrchestrator(data_provider=data_provider)
|
|
|
|
# Verify data flow: DataProvider -> UniversalDataAdapter -> Orchestrator
|
|
logger.info("✓ Data flow components created successfully")
|
|
|
|
# Test UniversalDataStream structure
|
|
try:
|
|
# Get sample data stream
|
|
sample_stream = universal_adapter.get_universal_data_stream()
|
|
|
|
# Verify it's a UniversalDataStream dataclass
|
|
if hasattr(sample_stream, 'eth_ticks'):
|
|
logger.info("✓ UniversalDataStream has eth_ticks")
|
|
if hasattr(sample_stream, 'eth_1m'):
|
|
logger.info("✓ UniversalDataStream has eth_1m")
|
|
if hasattr(sample_stream, 'eth_1h'):
|
|
logger.info("✓ UniversalDataStream has eth_1h")
|
|
if hasattr(sample_stream, 'eth_1d'):
|
|
logger.info("✓ UniversalDataStream has eth_1d")
|
|
if hasattr(sample_stream, 'btc_ticks'):
|
|
logger.info("✓ UniversalDataStream has btc_ticks")
|
|
|
|
logger.info("✓ UniversalDataStream structure verified")
|
|
|
|
except Exception as e:
|
|
logger.warning(f"⚠ UniversalDataStream structure test warning: {e}")
|
|
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"✗ Data flow architecture test failed: {e}")
|
|
return False
|
|
|
|
def test_removed_files():
|
|
"""Test that conflicting files were properly removed"""
|
|
logger.info("=== Testing Removed Files ===")
|
|
|
|
# Check that unified_data_stream.py was removed
|
|
unified_stream_path = os.path.join(os.path.dirname(__file__), 'core', 'unified_data_stream.py')
|
|
if os.path.exists(unified_stream_path):
|
|
logger.error("✗ core/unified_data_stream.py still exists - should be removed")
|
|
return False
|
|
|
|
logger.info("✓ Conflicting unified_data_stream.py properly removed")
|
|
|
|
# Check that universal_data_adapter.py still exists
|
|
universal_adapter_path = os.path.join(os.path.dirname(__file__), 'core', 'universal_data_adapter.py')
|
|
if not os.path.exists(universal_adapter_path):
|
|
logger.error("✗ core/universal_data_adapter.py missing - should exist")
|
|
return False
|
|
|
|
logger.info("✓ Correct universal_data_adapter.py exists")
|
|
|
|
return True
|
|
|
|
def run_all_tests():
|
|
"""Run all architecture compliance tests"""
|
|
logger.info("=" * 60)
|
|
logger.info("ARCHITECTURE COMPLIANCE TEST SUITE")
|
|
logger.info("Testing data flow cleanup and architecture compliance")
|
|
logger.info("=" * 60)
|
|
|
|
tests = [
|
|
("Import Architecture", test_architecture_imports),
|
|
("Orchestrator Integration", test_orchestrator_data_integration),
|
|
("Dashboard Compliance", test_dashboard_architecture_compliance),
|
|
("Data Flow Architecture", test_data_flow_architecture),
|
|
("Removed Files", test_removed_files)
|
|
]
|
|
|
|
passed = 0
|
|
total = len(tests)
|
|
|
|
for test_name, test_func in tests:
|
|
logger.info(f"\n--- {test_name} ---")
|
|
try:
|
|
if test_func():
|
|
logger.info(f"✓ {test_name} PASSED")
|
|
passed += 1
|
|
else:
|
|
logger.error(f"✗ {test_name} FAILED")
|
|
except Exception as e:
|
|
logger.error(f"✗ {test_name} ERROR: {e}")
|
|
|
|
logger.info("\n" + "=" * 60)
|
|
logger.info(f"ARCHITECTURE COMPLIANCE TEST RESULTS: {passed}/{total} tests passed")
|
|
|
|
if passed == total:
|
|
logger.info("🎉 ALL TESTS PASSED - Architecture cleanup successful!")
|
|
logger.info("✓ Single, centralized data flow through orchestrator")
|
|
logger.info("✓ Dashboard gets data through orchestrator methods")
|
|
logger.info("✓ UniversalDataAdapter is the only data stream implementation")
|
|
logger.info("✓ No conflicting UnifiedDataStream implementations")
|
|
return True
|
|
else:
|
|
logger.error(f"❌ {total - passed} tests failed - Architecture issues remain")
|
|
return False
|
|
|
|
if __name__ == "__main__":
|
|
success = run_all_tests()
|
|
sys.exit(0 if success else 1) |