Skip to content

ci: give the pyshark engine real-capture coverage, and stop a fallback passing as a pass - #846

Merged
JarryShaw merged 1 commit into
mainfrom
fix/845-pyshark-real-capture-coverage
Sep 27, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
fix/845-pyshark-real-capture-coverage

Conversation

@JarryShaw

Copy link
Copy Markdown
Owner

Please follow the guide below

What is the purpose of your pull request?

  • fix — corrects a defect
  • feat — adds a feature
  • perf — changes performance, not behaviour
  • refactor — changes neither behaviour nor performance
  • test — tests only
  • docs — documentation only
  • ci — workflows or build tooling
  • chore — anything else

Description of your pull request and other information

#845's first finding: no CI job anywhere drove engine='pyshark' through a real
tshark-parsed capture
, on any Python version, so the engine's own code path was never
exercised.

The one real engine='pyshark' extraction is in
tests/integration/test_engine_runtime.py. engine-tests installs both pyshark and
tshark but its selection ignores tests/integration and *_runtime.py wholesale, so it
cannot reach it. pypcap-parity can reach it and installs pyshark — but installed no
tshark (grep -ci tshark over its whole job log returned 0). So
PyShark.unsupported_reason() declined the engine, the extractor fell back to the built-in
parser, and assertGreater(extractor.length, 0) passed on the fallback's output. A
vacuous pass, invisible in every skip count.

Two changes:

  • pypcap-parity installs tshark, with the debconf pre-seed and DEBIAN_FRONTEND
    copied from engine-tests's own tshark step — without the pre-seed, tshark's postinst
    blocks on the "allow non-superusers to capture packets" prompt.
  • The test proves which engine ran: no EngineWarning fired, extractor._exnam == 'pyshark', and the engine is a PyShark instance. Same idiom as
    test_new_engine_parity_runtime.py's extract helper already uses for PyPCAP. The
    existing length assertion is kept, not weakened.

Deliberately narrow. #845's other two findings are not here: the PyPCAPFile
marker-shadowing fix is superseded by the maintainer's two-dimension matrix ruling on that
issue, and promoting Engines Python X to a required check is a ruleset change rather than
a workflow one.

One honest limit. The new assertion sits in the sys.version_info < (3, 14) branch, and
this host's venv is 3.14.7, so it takes the other branch locally — it is verified by
construction against the identical idiom in the already-passing parity test, not by local
execution. CI's 3.10/3.11 legs are what will actually exercise it.

Tests: 106 passed (tests/integration/test_engine_runtime, tests/test_tier_guard).

Refs #845.

@JarryShaw JarryShaw added ci Pull requests that change CI or workflow configuration (ci: subject prefix) test Pull requests that add or correct tests (test: subject prefix) review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Sep 27, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

GOOD TO GO — cross-review (opus, a different model from the sonnet author) on d9536763f.
No blockers. Two nits, one of which I am fixing here.

The load-bearing premise held under independent attack. It built the per-job table itself and
confirmed pypcap-parity is the only job that can reach the real engine='pyshark'
extraction: test and engine-tests exclude tests/integration and *_runtime.py twice over;
integration collects the file but installs no pyshark, so it skips; gate installs no pyshark
and runs only on the release path. It then falsified the broader claim too — the only other
non-mocked PyShark construction substitutes a FakeCapture, so tshark never runs there.

It did better than I could on the one thing I flagged as unverified. I said the new assertion
was verified by construction, since this host is 3.14.7 and the assertion sits in the < 3.14
branch. It drove that branch directly, twice — at the real ceiling and with the ceiling lifted and
tshark stripped from PATH — and reproduced the vacuous pass exactly: _exnam='default',
engine=PCAP, all three new assertions failing while the pre-existing assertGreater(length, 0)
passed on the fallback's output with length = 6.

Better still, CI has now proved it for real. PyPCAP/PyPCAPFile parity Python 3.10 and 3.11
are green on this head, and the 3.10 log shows Setting up tshark (4.2.2-1.1build3) with no
debconf hang and 176 passed, 2 skipped, 1754 subtests passed. So the caveat in the PR body is now
outdated in the PR's favour, and the debconf pre-seed is confirmed working rather than merely
copied.

Also confirmed: the EngineWarning filter is neither vacuous nor over-broad — all four fallback
warn sites in pcapkit/foundation/extraction.py pass the category positionally as args[1],
observed live, and the co-occurring ExtractionWarning is correctly excluded. Pre-seed identical
to engine-tests's. Scope exactly two files, with tests/_dependency_gates.py and
tests/test_tier_guard.py untouched.

The nit worth acting on: tests/integration/test_engine_parity.py:8-10 still says pyshark
"needs tshark, which is not installed here" — and that file is collected by the very leg this
PR installs tshark into, so the sentence is now false in the leg it describes. Fixing it in this
PR rather than leaving stale prose behind; it is the same class of self-contradiction that has cost
#838 four review rounds.

Left alone: the local named engines in the new assertion holds warning messages, not engine
names. Harmless, and renaming it would churn the diff for no behavioural gain.

One residual the reviewer named honestly: pytest -q prints no skip reasons, so it could not prove
from the log that the pyshark test is not one of that leg's 2 skips — inference, not observation.

…k passing as a pass

#845's first finding: no CI job anywhere drove `engine='pyshark'` through a
real tshark-parsed capture, so the engine's own code path was never
exercised on any Python version.

- .github/workflows/unit-tests.yml: the `pypcap-parity` job now installs
  tshark alongside libpcap-dev. It is the only job whose selection can
  reach tests/integration/test_engine_runtime.py's real `engine='pyshark'`
  extraction -- `engine-tests` installs both pyshark and tshark but ignores
  tests/integration and *_runtime.py wholesale. The debconf pre-seed and
  DEBIAN_FRONTEND mirror `engine-tests`'s own tshark step, or the postinst
  blocks on the capture-permissions prompt.
- tests/integration/test_engine_runtime.py: the pyshark case now asserts no
  EngineWarning fired, `extractor._exnam == 'pyshark'`, and the engine is a
  PyShark instance -- following test_new_engine_parity_runtime.py's pattern.
  Without tshark the engine declines, the extractor silently falls back to
  the built-in parser, and the existing length assertion passed on the
  fallback's output: a vacuous pass, invisible in skip counts.

Deliberately narrow. #845's other two findings are not addressed here: the
PyPCAPFile marker gap is superseded by the maintainer's two-dimension
matrix ruling on that issue, and promoting `Engines Python X` to a required
check is a ruleset change, not a workflow one.

Tests: 106 passed (tests/integration/test_engine_runtime, tests/test_tier_guard).
The new assertion sits in the Python < 3.14 branch, which this host's 3.14.7
venv does not take, so it is verified by construction against the existing
parity test's identical idiom rather than by local execution.

Refs #845.
@JarryShaw
JarryShaw force-pushed the fix/845-pyshark-real-capture-coverage branch from d953676 to 8d15a90 Compare September 27, 2026 05:56
@JarryShaw

Copy link
Copy Markdown
Owner Author

Label not updated after review?

Code LGTM. I'll merge once CI passed.

@JarryShaw JarryShaw added review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Sep 27, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Recorded, verbatim: "Label not updated after review? Code LGTM. I'll merge once CI passed."

You are right, and it was mine to flip — corrected to review: good-to-go.

One thing worth stating rather than glossing, since the head moved after the verdict. The
GOOD TO GO was earned on d9536763f; the head is now 8d15a90eb. My own rule is that a
review: * label tracks the current sha, so strictly that verdict is on a superseded head.
I am carrying it forward rather than claiming a fresh one, because the entire delta is the
docstring nit the review itself raised:

$ git diff --stat d9536763f 8d15a90eb
 tests/integration/test_engine_parity.py | 8 +++++---

Nothing but prose, in a test module's module docstring, fixing the sentence that claimed tshark is
"not installed here" — false in the very leg this PR installs it into. No executable line changed,
and 106 tests still pass.

If you would rather the label only ever sit on a sha a reviewer actually saw, say so and I will
re-run a short check on 8d15a90eb instead of carrying it — that is a defensible stricter reading
and it costs about twelve minutes.

CI on 8d15a90eb was 17✅ / 0❌ / 3 skipped / 10 running at last read. Worth noting the gate is
stricter than when this PR opened: per your ruling I added Engines Python 3.10-3.14 and
PyPCAP/PyPCAPFile parity Python 3.10/3.11 to ruleset 23497679, so this PR's own parity legs are
now required rather than advisory — which is fitting, given it is the PR that makes them mean
something.

@JarryShaw
JarryShaw merged commit 30bca99 into main Sep 27, 2026
31 checks passed
@JarryShaw
JarryShaw deleted the fix/845-pyshark-real-capture-coverage branch September 27, 2026 12:17
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Sep 27, 2026
JarryShaw added a commit that referenced this pull request Sep 27, 2026
engine='pyshark' had no CI job driving it through a real tshark-parsed
capture: pypcap-parity installed pyshark but not tshark, so
PyShark.unsupported_reason() declined the engine, the extractor fell back
to the built-in parser, and the one real-extraction assertion passed
against the fallback's output -- a vacuous pass invisible in every skip
count.

pypcap-parity now installs tshark with the same debconf pre-seed
engine-tests already carries, and the test proves which engine actually
ran rather than trusting the assertion alone.
JarryShaw added a commit that referenced this pull request Sep 27, 2026
Adds util/pyshark_encap_map.py, a generator that regenerates
ENCAP_TYPE_TO_LINKTYPE (152 entries) and FILTER_NAME_TO_LINKTYPE (58) in
place inside pcapkit/toolkit/pyshark.py, so the two tables #850 hand-built
stop being hand-maintained. Guards against its own worst failure mode: a
naive LinkType(dlt) lookup cannot detect an unmapped DLT, because
_missing_ mints a placeholder rather than raising, so the generator
snapshots every known value before any lookup.

The real-tshark sweep is gated on a new HAS_WIRESHARK flag and is
version-pinned -- editcap -T accepts 226 encapsulations on Wireshark
4.6.9, 224 on 4.2.2 (CI's Ubuntu noble) -- so the count assertions run
only under the measured version. One line of pyshark.py itself changes as
a result: the IPMB_LINUX table entry becomes I2C_LINUX, the canonical
name #848 gave value 209.

util/changelog_md.py regenerated CHANGELOG.md for all seven entries added
across this and the six preceding commits (#838, #846, #847, #848, #849,
#850, #853); `--check` exit 0.
JarryShaw added a commit that referenced this pull request Sep 27, 2026
#846 and #850

- #838's "the 21 whose vendor crawler leaves Vendor.process() unmodified"
  measures 22, not 21 -- pcapkit.const.hip.transport.Transport also has an
  unmodified process(), but its FLAG-bound range has no unassigned gap, so
  its _missing_ carries no bounded-range extend_enum branch to fix. The
  real discriminator is that branch, not the process() override; reworded,
  and the "other 84" split into the 83 that do override process() and the
  one that doesn't but has nothing to fix either. Re-derived independently
  against 5e25db2^..5e25db2 (not main, which would fold in #847's own
  edit to ipx/socket.py): 22 registries have no process() override, 21 of
  them have the bounded-range branch, matching
  tests/const/test_const_enum_no_mint.py's own REGISTRIES_WITH_UNASSIGNED_RANGES
  (21 entries) vs ALL_REGISTRIES (22, +hip.transport, with a NOTE explaining
  the exclusion).

- #846's "Only tests/integration/test_engine_runtime.py and
  test_engine_parity.py change" is false -- 30bca99's own numstat also
  touches .github/workflows/unit-tests.yml (17+/2-). Qualified to "only
  these two test files change".

- #850 gets the breaking marker: its own prose already says the fallback
  is gone and an unrecognised encapsulation or filter name now raises
  MissingKeyError instead of substituting a plausible DLT -- the same
  shape as the two existing markers at AppType.get (1.5.0.rst:2456) and
  the four .get()-backed enum fields (1.5.0.rst:2720). Restructured to
  lead with the marker and the subject, matching their wording and
  placement; the later restatement of the same fact is dropped.

None of these are code or test changes -- prose only, matching the
cross-review's own framing. #848 stays unmarked (its own "Not breaking"
paragraph holds); #838, #849 and #853 stay unmarked per explicit
instruction not to add markers beyond what was asked.
JarryShaw added a commit that referenced this pull request Sep 27, 2026
util/changelog_md.py regenerated from 1.5.0.rst after the #838/#846/#850
corrections; --check exit 0.
JarryShaw added a commit that referenced this pull request Sep 27, 2026
…g claim

The previous fix qualified "Only ... change" but dropped the two file
names it was qualifying, leaving "these two" with no antecedent -- a
grep for test_engine_runtime and test_engine_parity over the whole file
returned nothing. Restored the names: "Only
tests/integration/test_engine_runtime.py and test_engine_parity.py change
among the test files".

Also softened "(0 hits for tshark anywhere in that job's log)" -- nobody
had actually read that CI log, on this pass or the last. Checked what is
verifiable instead: 30bca99's diff shows the pypcap-parity job's
apt-get install step named packages "build-essential libpcap-dev" before
this change and "build-essential libpcap-dev tshark" after, so the entry
now says its apt-get install step named no tshark package -- true by the
diff alone, no log read required.
JarryShaw added a commit that referenced this pull request Sep 27, 2026
…ence fix

util/changelog_md.py regenerated from 1.5.0.rst; --check exit 0.
JarryShaw added a commit that referenced this pull request Sep 28, 2026
engine='pyshark' had no CI job driving it through a real tshark-parsed
capture: pypcap-parity installed pyshark but not tshark, so
PyShark.unsupported_reason() declined the engine, the extractor fell back
to the built-in parser, and the one real-extraction assertion passed
against the fallback's output -- a vacuous pass invisible in every skip
count.

pypcap-parity now installs tshark with the same debconf pre-seed
engine-tests already carries, and the test proves which engine actually
ran rather than trusting the assertion alone.
JarryShaw added a commit that referenced this pull request Sep 28, 2026
Adds util/pyshark_encap_map.py, a generator that regenerates
ENCAP_TYPE_TO_LINKTYPE (152 entries) and FILTER_NAME_TO_LINKTYPE (58) in
place inside pcapkit/toolkit/pyshark.py, so the two tables #850 hand-built
stop being hand-maintained. Guards against its own worst failure mode: a
naive LinkType(dlt) lookup cannot detect an unmapped DLT, because
_missing_ mints a placeholder rather than raising, so the generator
snapshots every known value before any lookup.

The real-tshark sweep is gated on a new HAS_WIRESHARK flag and is
version-pinned -- editcap -T accepts 226 encapsulations on Wireshark
4.6.9, 224 on 4.2.2 (CI's Ubuntu noble) -- so the count assertions run
only under the measured version. One line of pyshark.py itself changes as
a result: the IPMB_LINUX table entry becomes I2C_LINUX, the canonical
name #848 gave value 209.

util/changelog_md.py regenerated CHANGELOG.md for all seven entries added
across this and the six preceding commits (#838, #846, #847, #848, #849,
#850, #853); `--check` exit 0.
JarryShaw added a commit that referenced this pull request Sep 28, 2026
#846 and #850

- #838's "the 21 whose vendor crawler leaves Vendor.process() unmodified"
  measures 22, not 21 -- pcapkit.const.hip.transport.Transport also has an
  unmodified process(), but its FLAG-bound range has no unassigned gap, so
  its _missing_ carries no bounded-range extend_enum branch to fix. The
  real discriminator is that branch, not the process() override; reworded,
  and the "other 84" split into the 83 that do override process() and the
  one that doesn't but has nothing to fix either. Re-derived independently
  against 5e25db2^..5e25db2 (not main, which would fold in #847's own
  edit to ipx/socket.py): 22 registries have no process() override, 21 of
  them have the bounded-range branch, matching
  tests/const/test_const_enum_no_mint.py's own REGISTRIES_WITH_UNASSIGNED_RANGES
  (21 entries) vs ALL_REGISTRIES (22, +hip.transport, with a NOTE explaining
  the exclusion).

- #846's "Only tests/integration/test_engine_runtime.py and
  test_engine_parity.py change" is false -- 30bca99's own numstat also
  touches .github/workflows/unit-tests.yml (17+/2-). Qualified to "only
  these two test files change".

- #850 gets the breaking marker: its own prose already says the fallback
  is gone and an unrecognised encapsulation or filter name now raises
  MissingKeyError instead of substituting a plausible DLT -- the same
  shape as the two existing markers at AppType.get (1.5.0.rst:2456) and
  the four .get()-backed enum fields (1.5.0.rst:2720). Restructured to
  lead with the marker and the subject, matching their wording and
  placement; the later restatement of the same fact is dropped.

None of these are code or test changes -- prose only, matching the
cross-review's own framing. #848 stays unmarked (its own "Not breaking"
paragraph holds); #838, #849 and #853 stay unmarked per explicit
instruction not to add markers beyond what was asked.
JarryShaw added a commit that referenced this pull request Sep 28, 2026
util/changelog_md.py regenerated from 1.5.0.rst after the #838/#846/#850
corrections; --check exit 0.
JarryShaw added a commit that referenced this pull request Sep 28, 2026
…g claim

The previous fix qualified "Only ... change" but dropped the two file
names it was qualifying, leaving "these two" with no antecedent -- a
grep for test_engine_runtime and test_engine_parity over the whole file
returned nothing. Restored the names: "Only
tests/integration/test_engine_runtime.py and test_engine_parity.py change
among the test files".

Also softened "(0 hits for tshark anywhere in that job's log)" -- nobody
had actually read that CI log, on this pass or the last. Checked what is
verifiable instead: 30bca99's diff shows the pypcap-parity job's
apt-get install step named packages "build-essential libpcap-dev" before
this change and "build-essential libpcap-dev tshark" after, so the entry
now says its apt-get install step named no tshark package -- true by the
diff alone, no log read required.
JarryShaw added a commit that referenced this pull request Sep 28, 2026
…ence fix

util/changelog_md.py regenerated from 1.5.0.rst; --check exit 0.
@JarryShaw JarryShaw added this to the 1.5 milestone Oct 6, 2026
@JarryShaw JarryShaw moved this to Done in PyPCAPKit Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci Pull requests that change CI or workflow configuration (ci: subject prefix) test Pull requests that add or correct tests (test: subject prefix)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant