Commit 80f2115a by PLN (Algolia)

midiviz: test the state layer's PIXELS, and name the zero-zone guess

Two gaps in the commit before this one.

`--selftest` writes no state file, so `_paint_state` returned at its first line
through all three themes and all four window shapes. The previous message cited
that PASS next to the new layer, which reads as coverage it did not have: the
drawing had executed in exactly one place, a throwaway script, which is how a
whole layer stays green while never running. There is now a differential render
test — paint offscreen, read the pixels back, assert WHICH SIDE of the detent
filled: left for a low filter, right for a high one, neither for one at rest,
and nothing at all in the five columns this slice does not own.

Getting that test right took three attempts, all three failing on the widget
rather than the layer. Asserting two x positions in a cell are equal is never
safe here — the CRT texture draws vertical lines every few pixels — and the
strip's TRACK spans the full cell, so "this pixel changed" is true across the
whole row regardless of value. The version that holds blits the texture off (the
one overlay not under test) and compares flanks, plus asserts low and high are
mirror images of each other rather than merely different.

Second: the zero zone was a bare `abs(val - 64) <= 2`. It is now ZERO_ZONE, at
module scope, with the reason it is a guess written next to it — rows B/C are
relative and the driver integrates with a clamp (`max(0, min(127, cur + d))`),
so a knob swept to an end and brought back loses every click it spent against
the clamp and settles NEAR 64 rather than on it. Too tight shows a sliver of LOW
where his hand says ZERO; too loose hides a real nudge off centre, which is the
worse failure because the layer exists to stop the picture lying about rest.
Narrow to start, and it wants a hand on the board rather than another argument.

Suites 529 passed, 2 failed (both pre-existing).
parent b9d83bcd
......@@ -505,6 +505,18 @@ def _norm_value(ev: dict) -> int:
# ── the reader ─────────────────────────────────────────────────────────────
STATE_FILE = Path(os.path.expanduser("~/.cache/parvagues/surface-state.json"))
# How close to the centre detent still reads as ZERO.
#
# A GUESS, and the one number on this layer that wants a real hand on the board.
# Rows B/C are relative: the driver integrates `v - 64` and CLAMPS
# (`max(0, min(127, cur + d))`), so a knob swept to an end and brought back
# loses every click it spent against the clamp and settles somewhere near 64
# rather than on it. Too tight and a filter his hand calls ZERO draws a sliver
# of LOW; too loose and a real, audible nudge off centre shows as bypass — which
# is the worse error, since the whole layer exists to stop the picture lying
# about rest. Start narrow, widen only if the board says to.
ZERO_ZONE = 2
class SurfaceState:
"""The resting position of the surface, which the event stream cannot carry.
......@@ -1960,7 +1972,7 @@ def build_widget(port_label: str, reader: "Reader | None", scale: float = 1.0,
# where it RESTS, as a bar growing out of the detent toward the
# side it is filtering: direction says LOW or HIGH, no decoding.
pos = x + round((w - 1) * max(0.0, min(1.0, val / 127.0)))
at_zero = abs(val - 64) <= 2
at_zero = abs(val - 64) <= ZERO_ZONE
fam = FAM_LEVEL if at_zero else FAM_FAMILY
if not at_zero:
lo, hi = (mid, pos) if pos >= mid else (pos, mid)
......
......@@ -206,3 +206,97 @@ def test_the_detent_is_the_seeded_rest_value():
for cc, (role, _) in grid.CC_ROLE.items()}
assert all(seeded[cc] == 64 for cc in (49, 50, 51))
assert seeded.get(29, 0) == 0
# --------------------------------------------------------------------------- #
# the paint path, which "selftest PASS" did NOT cover
# --------------------------------------------------------------------------- #
# `--selftest` writes no state file, so `_paint_state` returned at its first
# line through every one of those themes and shapes. The layer's drawing had run
# in exactly one place — a throwaway script — which is how a whole layer goes
# green while never executing. So: render it for real and read the pixels back.
def _offscreen_widget(mv_mod, state_path, width=1000, height=620):
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
try:
_c, _g, QtWidgets = mv_mod._qt()
except Exception:
return None, None
app = QtWidgets.QApplication.instance() or QtWidgets.QApplication([])
w = mv_mod.build_widget("--", None)
w.state = mv_mod.SurfaceState(state_path)
w.resize(width, height)
w.show()
app.processEvents()
return app, w
def _strip_row(w, col):
"""The y of the state strip, and the x span of `col`'s cell — derived the
same way _paint_state derives them, so a geometry change breaks both."""
chi = max(2, round(w.ch) - w.inset)
ebar = max(2, round(chi * w.theme.bar_frac))
sh = max(3, round(3 * w.dens))
rows = {row: r for r, row in enumerate(grid.PHYSICAL_ORDER)}
y = round(w.my + rows["C"] * w.ch) + chi - ebar - 2 - sh
x = round(w.mx + (col - 1) * w.cw) + 1
return x, y + sh // 2, max(4, max(2, round(w.cw) - w.inset) - 2)
def test_the_strip_actually_draws_and_says_low_zero_high(tmp_path):
"""Three values, three different pictures. The assertion is on PIXELS.
The CRT texture is blitted off for this one. Two earlier versions of this
test failed on it rather than on the layer: it draws vertical lines every
few pixels, so no two x positions in a cell can be assumed equal. Turning
off the one overlay that is not under test is honest — and the no-op test
below still renders the full stack, texture included.
"""
state = tmp_path / "surface-state.json"
state.write_text(json.dumps({"seq": 1, "t": 1.0, "track": "T",
"values": {"49": 4, "50": 64, "51": 123}}))
mv, w = _offscreen_widget(MV, state)
if mv is None:
pytest.skip("no Qt available")
w._scanlines_blit = lambda _p: None
assert w.state.poll() is True
w.repaint()
img = w.grab().toImage()
def ink(col, frac):
x, y, cw = _strip_row(w, col)
return img.pixelColor(x + int(cw * frac), y).name()
# The track spans the whole cell, so "something is drawn" is not the claim.
# The claim is WHICH SIDE of the detent is filled — that is what says LOW
# or HIGH without a number to decode.
#
# gF1 = 4: filled left of the detent, bare track to its right.
assert ink(1, 0.25) != ink(1, 0.75), "gF1 low: no bar left of the detent"
# gF3 = 123: the mirror image.
assert ink(3, 0.75) != ink(3, 0.25), "gF3 high: no bar right of the detent"
# …and they are mirror images of each other, not the same picture twice.
assert ink(1, 0.25) == ink(3, 0.75), "low and high should fill alike"
assert ink(1, 0.75) == ink(3, 0.25), "and leave the other side alike"
assert ink(1, 0.25) != ink(3, 0.25), "low and high draw the same picture"
# gF2 = 64 sits ON the detent: neither flank fills, so they match, and they
# match gF1's bare side — the same track colour.
assert ink(2, 0.25) == ink(2, 0.75), "gF2 at zero drew a bar"
assert ink(2, 0.25) == ink(1, 0.75), "zero's flanks are not bare track"
def test_the_layer_is_a_no_op_without_a_file(tmp_path):
"""The safety property: an older driver, or none, must change nothing."""
mv, w = _offscreen_widget(MV, tmp_path / "absent.json")
if mv is None:
pytest.skip("no Qt available")
w.repaint()
before = w.grab().toImage()
w.state.values = {}
w.repaint()
assert w.grab().toImage() == before
def test_the_zero_zone_is_one_named_tunable():
"""It is a guess about a clamping integrator, so it must be findable."""
assert isinstance(MV.ZERO_ZONE, int)
assert 0 <= MV.ZERO_ZONE <= 8, "a wide zero zone would hide a real nudge"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment