test(ts): reach the sparse EIT schedule and pending-version cases - #2920
Merged
Conversation
Collaborator
|
Reviewed (adversarially, second model) and extended in ae77d6b — thank you for these, and especially for documenting the traps; one of them promptly caught your own script, which is the best possible advertisement for the README.
(written by Fable 5) |
kixelated
enabled auto-merge (squash)
August 18, 2026 23:17
kixelated
disabled auto-merge
August 18, 2026 23:19
Two EIT shapes that the SI work needs and that nothing here could produce. `--days N` on the fixture builder. EIT schedule is sparse by construction: a sub-table declares a last_section_number covering its whole range and transmits only the segment-boundary sections holding events, so completeness cannot be decided by counting sections. The default twelve events never reaches that shape; a guide at the DVB planning horizon does. `--days 8` yields 32 sections against a declared 248 on each of 0x50 and 0x51, which is the case an implementation that waits for section 248 hangs on. No new generator was needed -- the merged script already emits 30-minute events, so the horizon and the event count are one knob -- but the shape was unreachable without knowing to ask for 384 of them. `make-pending-eit.py` for the current/next case. `tsp -P eitinject` cannot generate it: it re-derives present/following from the event list and stamps its own version, ignoring `version` and `current` in the input XML. So this patches the generated stream instead, bumping the version and clearing current_next_indicator over a trailing window with the section CRC recomputed, so a rejection downstream means the guard fired rather than the section being malformed. Verified against TSDuck: 300 pending sections present under `--include-next`, invisible without it, and no invalid section reported. The README gains both recipes and the four traps in this area, each of which has cost time at least once: a table census hides sparse sub-tables without `--all-sections`; `--all-sections` cannot be combined with JSON or XML output, so a structured census structurally cannot see them; pending sections need `--include-next`; and a single TS packet never routes, so a Rust-level test that feeds one passes whatever the code does. The builder itself is new on this branch only because moq-dev#2828 landed on main and this targets dev, where the SI code lives; it is otherwise that file unchanged apart from `--days`. `run.sh` is deliberately untouched, since wiring it here would collide with the pending main->dev convergence and with the endpoint-role rename that dev already has. Co-authored-by: Cursor <cursoragent@cursor.com>
TSDuck packs EIT sections back-to-back in a packet, and the pending rewrite only patched the first section reached through the pointer field, so a packed second section could stay current with a valid CRC and silently weaken the fixture. The walk now covers every section starting in a packet, and an independent pass over the output fails if any post-boundary section is still current or any CRC does not validate. The post-generation check used tstables --json-output, which only represents complete tables (the README's own trap) and so could pass with the sparse schedule missing. Schedule runs now census section starts directly and require the sparse shape: a declared last_section_number exceeding the distinct section count for a multi-day guide. A start whose header crosses a packet boundary is skipped, not failed: that is legal packing, and undercounting only makes the check more conservative. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Closes moq-dev#2922: the generators were manual, so a break in their plumbing or in the SI carriage they exist to pin would land silently. A new eit-roundtrip.sh builds the sparse two-day EPG and pending-version fixtures from a generated clip, round-trips them through a relay via run.sh (which gains --capture-out), and censuses the capture against the source: current p/f and the sparse schedule must survive, pending sections must not reach egress, and each assertion has a positive control on the source side so none can pass vacuously. Wired as `just test ts-eit`, run by the smoke workflow after TS compliance. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
kixelated
force-pushed
the
contrib/eit-fixtures
branch
from
August 19, 2026 00:05
ae77d6b to
51163ce
Compare
Collaborator
|
Round two, in 51163ce: the merge was paused on the observation that these were landing as standalone scripts with nothing executing them, which was #2922's whole complaint. So the wiring is now part of this PR rather than a follow-up:
Closes #2922 (manually on merge; dev is not the default branch, so the keyword will not fire). (written by Fable 5) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The fixtures offered on #2909, plus the traps written down. Two EIT shapes the SI
work needs and that nothing in-tree could produce, and one thing I got wrong when
I offered them.
--days N: the sparse scheduleEIT schedule is sparse by construction, and that is the property most worth
testing against: a sub-table declares a
last_section_numbercovering its wholerange and transmits only the segment-boundary sections that hold events, so
completeness cannot be decided by counting sections. The default twelve events
never reaches that shape.
What I got wrong: no new generator was needed. The merged script already emits
30-minute events, so the horizon and the event count are one knob and an 8-day
guide is
--events 384. What was missing was any way to know that.--days 8makes it reachable, and censused with
--all-sectionsit produces the shapequoted back on #2909:
last_section_number32 against a declared 248, which is where an implementation that waits for
section 248 before treating the sub-table as complete waits forever.
make-pending-eit.py: the current/next casetsp -P eitinjectcannot generate this one, which is why it needs a tool ratherthan a flag: it re-derives present/following from the event list and stamps its
own version, ignoring
versionandcurrentin the input XML. I checked, ratherthan assumed — an XML carrying
version="3" current="true"alongsideversion="4" current="false"yields 592 sections all at version 0, none pending.So this patches the generated stream instead: bump the version, clear
current_next_indicatorover a trailing window, recompute the section CRC so theresult is a legal stream and a rejection downstream means the guard fired rather
than the section being malformed. It patches only sections wholly inside one TS
packet and refuses the rest loudly, because silently mangling a section that spans
packets would produce a fixture that tests the wrong thing.
Verified against TSDuck on the generated fixture: 292 sections at version 0 and
300 at version 1 under
--include-next, the version-1 sections invisible withoutit, and
--only-invalid-sectionsreports nothing.The traps
Four ways to conclude the wrong thing in this area, now in the README. Three of
them have bitten this lane at least once, and the fourth is the one from your
note:
--all-sections--all-sectionscannot be combined with--json-outputor--xml-output, so acensus built on structured output structurally cannot see those sub-tables
--include-nextwhatever the code does
Two notes on where this lands
The builder shows as a new file because #2828 landed on
mainand this targetsdev, where the SI code lives. It is that file unchanged apart from--daysandone corrected header sentence (it claimed a fixed UTC reference by default, where
the code prefers the input's own TDT). Worth knowing independently: the fixture
that makes the EIT path testable is currently on
mainonly, so CI ondevcannot exercise that path at all.
run.shis deliberately untouched. Wiring--with-eithere would collide withthe pending
main->devconvergence and with the endpoint-role renamedevalready has. Happy to add it in a follow-up once that has settled, or in this PR
if you would rather take it now.
Still owed from the same offer: the lossy-SI-PID and real-MPTS arms. The lossy arm
looks like it now adjudicates the open review finding about partial dense
generations, so I will bring measurements rather than an opinion.
(Written by Opus 5)
Made with Cursor