test: a probe reads the hidden tab's accumulator, and the docs follow the tabs
`UDPSCOPE_PROBE_SIDE_TAB_MS` is the one reading for the design's §5 rule -- the statistics accumulator keeps running on the hidden page -- which nothing tested before. It switches to Measure, forces one pass so there is a baseline, switches away to Signals and reads again two seconds later: `advanced=4` is the assertion, and `advanced=0` is the defect where the accumulation is gated on the visible tab, which would leave a gap in min/max/avg for exactly as long as the trigger was on screen. Two things the probe has to do for itself, and getting either wrong makes `advanced=0` a lie about the tab: - it **enables its own signal**, because a signal starts disabled (enabling is what starts acquisition) and a probe that waited for one to be on would be reading another probe's side effects -- and `UDPSCOPE_ENABLE_ALL_MS` is not part of this run; - it **assigns that channel to a plot**, because a channel with no trace leaves the live window *still*, and a still window is precisely the state `update_measures()` is supposed to skip. Measured the hard way: without the assignment the probe read `advanced=0 min_n=0` with the view pinned and only four passes in twelve seconds, none of them the tab's doing. Docs: `probe-readings.md` gains the probe's entry and the signals panel's new shape (`rows == signals + 1 + math`, `divider=0` a list that lost its `+`), loses the whole `math panel:` entry, and follows `pane_sensitive=`, the gone `revealed=` field, the six toolbar controls and the tab-reading `m`/`g` key pairs. `verification.md` gains the probe's bullet and the re-measured warning figures. The invariants record the sidebar as a switcher above a stack with a scroller per page, the hidden-page trap that replaces the unrevealed-revealer one for it, that a feature's on/off is sensitivity rather than visibility, that a math channel is a row of the signal list, and that a cursors-off readout blanks to `--` with the panel left on screen. `shortcuts.ui` and the help page's window and sidebar bullets stop describing five revealers. The README records the deviation from `SPECS.md` that names the panes as separate collapsible sections. Verified: `[side-tab-probe] page=signals rows=4 accums=4 advanced=4 min_n=16`; `signals panel: labels=2 list=1 rows=9 signals=4 math=4 divider=1`; `panels: … (page_current=1) (sensitive=0) switcher=1`; `toolbar icons:` six controls with every name `(ok)`, with the Preferences dialog opened in the same run; zero `Gtk-CRITICAL` and no missing icon.
This commit is contained in:
1 parent
cb866774c6
commit
6492bb910f
9 files changed
+197
-41
No files matched your search
@@ -161,10 +161,12 @@ Two lines of the self-check output are assertions in disguise:
|
||||
*adoption* half -- a gesture that does move a cursor, and the shared value reaching every row
|
||||
-- is asserted in the `check_host` harness, which can call `sync_cursors(row)` directly; a
|
||||
synthetic press here cannot reach the adapter's own event pump.)
|
||||
- `[cursors-probe] <action> mode=.. on=D pane=D t0=.. t1=.. dt=.. T=[..] lines=N [..]`
|
||||
- `[cursors-probe] <action> mode=.. on=D pane_sensitive=D t0=.. t1=.. dt=.. T=[..] lines=N [..]`
|
||||
(stderr, `UDPSCOPE_PROBE_CURSORS_MS`) — walks `vertical` → `horizontal` → `both` →
|
||||
`mix`, then moves a marker *through the plot* (`Plot::set_cursor_x(..., Free)`, which is
|
||||
what a drag does) and reports again. **The times must survive every mode change**: they
|
||||
what a drag does) and reports again. `pane_sensitive` is the cursors *panel's* sensitivity, not a
|
||||
revealer's child: with the cursors off the panel stays exactly where it is and its cells blank to `--`,
|
||||
because a readout whose instruments are off has no sample to quote. **The times must survive every mode change**: they
|
||||
are the `RowSet`'s one pair, and a mode that parks the markers must not read them back
|
||||
(a parked cursor reports a real number, so a read-back would adopt it as a gesture — the
|
||||
bug that made `T0` read 0). **`lines`** must be 0 for `vertical`, one per row for
|
||||
@@ -195,7 +197,7 @@ Two lines of the self-check output are assertions in disguise:
|
||||
numbers and the plot's state agreeing is the difference between "the app placed them" and
|
||||
"the app placed them and they are on screen".
|
||||
- `[measures-probe]` + the dump's `measure N: 'sig' type thr=..% above=D show=D -> ok|invalid value text=[..]
|
||||
[duty=..] [marks=..]` and `measures pane: n=N revealed=D marks_shown=M pane_rows=R pane_w=W
|
||||
[duty=..] [marks=..]` and `measures pane: n=N marks_shown=M pane_rows=R pane_w=W
|
||||
pane_h=H switch_on=X reset_sensitive=Y`
|
||||
(stderr, `UDPSCOPE_PROBE_MEASURES_MS`) — adds one measurement of every type on the first
|
||||
plottable signal and lets the tick compute them, so what it prints is what a user reads.
|
||||
@@ -345,9 +347,9 @@ Two lines of the self-check output are assertions in disguise:
|
||||
and an expanding one is measured into the title's centre box, so it stretched from the
|
||||
label to the title (516 px at a 1270 px bar before the fix, 121 px after). A `W` that
|
||||
grows with the window width is that bug back.
|
||||
- `toolbar icons: trigger=NAME(ok) pause=... cursors=... measures=... math=... sidebar=...
|
||||
menu=...` (in the exit dump, beside `panel controls:`) — the icon name every toolbar button
|
||||
carries, with `gtk_icon_theme_has_icon()`'s verdict. **Every entry must read `(ok)`.** Four
|
||||
- `toolbar icons: trigger=NAME(ok) events=... pause=... cursors=... sidebar=... menu=...` (in the
|
||||
exit dump, beside `panel controls:`) — the icon name every toolbar button
|
||||
carries, with `gtk_icon_theme_has_icon()`'s verdict. **Every entry must read `(ok)`.** Three
|
||||
of the names are this app's own (`udpscope-trigger-symbolic` and friends, a `GResource`
|
||||
compiled into the binary — see the toolbar-icon invariant in
|
||||
[invariants-gtk-and-chrome.md](invariants-gtk-and-chrome.md)), and a `(MISSING)` on one of
|
||||
@@ -598,7 +600,7 @@ two also catch a row whose accelerator went missing. `settings=` must be a real
|
||||
every row then reports `h=0`. It turns autohide off for its own measurement — a popover dismisses
|
||||
itself when it loses the grab, and `xvfb-run` has no window manager to hand it one — and restores
|
||||
it afterwards.
|
||||
- `[keys] a: armed 0->1 | space: paused 0->1 | t: trigger panel: 0->1 | … | editable focused: 'm' refused=1` (stderr, `UDPSCOPE_PROBE_KEYS_MS`) — **every `X->Y` pair must differ** and **`refused` must be 1**. The refusal is the whole reason the controller is in the bubble phase: every bare-letter accel is also a character, so an accel that fires while a `GtkEditable` has focus makes the window entry unusable. A pair reading `0->0` is an action whose dispatch does not reach the handler a click reaches. Note the format is `<key>: <widget-description>: <before>-><after>` — the name passed to `before_after()` includes the widget's description, so `t: trigger panel: 0->1` is the correct form (not `t: trigger panel 0->1` without the colon before the values).
|
||||
- `[keys] a: armed 0->1 | space: paused 0->1 | t: trigger panel: 0->1 | c: cursors: 0->1 | m: tab signals->measure | g: tab measure->signals | … | editable focused: 'm' refused=1` (stderr, `UDPSCOPE_PROBE_KEYS_MS`) — **every `X->Y` pair must differ** and **`refused` must be 1**. The `m`/`g` pairs are the *tab name* before and after, which is what says those two keys select a tab rather than toggling a pane; `t`/`c` read the toolbar toggle's own state, because those two enable a feature and the button is where that state is visible. The refusal is the whole reason the controller is in the bubble phase: every bare-letter accel is also a character, so an accel that fires while a `GtkEditable` has focus makes the window entry unusable. A pair reading `0->0` is an action whose dispatch does not reach the handler a click reaches. Note the format is `<key>: <widget-description>: <before>-><after>` — the name passed to `before_after()` includes the widget's description, so `t: trigger panel: 0->1` is the correct form (not `t: trigger panel 0->1` without the colon before the values).
|
||||
- `[color] '<name>' at row R slot S: trace=#RRGGBB chip_agrees=1 (want 1)`, then `[color] override: trace=#123456 chip_agrees=1`, `[color] session: entries=1 rgb=#123456` and `[color] default: trace=#RRGGBB chip_agrees=1` (stderr, `UDPSCOPE_PROBE_COLOR_MS`) — **all three `chip_agrees` must be 1**, the override line's `trace` must be `#123456`, the session line must read `entries=1 rgb=#123456`, and the default line's `trace` must be back to the first line's. Run it with `UDPSCOPE_ENABLE_ALL_MS` ahead of it, or there is no bound trace and the probe prints `no bound trace to recolour` instead of asserting anything; on the standard mock the first line reads `'sine' at row 0 slot 0: trace=#4FA3FF`. Two things make this an assertion rather than a tautology. The colours are read out of **`plot::Plot::trace().color`** — what the renderer will stroke, reached through `Row::plot` *after* `relayout_areas()`, since a new colour is a new figure — and out of the chip's own `<span foreground="…">` markup, not by asking `RowSet::signal_color()` twice, which would pass against a chip that never reached the trace. And the override is `#123456`, deliberately in no palette slot: an override equal to the entry it replaces passes against an implementation that ignores overrides entirely. The session leg round-trips `collect_layout()` → `save_layout()` → `load_layout()` on a temp path and deletes it, because a probe must not leave a colour in the real session file for a later run to inherit.
|
||||
- `[reseq-probe] reseq=N late=N stale=N overflows=N holes=N hole_slots=N backfilled=N
|
||||
open_holes=N bands=N bands_repaired=N nan_slots=N scanned=N trigger_in_hole=D` (stderr,
|
||||
@@ -1144,6 +1146,30 @@ and `regained` reads 400 ms later.
|
||||
- `collapsed=1` means the window is narrower than `kSidebarRoom` (900), which is the expected reading on a
|
||||
scaled display, where the logical width is half what the screen looks like.
|
||||
|
||||
## `[side-tab-probe]`
|
||||
|
||||
```
|
||||
[side-tab-probe] page=signals accums=4 baseline recorded
|
||||
[side-tab-probe] page=signals rows=4 accums=4 advanced=4 min_n=18
|
||||
```
|
||||
|
||||
`UDPSCOPE_PROBE_SIDE_TAB_MS` is the one reading for the rule that **the statistics accumulator keeps running
|
||||
on the hidden page**. It switches *to* the Measure tab, forces one pass so there is a baseline, then switches
|
||||
away to Signals and reads again two seconds later -- with the measurements' page not current, so its widgets
|
||||
are unrealized and measure 0x0.
|
||||
|
||||
- **`advanced=4` is the assertion**: every accumulator gained passes while its page was off screen, and
|
||||
`min_n` (the smallest `n` seen) must be non-zero too. **`advanced=0` is the defect**: something gated the
|
||||
accumulation on the visible tab, so the readout would gain a gap in its min/max/avg for exactly as long as
|
||||
the trigger was on screen. A `Gtk-CRITICAL` here is the other half of the same rule -- a label or an
|
||||
allocation read on the unrealized page.
|
||||
- The probe enables a signal **and assigns it to a plot** itself, both deliberately. A signal starts disabled
|
||||
(enabling is what starts acquisition), and a channel with no trace leaves the live window *still* -- and a
|
||||
still window is the state `update_measures()` is *supposed* to skip, so a probe that left it that way would
|
||||
read `advanced=0` for a reason that has nothing to do with the tab.
|
||||
- `rows` is the measurement count and `accums` the accumulator count; the two must agree, because one
|
||||
accumulator per measurement row is what makes `advanced` a statement about every row.
|
||||
|
||||
## `[prefs-probe]`
|
||||
|
||||
```
|
||||
@@ -1252,25 +1278,20 @@ the two lines together read what the file gave and what the code put in it.
|
||||
## `signals panel:`
|
||||
|
||||
```
|
||||
[udpscope] signals panel: labels=2 list=1
|
||||
[udpscope] signals panel: labels=2 list=1 rows=5 signals=4 math=0 divider=1
|
||||
[udpscope] signals panel: labels=2 list=1 rows=9 signals=4 math=4 divider=1
|
||||
```
|
||||
|
||||
The signals panel's frame read from the window: the heading and the hint the `.ui` gives it, and the list
|
||||
the rows go in. `labels=1` is a `.ui` that lost one of the two, `list=0` one that lost the list -- both of
|
||||
which otherwise show as a panel quietly missing a piece. `panels: … signals=WxH row_h=26` is the other half:
|
||||
the list's own geometry and the height a row really takes, which is what the compact-row CSS rule is for.
|
||||
|
||||
## `math panel:`
|
||||
|
||||
```
|
||||
[udpscope] math panel: head=2 buttons=1 list=1 title='Math channels'
|
||||
```
|
||||
|
||||
The math panel's frame read from the window: the head row the `.ui` gives it (the title and the add
|
||||
button), and the list the channel rows go in. `buttons=0` is a `.ui` that lost the `+` -- a panel that
|
||||
cannot add a channel, with nothing else complaining -- and `title=` is the file's own text read back, so a
|
||||
`.ui` that lost the label shows as `title='-'`. `[math-probe]` is the other half of the reading: it drives
|
||||
the add and the editor through the same code a user does.
|
||||
The signals panel's frame read from the window, and in the same line the *shape* of the one channel list:
|
||||
the heading and the hint the `.ui` gives it, the list the rows go in, how many rows that list holds
|
||||
(`rows`), how many of them are streamed signals (`signals`), how many math channels the app has (`math`),
|
||||
and `divider`, which is 1 when `rows == signals + 1 + math` and 0 otherwise. `labels=1` is a `.ui` that lost
|
||||
one of the two labels, `list=0` one that lost the list -- both of which otherwise show as a panel quietly
|
||||
missing a piece -- and **`divider=0` is the merged list that lost its `+`**, the one control that can create
|
||||
a math channel. The first line above is a run with no math channels at all: the divider is there anyway,
|
||||
because a `+` that only appeared once a channel existed could never create the first one. `panels: …
|
||||
signals=WxH row_h=26` is the other half: the list's own geometry and the height a row really takes, which
|
||||
is what the compact-row CSS rule is for.
|
||||
|
||||
## `events pane:`
|
||||
|
||||
|
||||
Reference in new issue
Block a user