#!/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)