test_assistant_integration.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. """Integration: the assistant service consuming a real publish-only bus."""
  2. import os
  3. import shutil
  4. import tempfile
  5. import time
  6. import pytest
  7. from stt_daemon import events
  8. from stt_daemon.assistant.service import AssistantService
  9. from stt_daemon.bus import EventPublisher, EventSubscriber
  10. from stt_daemon.config import Config
  11. @pytest.fixture
  12. def sock_path():
  13. directory = tempfile.mkdtemp(prefix="sttb-")
  14. try:
  15. yield os.path.join(directory, "s.sock")
  16. finally:
  17. shutil.rmtree(directory, ignore_errors=True)
  18. def _wait(predicate, timeout=5.0):
  19. deadline = time.time() + timeout
  20. while time.time() < deadline:
  21. if predicate():
  22. return True
  23. time.sleep(0.01)
  24. return predicate()
  25. def _heartbeat_fields():
  26. return {
  27. "in_flight": False,
  28. "segments_done": 0,
  29. "worker_stall_s": 0.0,
  30. "queue_depth": 0,
  31. "frames_since_last": 1,
  32. "rms": 0.0,
  33. "capture": "test",
  34. "device_ok": True,
  35. "model_loaded": True,
  36. "uptime_s": 1.0,
  37. "last_transcript_age_s": 0.0,
  38. }
  39. def test_service_consumes_real_bus(sock_path):
  40. cfg = Config()
  41. publisher = EventPublisher(sock_path, ring_size=10)
  42. publisher.start()
  43. subscriber = EventSubscriber(sock_path, reconnect_delay=0.05)
  44. emitted: list[dict] = []
  45. service = AssistantService(
  46. cfg,
  47. subscriber,
  48. emit=lambda type_, **fields: emitted.append({"type": type_, **fields}),
  49. )
  50. service.start()
  51. try:
  52. publisher.emit(events.HEARTBEAT, **_heartbeat_fields())
  53. assert _wait(lambda: service.stt_ok() is True)
  54. assert service.arm() is True
  55. assert _wait(lambda: any(e.get("mode") == "command_armed" for e in emitted))
  56. publisher.emit(events.SPEECH_START)
  57. assert _wait(lambda: service.speech_open is True)
  58. publisher.emit(events.SPEECH_STOP, seg_id=5)
  59. assert _wait(lambda: service.awaited_seg_id == 5)
  60. assert service.ready() is False
  61. publisher.emit(events.SEGMENT_DONE, seg_id=5, emitted=True)
  62. assert _wait(lambda: service.ready() is True)
  63. publisher.emit(events.TRANSCRIPT, seg_id=5, text="hello", lang="en", lang_prob=0.9)
  64. assert _wait(lambda: service.command_text == "hello")
  65. assert service.execute() == "hello"
  66. assert service.finish() is True
  67. finally:
  68. service.stop()
  69. publisher.close()