aboutsummaryrefslogtreecommitdiff
path: root/lib/project/tests
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-09-12 18:45:33 -0400
committerhistoria <historiavg@proton.me>2026-09-12 18:45:33 -0400
commita5bca8573e7781f71aba9575acd99f1a7e82cbe4 (patch)
treee469d0f80308792dde6d1bd9894769e3e058cabc /lib/project/tests
parent45cb401b194be6dbffd2fbd226b88de0f1a2df30 (diff)
downloadproducer-a5bca8573e7781f71aba9575acd99f1a7e82cbe4.tar.gz
feat: gui notifications when changing sound profile
Diffstat (limited to 'lib/project/tests')
-rw-r--r--lib/project/tests/test_gui.py31
-rw-r--r--lib/project/tests/test_gui_browser.py1
2 files changed, 32 insertions, 0 deletions
diff --git a/lib/project/tests/test_gui.py b/lib/project/tests/test_gui.py
index e490e99..2f17549 100644
--- a/lib/project/tests/test_gui.py
+++ b/lib/project/tests/test_gui.py
@@ -1,5 +1,6 @@
"""Optional GUI API, origin boundary, uploads, snapshots, and real sound previews."""
from dataclasses import asdict
+import socket
import hashlib
from pathlib import Path
import struct
@@ -13,6 +14,7 @@ pytest.importorskip("fastapi")
from fastapi.testclient import TestClient
from producer.config import Settings
+from producer import gui as gui_module
from producer.gui import create_app
from producer import gui_jobs
@@ -280,3 +282,32 @@ def test_waveform_buffers_bounded_and_scan_cancellable(wav, monkeypatch):
with pytest.raises(gui_jobs.Cancelled):
gui_jobs.waveform(source, cancel)
assert reads == [65536]
+
+
+def test_serve_listener_allows_quick_restart(monkeypatch):
+ """serve() must set SO_REUSEADDR: without it a restart right after Ctrl+C
+ fails while connections the server closed first sit in TIME_WAIT."""
+ captured = {}
+
+ class FakeServer:
+ def __init__(self, config):
+ pass
+ def run(self, sockets):
+ captured["sockets"] = sockets
+ (sock,) = sockets
+ # Sample the state while serve() still holds the socket open.
+ captured["reuseaddr"] = sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
+ captured["address"] = sock.getsockname()
+
+ class FakeConfig:
+ def __init__(self, *args, **kwargs):
+ pass
+
+ class FakeUvicorn:
+ Server, Config = FakeServer, FakeConfig
+
+ monkeypatch.setitem(__import__("sys").modules, "uvicorn", FakeUvicorn)
+ monkeypatch.setattr(gui_module, "create_app", lambda *a, **k: object())
+ gui_module.serve(18765)
+ assert captured["reuseaddr"] == 1
+ assert captured["address"] == ("127.0.0.1", 18765)
diff --git a/lib/project/tests/test_gui_browser.py b/lib/project/tests/test_gui_browser.py
index 385de44..efc6e55 100644
--- a/lib/project/tests/test_gui_browser.py
+++ b/lib/project/tests/test_gui_browser.py
@@ -8,6 +8,7 @@ The long overview case uses mocked fixed-size scan metadata, not 4-hour AI infer
from dataclasses import asdict
import hashlib
import json
+import os
from pathlib import Path
import socket
import threading