From 673253d848cdd2ed92418fa67216cdb64bff258b Mon Sep 17 00:00:00 2001 From: YueGuobin Date: Fri, 11 Sep 2026 23:49:51 +0800 Subject: [PATCH] ci: install sharkd in the test workflow and make manager tests hermetic The replay tests marked sharkd_present skip gracefully without the binary, but four manager-level tests (cap eviction, in-use protection, single spawn under concurrency, filter-error mapping) run entirely against fakes and died on the acquire-time PATH check instead - install wireshark-common (which ships /usr/bin/sharkd on the Ubuntu runner) so the real-engine tests actually run in CI, and patch the which() check in the fake-session tests so the suite stays green on machines without sharkd. --- .github/workflows/testing.yml | 4 ++++ tests/controller/test_marker_replay.py | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 20c1cf5ea..d0bfa4f1a 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -30,6 +30,10 @@ jobs: run: | python -m pip install --upgrade pip python -m pip install .[ai-features,dev] + - name: Install sharkd (marker replay engine) + run: | + sudo apt-get update + sudo apt-get install -y wireshark-common - name: Lint with flake8 run: | diff --git a/tests/controller/test_marker_replay.py b/tests/controller/test_marker_replay.py index 3c3ed252b..19888bbd0 100644 --- a/tests/controller/test_marker_replay.py +++ b/tests/controller/test_marker_replay.py @@ -170,6 +170,12 @@ class _FakeSession: self.closed = True +def _pretend_sharkd(monkeypatch): + """The manager-level tests run entirely against fakes — the sharkd binary + must not be a precondition (the suite stays green without the engine).""" + monkeypatch.setattr(marker_replay.shutil, "which", lambda name: "/usr/bin/sharkd") + + # --------------------------------------------------------------------------- # pcap scanning (engine-free backbone) # --------------------------------------------------------------------------- @@ -473,7 +479,8 @@ class TestSessions: with pytest.raises(SharkdMissingError): await build_timeline(project, tag=7) - async def test_cap_evicts_idle_lru_only(self, tmp_path): + async def test_cap_evicts_idle_lru_only(self, tmp_path, monkeypatch): + _pretend_sharkd(monkeypatch) manager = marker_replay._SharkdManager() fakes = {} @@ -495,7 +502,8 @@ class TestSessions: assert fakes[str(tmp_path / "pcap1")].closed is True assert fakes[str(tmp_path / "pcap2")].closed is False - async def test_in_use_session_survives_cap_pressure(self, tmp_path): + async def test_in_use_session_survives_cap_pressure(self, tmp_path, monkeypatch): + _pretend_sharkd(monkeypatch) manager = marker_replay._SharkdManager() async def fake_spawn(pcap, stat): @@ -518,7 +526,8 @@ class TestSessions: assert len(manager._sessions) <= marker_replay.SESSION_MAX await manager.close_all() - async def test_concurrent_acquire_spawns_once(self, tmp_path): + async def test_concurrent_acquire_spawns_once(self, tmp_path, monkeypatch): + _pretend_sharkd(monkeypatch) manager = marker_replay._SharkdManager() spawns = [] @@ -582,6 +591,7 @@ class TestSessions: assert proc.returncode is not None async def test_filter_error_only_for_the_filter_code(self, tmp_path, monkeypatch): + _pretend_sharkd(monkeypatch) manager = marker_replay._SharkdManager() monkeypatch.setattr(marker_replay, "_manager", manager) pcap = tmp_path / "n1_linkA_icmp.pcap"