import os import threading import time import numpy as np import pytest def test_frame_roundtrip_stereo_hop(): from enhance_ipc import dump_frame, load_frame hop = 1600 t = np.arange(hop, dtype=np.int16) pcm = np.stack([t, t + 1], axis=1) blob = dump_frame("cam-07", pcm) ident, out = load_frame(blob) assert ident == "cam-07" assert out.dtype == np.int16 assert out.shape == (hop, 2) np.testing.assert_array_equal(out, pcm) def test_unix_client_gets_handler_output(tmp_path): from enhance_daemon import serve_unix from enhance_ipc import EnhanceClient sock = str(tmp_path / "enhance.sock") stop = threading.Event() def handler(ident, pcm): assert ident == "cam-03" # fake "enhance": average channels, invert if pcm.ndim == 2: mono = pcm.mean(axis=1) else: mono = pcm return (-mono).astype(np.int16) t = threading.Thread(target=serve_unix, args=(sock, handler, stop), daemon=True) t.start() deadline = time.time() + 2 while time.time() < deadline and not (tmp_path / "enhance.sock").exists(): time.sleep(0.01) hop = 800 pcm = np.stack([np.full(hop, 1000, np.int16), np.full(hop, 3000, np.int16)], axis=1) client = EnhanceClient(sock) try: out = client.process("cam-03", pcm) finally: client.close() stop.set() assert out.dtype == np.int16 assert out.shape == (hop,) assert int(out[0]) == -2000 def _start_echo_daemon(sock, stop): from enhance_daemon import serve_unix def handler(ident, pcm): if pcm.ndim == 2: mono = pcm.mean(axis=1) else: mono = pcm return np.asarray(mono, dtype=np.int16) t = threading.Thread(target=serve_unix, args=(sock, handler, stop), daemon=True) t.start() deadline = time.time() + 2 while time.time() < deadline and not os.path.exists(sock): time.sleep(0.01) return t def test_audio_cleaner_remote_does_not_load_model(tmp_path): from audio_cleanup import AudioCleaner sock = str(tmp_path / "enhance.sock") stop = threading.Event() _start_echo_daemon(sock, stop) try: c = AudioCleaner( mode="force", beamform="force", enhance_socket=sock, identity="cam-09") assert c._enhancer is None assert c._beamformer is None assert c.backend == "daemon" hop = 1600 stereo = np.stack([ np.full(hop, 400, np.int16), np.full(hop, 800, np.int16), ], axis=1) out = c.process(stereo) assert out.shape == (hop,) assert out.dtype == np.int16 assert int(out[0]) == 600 finally: stop.set() def test_shared_engine_constructs_one_cleaner_for_two_cams(): from audio_cleanup import AudioCleaner from enhance_daemon import SharedEnhanceEngine n = {"c": 0} def make(): n["c"] += 1 return AudioCleaner(mode="off", beamform="off") eng = SharedEnhanceEngine(make_cleaner=make) hop = np.zeros(800, dtype=np.int16) out_a = eng.process("cam-01", hop) out_b = eng.process("cam-02", hop) out_a2 = eng.process("cam-01", hop) assert n["c"] == 1 assert set(eng.identities()) == {"cam-01", "cam-02"} assert out_a.shape == (800,) assert out_b.shape == (800,) assert out_a2.shape == (800,) def test_wait_for_socket_false_then_true(tmp_path): from enhance_daemon import wait_for_socket, serve_unix sock = str(tmp_path / "missing.sock") assert wait_for_socket(sock, timeout=0.15) is False stop = threading.Event() t = threading.Thread( target=serve_unix, args=(sock, lambda i, p: p, stop), daemon=True) t.start() try: assert wait_for_socket(sock, timeout=2.0) is True finally: stop.set()