Files
agent-call/tests/test_real_cell.py
T

176 lines
6.4 KiB
Python

from __future__ import annotations
import socket
import struct
import tempfile
import unittest
from pathlib import Path
from types import SimpleNamespace
from typing import cast
from agent_call.real_cell import (
CellCallConfig,
CellCallError,
CellExecutionLedger,
RealCellCall,
RealCellWorker,
RTPMedia,
alaw_to_pcm16,
voice_level,
)
class FakeBroker:
def __init__(self, messages: list[dict]) -> None:
self.messages = list(messages)
self.acked: list[dict] = []
self.requeued: list[dict] = []
self.rejected: list[dict] = []
self.published: list[dict] = []
def declare_tenant(self, tenant_key: str) -> None:
self.tenant_key = tenant_key
def consume(self, _queue: str) -> dict | None:
return self.messages.pop(0) if self.messages else None
def ack(self, message: dict) -> None:
self.acked.append(message)
def requeue(self, message: dict) -> None:
self.requeued.append(message)
def reject(self, message: dict) -> None:
self.rejected.append(message)
def publish(
self, _exchange: str, _route: str, body: dict, **_kwargs: object
) -> None:
self.published.append(body)
class RealCellTests(unittest.TestCase):
def test_pcma_decode_and_rtp_payload(self) -> None:
media = RTPMedia("127.0.0.1", 0)
receiver = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
receiver.bind(("127.0.0.1", 0))
try:
media.peer = ("127.0.0.1", receiver.getsockname()[1])
sent = media.send_pcm16(b"\x00\x00" * 160, 8000)
packet, _ = receiver.recvfrom(512)
self.assertEqual(sent, 160)
self.assertEqual(len(packet), 172)
self.assertEqual(packet[1] & 0x7F, 8)
self.assertEqual(packet[12:], b"\xd5" * 160)
self.assertEqual(len(alaw_to_pcm16(packet[12:])), 320)
self.assertEqual(voice_level(alaw_to_pcm16(packet[12:])), 8)
finally:
media.close()
receiver.close()
def test_rtp_payload_handles_extension_and_padding(self) -> None:
payload = b"abc"
packet = struct.pack("!BBHII", 0xB0, 8, 1, 2, 3)
packet += struct.pack("!HH", 0, 1) + b"xxxx" + payload + b"\x00\x00\x03"
self.assertEqual(RTPMedia._payload(packet), payload)
self.assertIsNone(RTPMedia._payload(b"bad"))
def test_cell_config_rejects_non_pcma_and_bad_port(self) -> None:
with self.assertRaises(CellCallError):
CellCallConfig("http://127.0.0.1:8088", "u", "p", rtp_format="ulaw")
with self.assertRaises(CellCallError):
CellCallConfig("http://127.0.0.1:8088", "u", "p", rtp_bind_port=65536)
def test_ledger_marks_in_progress_as_in_doubt(self) -> None:
with tempfile.TemporaryDirectory() as directory:
ledger = CellExecutionLedger(Path(directory) / "ledger.sqlite3")
first = ledger.claim("exec-1", "15003164745")
second = ledger.claim("exec-1", "15003164745")
self.assertTrue(first["claimed"])
self.assertTrue(second["in_doubt"])
def test_worker_uses_queue_and_never_redials_terminal_execution(self) -> None:
command = {
"body": {
"command_type": "call.execute",
"tenant_id": "tenant-demo",
"tenant_key": "tenant-key",
"payload": {
"execution_id": "exec-1",
"agent_version_id": "agent_v1",
"callee": "15003164745",
},
}
}
broker = FakeBroker([command, command])
with tempfile.TemporaryDirectory() as directory:
ledger = CellExecutionLedger(Path(directory) / "ledger.sqlite3")
fake_result = SimpleNamespace(
as_dict=lambda: {
"call_id": "call-1",
"status": "failed",
"reason_code": "CUSTOMER_SILENT",
"recording_path": "/private/recording.wav",
}
)
class FakeExecutor:
def __init__(self) -> None:
self.engine = SimpleNamespace(
config={"agent_version_id": "agent_v1"}
)
self.calls: list[str] = []
def start_authorized_call(self, callee: str) -> SimpleNamespace:
self.calls.append(callee)
return fake_result
fake_executor = FakeExecutor()
executor = cast(RealCellCall, fake_executor)
worker = RealCellWorker(broker, "tenant-key", ledger, executor)
first = worker.process_once()
second = worker.process_once()
if first is None or second is None:
self.fail("worker did not publish a call.finished event")
self.assertEqual(first["event_type"], "call.finished")
self.assertEqual(second["event_type"], "call.finished")
self.assertEqual(fake_executor.calls, ["15003164745"])
self.assertEqual(len(broker.acked), 2)
self.assertNotIn("recording_path", broker.published[0]["payload"])
def test_worker_rejects_wrong_tenant_route(self) -> None:
broker = FakeBroker(
[
{
"body": {
"command_type": "call.execute",
"tenant_id": "tenant-demo",
"tenant_key": "other-tenant",
"payload": {
"execution_id": "exec-1",
"agent_version_id": "agent_v1",
"callee": "15003164745",
},
}
}
]
)
with tempfile.TemporaryDirectory() as directory:
ledger = CellExecutionLedger(Path(directory) / "ledger.sqlite3")
executor = cast(
RealCellCall,
SimpleNamespace(
engine=SimpleNamespace(config={"agent_version_id": "agent_v1"})
),
)
worker = RealCellWorker(broker, "tenant-key", ledger, executor)
result = worker.process_once()
if result is None:
self.fail("worker returned no command result")
self.assertEqual(result["reason_code"], "COMMAND_INVALID")
self.assertEqual(len(broker.rejected), 1)
if __name__ == "__main__":
unittest.main()