431 lines
14 KiB
Python
431 lines
14 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
TSNet Phase 2 - Test Suite Completo
|
|
Tests exhaustivos para validar la funcionalidad de simulación TSNet
|
|
"""
|
|
|
|
import requests
|
|
import json
|
|
import time
|
|
import sys
|
|
from datetime import datetime
|
|
|
|
|
|
class TSNetTestSuite:
|
|
def __init__(self, base_url="http://localhost:5006"):
|
|
self.base_url = base_url
|
|
self.test_results = []
|
|
self.created_objects = []
|
|
|
|
def log_test(self, test_name, passed, details=""):
|
|
"""Registrar resultado de test"""
|
|
self.test_results.append(
|
|
{
|
|
"test": test_name,
|
|
"passed": passed,
|
|
"details": details,
|
|
"timestamp": datetime.now().isoformat(),
|
|
}
|
|
)
|
|
status = "✅ PASS" if passed else "❌ FAIL"
|
|
print(f"{status}: {test_name}")
|
|
if details:
|
|
print(f" Details: {details}")
|
|
|
|
def send_mcp_request(self, method, params=None, timeout=10):
|
|
"""Enviar request MCP con manejo de errores"""
|
|
try:
|
|
payload = {
|
|
"jsonrpc": "2.0",
|
|
"method": method,
|
|
"id": int(time.time() * 1000),
|
|
}
|
|
if params:
|
|
payload["params"] = params
|
|
|
|
response = requests.post(self.base_url, json=payload, timeout=timeout)
|
|
|
|
if response.status_code == 200:
|
|
result = response.json()
|
|
if "error" in result:
|
|
return False, f"MCP Error: {result['error']}"
|
|
return True, result.get("result", {})
|
|
else:
|
|
return False, f"HTTP {response.status_code}: {response.text[:200]}"
|
|
|
|
except Exception as e:
|
|
return False, f"Exception: {str(e)}"
|
|
|
|
def test_01_mcp_connectivity(self):
|
|
"""Test 1: Conectividad básica MCP"""
|
|
success, result = self.send_mcp_request("get_ctreditor_status")
|
|
if success:
|
|
status = result.get("connection_status", "unknown")
|
|
self.log_test(
|
|
"MCP Connectivity", status == "available", f"Status: {status}"
|
|
)
|
|
else:
|
|
self.log_test("MCP Connectivity", False, result)
|
|
return success
|
|
|
|
def test_02_clear_workspace(self):
|
|
"""Test 2: Limpiar workspace"""
|
|
success, result = self.send_mcp_request("list_objects")
|
|
if success:
|
|
objects = result.get("objects", [])
|
|
if objects:
|
|
# Eliminar objetos existentes
|
|
object_ids = [str(obj["id"]["Value"]) for obj in objects]
|
|
del_success, del_result = self.send_mcp_request(
|
|
"delete_objects", {"ids": object_ids}
|
|
)
|
|
self.log_test(
|
|
"Clear Workspace", del_success, f"Deleted {len(object_ids)} objects"
|
|
)
|
|
else:
|
|
self.log_test("Clear Workspace", True, "Workspace already empty")
|
|
else:
|
|
self.log_test("Clear Workspace", False, result)
|
|
return success
|
|
|
|
def test_03_create_hydraulic_system(self):
|
|
"""Test 3: Crear sistema hidráulico completo"""
|
|
components = [
|
|
{"type": "osHydTank", "x": 1.0, "y": 1.0, "name": "Source Tank"},
|
|
{"type": "osHydPump", "x": 3.0, "y": 1.0, "name": "Main Pump"},
|
|
{"type": "osHydPipe", "x": 5.0, "y": 1.0, "name": "Pipe 1"},
|
|
{"type": "osHydTank", "x": 7.0, "y": 1.0, "name": "Target Tank"},
|
|
]
|
|
|
|
created_count = 0
|
|
for comp in components:
|
|
success, result = self.send_mcp_request(
|
|
"create_object", {"type": comp["type"], "x": comp["x"], "y": comp["y"]}
|
|
)
|
|
|
|
if success:
|
|
created_count += 1
|
|
self.created_objects.append(comp["name"])
|
|
|
|
total_components = len(components)
|
|
all_created = created_count == total_components
|
|
self.log_test(
|
|
"Create Hydraulic System",
|
|
all_created,
|
|
f"Created {created_count}/{total_components} components",
|
|
)
|
|
return all_created
|
|
|
|
def test_04_list_created_objects(self):
|
|
"""Test 4: Verificar objetos creados"""
|
|
success, result = self.send_mcp_request("list_objects")
|
|
if success:
|
|
objects = result.get("objects", [])
|
|
hydraulic_objects = [
|
|
obj for obj in objects if "osHyd" in obj.get("type", "")
|
|
]
|
|
|
|
self.log_test(
|
|
"List Created Objects",
|
|
len(hydraulic_objects) > 0,
|
|
f"Found {len(hydraulic_objects)} hydraulic objects",
|
|
)
|
|
|
|
# Mostrar detalles de objetos hidráulicos
|
|
for obj in hydraulic_objects:
|
|
obj_type = obj.get("type", "Unknown")
|
|
obj_id = obj.get("id", {}).get("Value", "No ID")
|
|
print(f" - {obj_type} (ID: {obj_id})")
|
|
|
|
return len(hydraulic_objects) > 0
|
|
else:
|
|
self.log_test("List Created Objects", False, result)
|
|
return False
|
|
|
|
def test_05_tsnet_basic_integration(self):
|
|
"""Test 5: Integración básica TSNet"""
|
|
code = """
|
|
try:
|
|
print("Testing TSNet basic integration...")
|
|
app.TestTSNetIntegrationSync()
|
|
result = "SUCCESS: Basic TSNet integration test completed"
|
|
except Exception as e:
|
|
result = f"ERROR: {str(e)}"
|
|
import traceback
|
|
result += "\\n" + traceback.format_exc()
|
|
print(result)
|
|
"""
|
|
|
|
success, result = self.send_mcp_request(
|
|
"execute_python", {"code": code}, timeout=30
|
|
)
|
|
test_passed = success and "SUCCESS" in str(result)
|
|
self.log_test("TSNet Basic Integration", test_passed, str(result)[:200])
|
|
return test_passed
|
|
|
|
def test_06_tsnet_full_simulation(self):
|
|
"""Test 6: Simulación completa TSNet"""
|
|
code = """
|
|
try:
|
|
print("Testing TSNet full simulation...")
|
|
|
|
# Verificar objetos hidráulicos disponibles
|
|
hydraulic_objects = []
|
|
for obj in app.ObjetosSimulables:
|
|
if obj.GetType().Name.startswith("osHyd"):
|
|
hydraulic_objects.append({
|
|
'name': obj.Nombre,
|
|
'type': obj.GetType().Name,
|
|
'id': obj.Id.Value if obj.Id else None
|
|
})
|
|
|
|
print(f"Found {len(hydraulic_objects)} hydraulic objects:")
|
|
for hobj in hydraulic_objects:
|
|
print(f" - {hobj['name']} ({hobj['type']}) ID: {hobj['id']}")
|
|
|
|
# Ejecutar simulación TSNet
|
|
app.RunTSNetSimulationSync()
|
|
|
|
result = f"SUCCESS: Full TSNet simulation completed with {len(hydraulic_objects)} objects"
|
|
|
|
except Exception as e:
|
|
result = f"ERROR: {str(e)}"
|
|
import traceback
|
|
result += "\\n" + traceback.format_exc()
|
|
print(result)
|
|
"""
|
|
|
|
success, result = self.send_mcp_request(
|
|
"execute_python", {"code": code}, timeout=45
|
|
)
|
|
test_passed = success and "SUCCESS" in str(result)
|
|
self.log_test("TSNet Full Simulation", test_passed, str(result)[:300])
|
|
return test_passed
|
|
|
|
def test_07_adapter_validation(self):
|
|
"""Test 7: Validación de adaptadores TSNet"""
|
|
code = """
|
|
try:
|
|
print("Testing TSNet adapters validation...")
|
|
|
|
# Verificar adaptadores creados
|
|
adapter_count = {
|
|
'tanks': len(app.tsnetSimulationManager._tankAdapters) if hasattr(app.tsnetSimulationManager, '_tankAdapters') else 0,
|
|
'pumps': len(app.tsnetSimulationManager._pumpAdapters) if hasattr(app.tsnetSimulationManager, '_pumpAdapters') else 0,
|
|
'pipes': len(app.tsnetSimulationManager._pipeAdapters) if hasattr(app.tsnetSimulationManager, '_pipeAdapters') else 0
|
|
}
|
|
|
|
print(f"Adapters created: {adapter_count}")
|
|
|
|
# Validar configuraciones
|
|
config_errors = app.tsnetSimulationManager.ValidateAllConfigurations()
|
|
print(f"Configuration errors: {len(config_errors)}")
|
|
|
|
for error in config_errors:
|
|
print(f" - {error}")
|
|
|
|
total_adapters = sum(adapter_count.values())
|
|
result = f"SUCCESS: {total_adapters} adapters, {len(config_errors)} config errors"
|
|
|
|
except Exception as e:
|
|
result = f"ERROR: {str(e)}"
|
|
import traceback
|
|
result += "\\n" + traceback.format_exc()
|
|
print(result)
|
|
"""
|
|
|
|
success, result = self.send_mcp_request(
|
|
"execute_python", {"code": code}, timeout=30
|
|
)
|
|
test_passed = success and "SUCCESS" in str(result)
|
|
self.log_test("Adapter Validation", test_passed, str(result)[:300])
|
|
return test_passed
|
|
|
|
def test_08_network_rebuild(self):
|
|
"""Test 8: Reconstrucción de red hidráulica"""
|
|
code = """
|
|
try:
|
|
print("Testing network rebuild...")
|
|
|
|
# Reconstruir red
|
|
app.tsnetSimulationManager.RebuildNetwork()
|
|
|
|
# Verificar estado de la red
|
|
network_state = "Network rebuilt successfully"
|
|
if hasattr(app.tsnetSimulationManager, 'Network'):
|
|
network_state += " - Network object exists"
|
|
|
|
result = f"SUCCESS: {network_state}"
|
|
|
|
except Exception as e:
|
|
result = f"ERROR: {str(e)}"
|
|
import traceback
|
|
result += "\\n" + traceback.format_exc()
|
|
print(result)
|
|
"""
|
|
|
|
success, result = self.send_mcp_request(
|
|
"execute_python", {"code": code}, timeout=30
|
|
)
|
|
test_passed = success and "SUCCESS" in str(result)
|
|
self.log_test("Network Rebuild", test_passed, str(result)[:200])
|
|
return test_passed
|
|
|
|
def test_09_object_registration_stress(self):
|
|
"""Test 9: Stress test de registro de objetos"""
|
|
code = """
|
|
try:
|
|
print("Testing object registration stress...")
|
|
|
|
# Resetear manager
|
|
app.tsnetSimulationManager.ResetAllCalculatedValues()
|
|
|
|
# Registrar todos los objetos hidráulicos múltiples veces
|
|
registration_count = 0
|
|
for iteration in range(3):
|
|
for obj in app.ObjetosSimulables:
|
|
if obj.GetType().Name.startswith("osHyd"):
|
|
try:
|
|
app.tsnetSimulationManager.RegisterHydraulicObject(obj)
|
|
registration_count += 1
|
|
except Exception as reg_ex:
|
|
print(f"Registration error for {obj.Nombre}: {reg_ex}")
|
|
|
|
result = f"SUCCESS: {registration_count} registrations completed"
|
|
|
|
except Exception as e:
|
|
result = f"ERROR: {str(e)}"
|
|
import traceback
|
|
result += "\\n" + traceback.format_exc()
|
|
print(result)
|
|
"""
|
|
|
|
success, result = self.send_mcp_request(
|
|
"execute_python", {"code": code}, timeout=30
|
|
)
|
|
test_passed = success and "SUCCESS" in str(result)
|
|
self.log_test("Object Registration Stress", test_passed, str(result)[:200])
|
|
return test_passed
|
|
|
|
def test_10_performance_timing(self):
|
|
"""Test 10: Medición de rendimiento"""
|
|
code = """
|
|
import time
|
|
try:
|
|
print("Testing performance timing...")
|
|
|
|
# Medir tiempo de simulación completa
|
|
start_time = time.time()
|
|
|
|
# Resetear
|
|
app.tsnetSimulationManager.ResetAllCalculatedValues()
|
|
|
|
# Registrar objetos
|
|
reg_start = time.time()
|
|
hydraulic_count = 0
|
|
for obj in app.ObjetosSimulables:
|
|
if obj.GetType().Name.startswith("osHyd"):
|
|
app.tsnetSimulationManager.RegisterHydraulicObject(obj)
|
|
hydraulic_count += 1
|
|
reg_time = time.time() - reg_start
|
|
|
|
# Validar configuraciones
|
|
val_start = time.time()
|
|
config_errors = app.tsnetSimulationManager.ValidateAllConfigurations()
|
|
val_time = time.time() - val_start
|
|
|
|
# Reconstruir red
|
|
net_start = time.time()
|
|
app.tsnetSimulationManager.RebuildNetwork()
|
|
net_time = time.time() - net_start
|
|
|
|
total_time = time.time() - start_time
|
|
|
|
result = f"SUCCESS: Total: {total_time:.3f}s, Registration: {reg_time:.3f}s, Validation: {val_time:.3f}s, Network: {net_time:.3f}s ({hydraulic_count} objects)"
|
|
|
|
except Exception as e:
|
|
result = f"ERROR: {str(e)}"
|
|
import traceback
|
|
result += "\\n" + traceback.format_exc()
|
|
print(result)
|
|
"""
|
|
|
|
success, result = self.send_mcp_request(
|
|
"execute_python", {"code": code}, timeout=30
|
|
)
|
|
test_passed = success and "SUCCESS" in str(result)
|
|
self.log_test("Performance Timing", test_passed, str(result)[:300])
|
|
return test_passed
|
|
|
|
def run_all_tests(self):
|
|
"""Ejecutar todos los tests"""
|
|
print("🧪 TSNet Phase 2 - Complete Test Suite")
|
|
print("=" * 60)
|
|
print(f"Started at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|
print()
|
|
|
|
# Lista de tests a ejecutar
|
|
tests = [
|
|
self.test_01_mcp_connectivity,
|
|
self.test_02_clear_workspace,
|
|
self.test_03_create_hydraulic_system,
|
|
self.test_04_list_created_objects,
|
|
self.test_05_tsnet_basic_integration,
|
|
self.test_06_tsnet_full_simulation,
|
|
self.test_07_adapter_validation,
|
|
self.test_08_network_rebuild,
|
|
self.test_09_object_registration_stress,
|
|
self.test_10_performance_timing,
|
|
]
|
|
|
|
# Ejecutar tests
|
|
for i, test_func in enumerate(tests, 1):
|
|
print(f"\n--- Test {i:02d}: {test_func.__doc__.split(':')[1].strip()} ---")
|
|
try:
|
|
test_func()
|
|
except Exception as e:
|
|
self.log_test(f"Test {i:02d} Execution", False, f"Exception: {str(e)}")
|
|
|
|
# Pequeña pausa entre tests
|
|
time.sleep(1)
|
|
|
|
# Resumen final
|
|
self.print_summary()
|
|
|
|
def print_summary(self):
|
|
"""Imprimir resumen de resultados"""
|
|
print("\n" + "=" * 60)
|
|
print("📊 TEST SUMMARY")
|
|
print("=" * 60)
|
|
|
|
passed_tests = [r for r in self.test_results if r["passed"]]
|
|
failed_tests = [r for r in self.test_results if not r["passed"]]
|
|
|
|
print(f"Total Tests: {len(self.test_results)}")
|
|
print(f"Passed: {len(passed_tests)} ✅")
|
|
print(f"Failed: {len(failed_tests)} ❌")
|
|
print(f"Success Rate: {len(passed_tests)/len(self.test_results)*100:.1f}%")
|
|
|
|
if failed_tests:
|
|
print("\n❌ Failed Tests:")
|
|
for test in failed_tests:
|
|
print(f" • {test['test']}: {test['details'][:100]}")
|
|
|
|
if len(passed_tests) == len(self.test_results):
|
|
print("\n🎉 ALL TESTS PASSED! TSNet Phase 2 is fully functional.")
|
|
elif len(passed_tests) >= len(self.test_results) * 0.8:
|
|
print("\n✅ Most tests passed. TSNet Phase 2 is mostly functional.")
|
|
else:
|
|
print("\n⚠️ Multiple test failures. Please review the implementation.")
|
|
|
|
print(f"\nCompleted at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|
|
|
|
|
def main():
|
|
test_suite = TSNetTestSuite()
|
|
test_suite.run_all_tests()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|