#!/usr/bin/env python3 """El candado: que tape, que rechace lo que no es, y que NO obedezca. ./venv/bin/python pruebas/prueba_candado.py Lo que de verdad importa aqui no es que el panel se ponga negro —eso es cosmetica— sino que con el candado puesto **no se ejecute nada**. El panel tapado pero obedeciendo seria peor que no tener candado, porque da sensacion de seguridad sin darla. No se prueba con la contraseña de verdad: no la tenemos ni hace falta. Se comprueba que una mala se rechaza y que mientras tanto no pasa ni una orden. """ import os import sys import threading import time AQUI = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, AQUI) from boca.voz import Boca # noqa: E402 from cara.panel import Panel # noqa: E402 from manos import Manos # noqa: E402 fallos = [] def afirma(condicion, queja): print(f" {'OK ' if condicion else 'MAL'} {queja}") if not condicion: fallos.append(queja) class CaraFalsa: """Se queda con lo que el panel manda, sin levantar ningun servidor.""" def __init__(self): self.mensajes = [] self.conectados = 1 def manda(self, tipo, datos): self.mensajes.append((tipo, datos)) def de(self, tipo): return [d for t, d in self.mensajes if t == tipo] class BocaMuda(Boca): """Como la de verdad pero sin sonar: la prueba no tiene que hablar.""" def __init__(self): super().__init__("davefx") self.dicho = [] def di(self, texto): self.dicho.append(texto); return True def di_si_libre(self, texto): self.dicho.append(texto); return True def main() -> int: manos = Manos() cara = CaraFalsa() boca = BocaMuda() p = Panel(cara, boca, manos, candado=True) print("\n al abrir") p.arranca() time.sleep(0.2) afirma(not p.desbloqueado, "nace bloqueado") afirma(bool(cara.de("bloqueo")), "pide la contraseña nada mas abrir") print("\n con el candado puesto NO obedece") antes = len(cara.mensajes) for orden in ("prueba", "voz:siguiente", "parar"): p.pulsado("accion", orden) time.sleep(1.0) afirma(not boca.dicho, f"no ha hablado ({boca.dicho})") # Desde que la tanda va por tareas, lo que se ve al ejecutar son mensajes # "tarea" (una tarjeta por orden), no "respuesta". hechas = [d for t, d in cara.mensajes[antes:] if t in ("tarea", "respuesta")] afirma(not hechas, f"no ha ejecutado nada ({len(hechas)} tareas o respuestas)") # Solo se miran las respuestas a lo pulsado: la telemetria sigue latiendo # en su hilo cada segundo y se cuela entre medias. contestaciones = [t for t, _ in cara.mensajes[antes:] if t != "telemetria"] afirma(contestaciones and all(t == "bloqueo" for t in contestaciones), f"a cada intento contesta pidiendo la contraseña ({contestaciones})") print("\n una contraseña mala se rechaza") antes = len(cara.mensajes) p.pulsado("accion", "desbloquear:no-es-esta-contrasena-12345") time.sleep(0.5) afirma(not p.desbloqueado, "sigue bloqueado") ultimos = cara.de("bloqueo")[-1:] or [{}] afirma(ultimos[0].get("error") is True, "y lo dice como error") afirma(not cara.de("desbloqueado"), "no manda 'desbloqueado'") print("\n una vacia ni se intenta") antes = len(cara.mensajes) p.pulsado("accion", "desbloquear:") afirma(len(cara.mensajes) == antes, "no molesta a sudo con una clave vacia") print("\n sin candado, obedece") cara2, boca2 = CaraFalsa(), BocaMuda() p2 = Panel(cara2, boca2, manos, candado=False) p2.arranca() afirma(p2.desbloqueado, "nace desbloqueado") afirma(not cara2.de("bloqueo"), "no pide contraseña") p2.pulsado("accion", "prueba") time.sleep(3.0) tarjetas = {d["id"] for d in cara2.de("tarea")} afirma(bool(tarjetas), f"ejecuta de verdad ({len(tarjetas)} tarjetas)") afirma(any(d["estado"] == "hecha" for d in cara2.de("tarea")), "y las tareas llegan a terminar") print("\n y se puede volver a echar") p2.bloquea() afirma(not p2.desbloqueado, "bloquea() cierra aunque arrancara sin candado") antes = len(cara2.mensajes) p2.pulsado("accion", "prueba") time.sleep(0.6) afirma(not [d for t, d in cara2.mensajes[antes:] if t in ("tarea", "respuesta")], "y despues de cerrar ya no obedece") p.para(); p2.para() print(f"\n {'todo en orden' if not fallos else str(len(fallos)) + ' fallan'}\n") return 1 if fallos else 0 if __name__ == "__main__": sys.exit(main())