修复 Studio 失败测试并新增合并门禁
把丢失的 box 录像放回 apps/studio/tests/data/,修掉第 3 节 3–10 号与两处过时测试桩, 注册 timing 标记并让根目录收集零错误;新增 tools/gate.ps1 与可选的 pre-push 钩子。 验证:studio 524 通过 19 跳过、shared 467 通过 18 跳过、ui_check 632 项 0 失败、gate.ps1 退出码 0。 细节见 docs/test-repair-plan.zh.md。
This commit is contained in:
@@ -13,12 +13,13 @@ What is being defended, in the order the plan asked for it:
|
||||
5. **frames are addressed by id.** An id the recording does not hold is refused, never
|
||||
coerced into an index.
|
||||
|
||||
The fixtures use real footage — the 33-frame box recording under ``dist/`` and the
|
||||
shipped finger configuration — driven through the **finger** chain, which is what gives
|
||||
the result a validity mask and therefore a static candidate grid. The pass is O(5 s)
|
||||
and is shared per module. Where the SDK or the footage is absent the tests skip rather
|
||||
than fake a result: a synthetic result would not defend the id span (20…52), the
|
||||
keyframe identity or the sample round trip.
|
||||
The fixtures use real footage — the 33-frame box recording tracked beside this test
|
||||
(``data/box_short_20260930``) and the shipped finger configuration — driven through the
|
||||
**finger** chain, which is what gives the result a validity mask and therefore a static
|
||||
candidate grid. The pass is O(5 s) and is shared per module. Where the SDK is absent the
|
||||
tests skip rather than fake a result: a synthetic result would not defend the id span
|
||||
(20…52), the keyframe identity or the sample round trip. Where the *footage* is absent they
|
||||
fail, naming the file: a missing input is not an environment that should go green.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -73,16 +74,13 @@ from orisys_studio.replay_analysis import (
|
||||
ResultPolicyError,
|
||||
)
|
||||
|
||||
REPO = Path(__file__).resolve().parents[3]
|
||||
STUDIO = REPO / "dist" / "OrisysStudio"
|
||||
RECORDING = (
|
||||
STUDIO
|
||||
/ "outputs"
|
||||
/ "recordings"
|
||||
/ "20260930T015028Z_session0002_40cb8e7441434feab48bb646afdba011"
|
||||
)
|
||||
FINGER_CONFIG = STUDIO / "config" / "sensors" / "finger" / "sensor.json"
|
||||
FINGER_EXPORT = STUDIO / "config" / "sensors" / "finger" / "assets" / "30fps-0703"
|
||||
#: The tracked test input (``apps/studio/tests/data/README.md`` says where it came from).
|
||||
RECORDING = Path(__file__).resolve().parent / "data" / "box_short_20260930"
|
||||
#: The repository's own sensor configuration. These used to be read from the packaged copy
|
||||
#: under ``dist/``, which a build can delete — the same reason the footage moved here.
|
||||
CONFIG = Path(__file__).resolve().parents[1] / "config"
|
||||
FINGER_CONFIG = CONFIG / "sensors" / "finger" / "sensor.json"
|
||||
FINGER_EXPORT = CONFIG / "sensors" / "finger" / "assets" / "30fps-0703"
|
||||
|
||||
#: The evidence recording's own frame ids. Deliberately not 0…32: an implementation
|
||||
#: that used an index would pass every test written against a 0-based recording.
|
||||
@@ -91,13 +89,22 @@ LAST_FRAME_ID = 52
|
||||
|
||||
|
||||
def _require_inputs() -> None:
|
||||
"""The footage is committed, so its absence is a failure rather than a skip."""
|
||||
missing = [
|
||||
str(path)
|
||||
for path in (RECORDING / "frames.csv", RECORDING / "raw_0001.mp4", FINGER_CONFIG)
|
||||
for path in (
|
||||
RECORDING / "frames.csv",
|
||||
RECORDING / "raw_0001.mp4",
|
||||
FINGER_CONFIG,
|
||||
)
|
||||
if not path.exists()
|
||||
]
|
||||
if missing:
|
||||
pytest.skip("analysis inputs are not present: " + ", ".join(missing))
|
||||
assert not missing, (
|
||||
"analysis inputs are missing: "
|
||||
+ ", ".join(missing)
|
||||
+ ". The recording is committed (apps/studio/tests/data/README.md); restore it "
|
||||
"rather than skipping."
|
||||
)
|
||||
pytest.importorskip("orisys", reason="the SDK is needed to run the analysis pass")
|
||||
|
||||
|
||||
@@ -479,6 +486,11 @@ class _Host:
|
||||
if paint_2d:
|
||||
from orisys_app_shared.acquisition.image_backend import ImageFrame
|
||||
|
||||
# The fields the window's own sink puts on the frame it draws
|
||||
# (``app_window.py:2835-2851``). ``depth_valid``/``flow_valid`` are what
|
||||
# ``plan_image`` reads to decide whether the frame can be drawn as that
|
||||
# view, so a stub that leaves them out cannot answer "the depth view is
|
||||
# real" — which is exactly what the depth test below asks.
|
||||
self.frames.append(
|
||||
ImageFrame(
|
||||
getattr(packet, "processed_frame", None),
|
||||
@@ -487,6 +499,10 @@ class _Host:
|
||||
valid_mask=getattr(packet, "valid_mask", None),
|
||||
source=image_source or "replay",
|
||||
frame_id=int(getattr(packet, "frame_id", 0) or 0),
|
||||
flow_valid=getattr(packet, "flow_valid", None),
|
||||
flow_frame_id=getattr(packet, "flow_frame_id", None),
|
||||
depth_valid=getattr(packet, "depth_valid", None),
|
||||
depth_frame_id=getattr(packet, "depth_frame_id", None),
|
||||
arrow_policy=arrow_policy,
|
||||
result_available=True,
|
||||
)
|
||||
@@ -1652,6 +1668,8 @@ def test_a_stitch_grid_is_not_painted_onto_the_camera_frame():
|
||||
"""
|
||||
from types import SimpleNamespace
|
||||
|
||||
from orisys_app_shared.analysis.model import Provenance
|
||||
|
||||
class _Reader:
|
||||
complete = True
|
||||
key = "stitch"
|
||||
@@ -1659,6 +1677,14 @@ def test_a_stitch_grid_is_not_painted_onto_the_camera_frame():
|
||||
frame_ids = np.array([1], dtype=np.int64)
|
||||
times = np.array([0.0])
|
||||
keyframes: dict = {}
|
||||
#: A real reader always carries one (``AnalysisReader.__init__`` builds it from
|
||||
#: the result's metadata) and ``AnalysisSession`` reads it: *where* the samples
|
||||
#: are travels from ``provenance.policy``, and the overlay base opens from the
|
||||
#: rest. ``829d2c1`` added those reads; this stub predated them and the default
|
||||
#: ``Provenance()`` is the honest stand-in — an empty policy, so the session
|
||||
#: falls back to the display policy exactly as it does for a result that stored
|
||||
#: no grid.
|
||||
provenance = Provenance()
|
||||
|
||||
def mask(self):
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user