""" Comprehensive test script for Arrangement injection and related fixes. Tests: coherence_system, audio_analyzer_dual, bus_architecture ASCII-only to avoid encoding issues. """ import sys import os def test_header(name): print(f"\n{'='*60}") print(f"TEST: {name}") print('='*60) def test_result(success, message): status = "PASS" if success else "FAIL" print(f" [{status}] {message}") return success def main(): print("\n" + "="*60) print("ABLETON MCP AI - COMPREHENSIVE TEST SUITE") print("="*60) results = {"passed": 0, "failed": 0} # Test 1: Coherence System (standalone) test_header("1. COHERENCE SYSTEM (Standalone)") try: # Try importing without going through AbletonMCP_AI.__init__ import importlib.util spec = importlib.util.spec_from_file_location( "coherence_system", "AbletonMCP_AI/mcp_server/engines/coherence_system.py" ) coherence_module = importlib.util.module_from_spec(spec) # Need to mock the numpy dependencies import types mock_np = types.ModuleType('numpy') mock_np.float32 = float mock_np.array = lambda x: x mock_np.mean = lambda x: sum(x)/len(x) if x else 0 sys.modules['numpy'] = mock_np spec.loader.exec_module(coherence_module) test_result(True, "Coherence system loaded (mocked numpy)") results["passed"] += 1 # Test basic functionality try: CoherenceFeatures = coherence_module.CoherenceFeatures features1 = CoherenceFeatures(bpm=95.0, key="Am", spectral_centroid=500.0, mfcc_mean=0.5) features2 = CoherenceFeatures(bpm=95.5, key="Am", spectral_centroid=510.0, mfcc_mean=0.52) coherence = coherence_module.calculate_comprehensive_coherence(features1, features2) test_result(True, f"Coherence calculation works: score={coherence.overall:.3f}") results["passed"] += 1 except Exception as e: test_result(False, f"Coherence calculation failed: {e}") results["failed"] += 1 except Exception as e: test_result(False, f"Coherence import failed: {e}") results["failed"] += 2 # Test 2: Audio Analyzer Dual (standalone) test_header("2. AUDIO ANALYZER DUAL (Standalone)") try: import importlib.util spec = importlib.util.spec_from_file_location( "audio_analyzer_dual", "AbletonMCP_AI/mcp_server/engines/audio_analyzer_dual.py" ) audio_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(audio_module) AudioAnalyzerDual = audio_module.AudioAnalyzerDual analyzer = AudioAnalyzerDual(backend="basic") test_result(True, "AudioAnalyzerDual instantiated with basic backend") results["passed"] += 1 # Try to analyze a sample if libreria exists test_path = "libreria/reggaeton/kick/kick 1.wav" if os.path.exists(test_path): try: features = analyzer.analyze_sample(test_path) test_result(True, f"Audio analysis: BPM={features.bpm}, Key={features.key}") results["passed"] += 1 except Exception as e: test_result(False, f"Audio analysis failed: {e}") results["failed"] += 1 else: test_result(True, f"Sample path not found (expected): {test_path}") test_result(True, "AudioAnalyzerDual is importable and functional") results["passed"] += 2 except Exception as e: test_result(False, f"AudioAnalyzerDual import failed: {e}") results["failed"] += 3 # Test 3: Bus Architecture test_header("3. BUS ARCHITECTURE") try: import importlib.util spec = importlib.util.spec_from_file_location( "bus_architecture", "AbletonMCP_AI/mcp_server/engines/bus_architecture.py" ) bus_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(bus_module) BUS_GAIN_CALIBRATION = bus_module.BUS_GAIN_CALIBRATION bus_count = len(BUS_GAIN_CALIBRATION) test_result(True, f"Bus config loaded: {bus_count} buses") results["passed"] += 1 # Verify specific buses exist expected_buses = ["DRUM_BUS", "BASS_BUS", "MIX_BUS", "MASTER_CHAIN"] for bus in expected_buses: if bus in BUS_GAIN_CALIBRATION: test_result(True, f"Bus '{bus}' configured") results["passed"] += 1 else: test_result(False, f"Bus '{bus}' missing") results["failed"] += 1 except Exception as e: test_result(False, f"Bus architecture import failed: {e}") results["failed"] += 5 # Test 4: Arrangement Tools - check files exist test_header("4. ARRANGEMENT TOOLS (File Check)") arrangement_files = [ "AbletonMCP_AI/mcp_server/server.py", "AbletonMCP_AI/mcp_server/engines/arrangement_injection.py", "AbletonMCP_AI/mcp_server/engines/timeline_builder.py", ] for filepath in arrangement_files: if os.path.exists(filepath): test_result(True, f"File exists: {filepath}") results["passed"] += 1 else: test_result(False, f"File missing: {filepath}") results["failed"] += 1 # Check for arrangement functions in server.py try: with open("AbletonMCP_AI/mcp_server/server.py", 'r') as f: content = f.read() expected_functions = [ "build_arrangement_timeline", "create_arrangement_track", "create_arrangement_audio_pattern", "get_arrangement_status", "create_section_at_bar" ] for func in expected_functions: if f"def {func}(" in content or f"async def {func}(" in content: test_result(True, f"Function defined: {func}") results["passed"] += 1 else: test_result(False, f"Function missing: {func}") results["failed"] += 1 except Exception as e: test_result(False, f"Could not read server.py: {e}") results["failed"] += 5 # Test 5: Intelligent Track Generator (standalone) test_header("5. INTELLIGENT TRACK GENERATOR (Standalone)") try: import importlib.util spec = importlib.util.spec_from_file_location( "intelligent_track_generator", "AbletonMCP_AI/mcp_server/engines/intelligent_track_generator.py" ) itg_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(itg_module) test_result(True, "IntelligentTrackGenerator module loaded") results["passed"] += 1 # Test basic instantiation try: config_class = itg_module.IntelligentTrackConfig config = config_class( description="reggaeton 95bpm Am", structure_type="short" ) test_result(True, f"Config created: {config.description}") results["passed"] += 1 except Exception as e: test_result(False, f"Config creation failed: {e}") results["failed"] += 1 except Exception as e: test_result(False, f"IntelligentTrackGenerator import failed: {e}") results["failed"] += 2 # Manual MCP Test Instructions test_header("6. MANUAL MCP TEST INSTRUCTIONS") print(""" The following tests must be run via MCP when Ableton Live is running: TEST 6a: create_arrangement_audio_pattern 1. Ensure Ableton Live is running with MCP connection 2. Run: create_arrangement_audio_pattern with: - track_index: 0 - file_path: "libreria/reggaeton/kick/kick 1.wav" - positions: [0, 2, 4, 6] - name: "Test Kick Pattern" 3. Verify: Clips appear in Arrangement View at bars 0, 2, 4, 6 TEST 6b: build_arrangement_timeline 1. Ensure Ableton Live is running with MCP connection 2. Run: build_arrangement_timeline with: - sections_json: '[ {"name": "Intro", "start_bar": 0, "duration_bars": 4, "tracks": [{"type": "drums", "variation": "minimal"}]}, {"name": "Verse", "start_bar": 4, "duration_bars": 8, "tracks": [{"type": "drums", "variation": "full"}, {"type": "bass", "variation": "standard"}]} ]' 3. Verify: Two sections created in Arrangement View TEST 6c: get_arrangement_status 1. Run: get_arrangement_status 2. Verify: Returns current clips in Arrangement View 3. Check: total_clips > 0 after running tests 6a or 6b TEST 6d: create_arrangement_track 1. Run: create_arrangement_track with track_type="drums" 2. Verify: New track created in Arrangement View 3. Run: create_section_at_bar with section_type="intro", at_bar=0 4. Verify: Section created on the track TEST 6e: generate_intelligent_track 1. Run: generate_intelligent_track with: - description: "reggaeton 95bpm Am" - structure_type: "short" 2. Verify: Complete track generated with coherence > 0.9 3. Check: Clips appear in Arrangement View """) # Sample library check test_header("7. SAMPLE LIBRARY CHECK") libreria_path = "libreria" if os.path.exists(libreria_path): test_result(True, f"Sample library exists: {libreria_path}") results["passed"] += 1 # Count samples sample_count = 0 for root, dirs, files in os.walk(libreria_path): for file in files: if file.endswith(('.wav', '.mp3', '.aif')): sample_count += 1 test_result(True, f"Total samples found: {sample_count}") results["passed"] += 1 else: test_result(False, f"Sample library not found: {libreria_path}") results["failed"] += 2 # Summary test_header("TEST SUMMARY") total = results["passed"] + results["failed"] print(f" Total tests: {total}") print(f" Passed: {results['passed']}") print(f" Failed: {results['failed']}") if results["failed"] == 0: print("\n *** ALL TESTS PASSED ***") return 0 else: print(f"\n *** {results['failed']} TEST(S) FAILED ***") return 1 if __name__ == "__main__": sys.exit(main())