From 615a8e65160689496197b82822226eb47cff7872 Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Sun, 21 Jun 2026 16:42:10 -0700 Subject: [PATCH] fix(whatsapp): add missing re import + fix test import path after adapter relocation Follow-up to the salvaged #43846 commits: the WhatsApp adapter moved from gateway/platforms/whatsapp.py to plugins/platforms/whatsapp/adapter.py since the PR was authored. The cherry-pick brought _listener_pids_on_port's `re.finditer` ss-fallback and the new test's import, but the new module location doesn't import `re` (latent NameError on the lsof-absent fallback path) and the test imported the old module path. Add `import re` to the adapter and repoint the test import. --- plugins/platforms/whatsapp/adapter.py | 1 + tests/gateway/test_whatsapp_bridge_pidfile.py | 2 +- tests/gateway/test_whatsapp_connect.py | 45 ++++++++++++------- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/plugins/platforms/whatsapp/adapter.py b/plugins/platforms/whatsapp/adapter.py index 94ba3064b..c10d9a51a 100644 --- a/plugins/platforms/whatsapp/adapter.py +++ b/plugins/platforms/whatsapp/adapter.py @@ -19,6 +19,7 @@ import asyncio import logging import os import platform +import re import signal import subprocess diff --git a/tests/gateway/test_whatsapp_bridge_pidfile.py b/tests/gateway/test_whatsapp_bridge_pidfile.py index b25a7d30f..3da6fe998 100644 --- a/tests/gateway/test_whatsapp_bridge_pidfile.py +++ b/tests/gateway/test_whatsapp_bridge_pidfile.py @@ -22,7 +22,7 @@ import pytest import os import socket -from gateway.platforms.whatsapp import ( +from plugins.platforms.whatsapp.adapter import ( _bridge_pid_is_ours, _kill_port_process, _kill_stale_bridge_by_pidfile, diff --git a/tests/gateway/test_whatsapp_connect.py b/tests/gateway/test_whatsapp_connect.py index 93b3ab453..52e36f5b7 100644 --- a/tests/gateway/test_whatsapp_connect.py +++ b/tests/gateway/test_whatsapp_connect.py @@ -13,6 +13,7 @@ Regression tests for two bugs in WhatsAppAdapter.connect(): """ import asyncio +import signal from pathlib import Path from unittest.mock import AsyncMock, MagicMock, patch @@ -517,31 +518,41 @@ class TestKillPortProcess: for call in mock_run.call_args_list ) - def test_uses_fuser_on_linux(self): - from plugins.platforms.whatsapp.adapter import _kill_port_process + def test_kills_only_listeners_on_linux(self): + """POSIX path SIGTERMs only LISTENer PIDs (never clients) — the #43846 fix. - mock_check = MagicMock(returncode=0) + Replaces the old fuser-based test: ``fuser``/bare ``lsof -i`` also + matched client sockets sharing the port number, which closed unrelated + processes (a browser tab on the same port). The implementation now + resolves listeners via ``_listener_pids_on_port`` and signals only those. + """ + from plugins.platforms.whatsapp import adapter as wa + kills = [] with patch("plugins.platforms.whatsapp.adapter._IS_WINDOWS", False), \ - patch("plugins.platforms.whatsapp.adapter.subprocess.run", return_value=mock_check) as mock_run: - _kill_port_process(3000) + patch("plugins.platforms.whatsapp.adapter._listener_pids_on_port", + return_value=[55555]) as mock_listeners, \ + patch("plugins.platforms.whatsapp.adapter.os.kill", + side_effect=lambda pid, sig: kills.append((pid, sig))): + wa._kill_port_process(3000) - calls = [c.args[0] for c in mock_run.call_args_list] - assert ["fuser", "3000/tcp"] in calls - assert ["fuser", "-k", "3000/tcp"] in calls + mock_listeners.assert_called_once_with(3000) + assert kills == [(55555, signal.SIGTERM)] - def test_skips_fuser_kill_when_port_free(self): - from plugins.platforms.whatsapp.adapter import _kill_port_process - - mock_check = MagicMock(returncode=1) # port not in use + def test_no_kill_when_no_listener_on_port(self): + """No LISTENer on the port → nothing is signalled.""" + from plugins.platforms.whatsapp import adapter as wa + kills = [] with patch("plugins.platforms.whatsapp.adapter._IS_WINDOWS", False), \ - patch("plugins.platforms.whatsapp.adapter.subprocess.run", return_value=mock_check) as mock_run: - _kill_port_process(3000) + patch("plugins.platforms.whatsapp.adapter._listener_pids_on_port", + return_value=[]) as mock_listeners, \ + patch("plugins.platforms.whatsapp.adapter.os.kill", + side_effect=lambda pid, sig: kills.append((pid, sig))): + wa._kill_port_process(3000) - calls = [c.args[0] for c in mock_run.call_args_list] - assert ["fuser", "3000/tcp"] in calls - assert ["fuser", "-k", "3000/tcp"] not in calls + mock_listeners.assert_called_once_with(3000) + assert kills == [] def test_suppresses_exceptions(self): from plugins.platforms.whatsapp.adapter import _kill_port_process