251 lines
7.6 KiB
Python
251 lines
7.6 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Script de validacion para el Audio Resampler.
|
|
Verifica que:
|
|
1. Las 4 funciones standalone existan y sean importables
|
|
2. La clase AudioResampler funcione correctamente
|
|
3. El cache LRU opera correctamente
|
|
4. La integracion con build_transition_layers funcione
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
|
|
# Agregar el path del MCP_Server
|
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
mcp_server_dir = os.path.join(script_dir, "AbletonMCP_AI", "MCP_Server")
|
|
sys.path.insert(0, mcp_server_dir)
|
|
|
|
def test_imports():
|
|
"""Test 1: Verificar que todas las funciones se pueden importar"""
|
|
print("=" * 60)
|
|
print("TEST 1: Verificacion de imports")
|
|
print("=" * 60)
|
|
|
|
try:
|
|
from audio_resampler import (
|
|
AudioResampler,
|
|
create_reverse_fx,
|
|
create_riser_fx,
|
|
create_downlifter_fx,
|
|
create_stutter_fx,
|
|
)
|
|
print("[OK] Todos los imports exitosos")
|
|
print(f" - AudioResampler: {AudioResampler}")
|
|
print(f" - create_reverse_fx: {create_reverse_fx}")
|
|
print(f" - create_riser_fx: {create_riser_fx}")
|
|
print(f" - create_downlifter_fx: {create_downlifter_fx}")
|
|
print(f" - create_stutter_fx: {create_stutter_fx}")
|
|
return True
|
|
except Exception as e:
|
|
print(f"[ERROR] Fallo en imports: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
|
|
def test_class_structure():
|
|
"""Test 2: Verificar estructura de la clase AudioResampler"""
|
|
print("\n" + "=" * 60)
|
|
print("TEST 2: Estructura de AudioResampler")
|
|
print("=" * 60)
|
|
|
|
try:
|
|
from audio_resampler import AudioResampler
|
|
|
|
# Verificar metodos privados de FX
|
|
required_methods = [
|
|
'_render_reverse_fx',
|
|
'_render_riser',
|
|
'_render_downlifter',
|
|
'_render_stutter',
|
|
'_load_audio',
|
|
'_write_audio',
|
|
'_output_path',
|
|
'build_transition_layers',
|
|
'cache_stats',
|
|
'clear_cache',
|
|
]
|
|
|
|
resampler = AudioResampler()
|
|
missing = []
|
|
for method in required_methods:
|
|
if not hasattr(resampler, method):
|
|
missing.append(method)
|
|
else:
|
|
print(f"[OK] Metodo encontrado: {method}")
|
|
|
|
if missing:
|
|
print(f"[ERROR] Metodos faltantes: {missing}")
|
|
return False
|
|
|
|
# Verificar constantes de cache
|
|
print(f"[OK] Cache limit: {resampler._CACHE_LIMIT}")
|
|
print(f"[OK] Cache max age: {resampler._CACHE_MAX_AGE_S}s")
|
|
print(f"[OK] Default peak: {resampler._DEFAULT_PEAK}")
|
|
|
|
return True
|
|
except Exception as e:
|
|
print(f"[ERROR] Fallo en estructura: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
|
|
def test_cache_system():
|
|
"""Test 3: Verificar sistema de cache"""
|
|
print("\n" + "=" * 60)
|
|
print("TEST 3: Sistema de Cache LRU")
|
|
print("=" * 60)
|
|
|
|
try:
|
|
from audio_resampler import AudioResampler
|
|
|
|
resampler = AudioResampler()
|
|
|
|
# Verificar cache inicial vacio
|
|
stats = resampler.cache_stats()
|
|
print(f"[OK] Cache stats inicial: entries={stats['entries']}, hits={stats['hits']}")
|
|
|
|
# Verificar que el cache funciona (incluso sin audio)
|
|
assert stats['entries'] == 0, "Cache deberia estar vacio al inicio"
|
|
assert stats['max_entries'] == 50, "Cache limit deberia ser 50"
|
|
assert stats['max_age_s'] == 1800.0, "Cache max age deberia ser 1800s"
|
|
|
|
print("[OK] Sistema de cache operando correctamente")
|
|
return True
|
|
except Exception as e:
|
|
print(f"[ERROR] Fallo en cache: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
|
|
def test_transition_layers_structure():
|
|
"""Test 4: Verificar estructura de build_transition_layers"""
|
|
print("\n" + "=" * 60)
|
|
print("TEST 4: Estructura de build_transition_layers")
|
|
print("=" * 60)
|
|
|
|
try:
|
|
from audio_resampler import AudioResampler
|
|
|
|
resampler = AudioResampler()
|
|
|
|
# Probar con un plan vacio
|
|
empty_plan = {"matches": {}}
|
|
sections = [
|
|
{"kind": "intro", "name": "Intro", "beats": 16},
|
|
{"kind": "build", "name": "Build Up", "beats": 16},
|
|
{"kind": "drop", "name": "Drop A", "beats": 32},
|
|
]
|
|
|
|
layers = resampler.build_transition_layers(empty_plan, sections, 128.0)
|
|
|
|
# Verificar que retorna una lista
|
|
assert isinstance(layers, list), "Debe retornar una lista"
|
|
print(f"[OK] build_transition_layers retorna lista: {len(layers)} capas")
|
|
|
|
# Verificar estructura de capas (si hay alguna)
|
|
for i, layer in enumerate(layers):
|
|
required_keys = ['name', 'file_path', 'positions', 'color', 'volume', 'source', 'generated']
|
|
missing = [k for k in required_keys if k not in layer]
|
|
if missing:
|
|
print(f"[WARN] Capa {i} falta keys: {missing}")
|
|
else:
|
|
print(f"[OK] Capa {i} '{layer['name']}' estructura correcta")
|
|
|
|
print("[OK] build_transition_layers estructura correcta")
|
|
return True
|
|
except Exception as e:
|
|
print(f"[ERROR] Fallo en transition_layers: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
|
|
def test_function_signatures():
|
|
"""Test 5: Verificar firmas de funciones standalone"""
|
|
print("\n" + "=" * 60)
|
|
print("TEST 5: Firmas de funciones standalone")
|
|
print("=" * 60)
|
|
|
|
try:
|
|
from audio_resampler import (
|
|
create_reverse_fx,
|
|
create_riser_fx,
|
|
create_downlifter_fx,
|
|
create_stutter_fx,
|
|
)
|
|
import inspect
|
|
|
|
functions = [
|
|
('create_reverse_fx', create_reverse_fx),
|
|
('create_riser_fx', create_riser_fx),
|
|
('create_downlifter_fx', create_downlifter_fx),
|
|
('create_stutter_fx', create_stutter_fx),
|
|
]
|
|
|
|
for name, func in functions:
|
|
sig = inspect.signature(func)
|
|
params = list(sig.parameters.keys())
|
|
|
|
# Verificar parametros minimos
|
|
assert 'source_path' in params, f"{name} debe tener source_path"
|
|
assert 'output_path' in params, f"{name} debe tener output_path"
|
|
|
|
print(f"[OK] {name} firma: {sig}")
|
|
|
|
print("[OK] Todas las funciones tienen firmas correctas")
|
|
return True
|
|
except Exception as e:
|
|
print(f"[ERROR] Fallo en firmas: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
|
|
def main():
|
|
"""Ejecutar todos los tests"""
|
|
print("\n" + "=" * 60)
|
|
print("VALIDACION DE AUDIO RESAMPLER")
|
|
print("=" * 60)
|
|
|
|
results = [
|
|
("Imports", test_imports),
|
|
("Estructura de clase", test_class_structure),
|
|
("Sistema de cache", test_cache_system),
|
|
("Transition layers", test_transition_layers_structure),
|
|
("Firmas de funciones", test_function_signatures),
|
|
]
|
|
|
|
passed = 0
|
|
failed = 0
|
|
|
|
for name, test_func in results:
|
|
try:
|
|
if test_func():
|
|
passed += 1
|
|
else:
|
|
failed += 1
|
|
except Exception as e:
|
|
print(f"\n[ERROR CRITICO] {name}: {e}")
|
|
failed += 1
|
|
|
|
print("\n" + "=" * 60)
|
|
print("RESUMEN DE VALIDACION")
|
|
print("=" * 60)
|
|
print(f"Tests pasados: {passed}/{len(results)}")
|
|
print(f"Tests fallidos: {failed}/{len(results)}")
|
|
|
|
if failed == 0:
|
|
print("\n[OK] Audio Resampler validado exitosamente!")
|
|
return 0
|
|
else:
|
|
print("\n[ERROR] Algunos tests fallaron")
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|