Skip to content

08 — Test coverage (behavioral)

No line/branch % claimed — no coverage tool is wired. This page is the definitive behavioral FEATURE × TEST matrix from the live tree: what is tested, where, and how. Gate wiring (lefthook, ctest registrations) lives on quality-gates.md and is only referenced, not repeated.

Dual harness (+ script gates)

Harness Source Runner Count (this refresh)
C++ Catch2 src/Engine/tests/engine_tests.cpp ctestNPSEngineTests 93 TEST_CASEs (76 TEST_CASE + 17 TEST_CASE_METHOD)
C# xUnit tests/NPSEngine.Tests/*.cs (12 files) dotnet test 158 attributes (154 [Fact] + 4 [Theory], all Theories in EngineBridgeTests.cs) → 163 test cases after Theory row expansion
Script fitness scripts/*.sh lefthook pre-push + ctest layer-fitness (live), no-placeholder-scan (live), fixture-present (live), docs-deploy (live), structural-fitness (disabled), smoke-apps (disabled), production Test*-gate (ctest-only)

HOW legend — golden = real Benchy fixture with hard asserts; synthetic = embedded gcode/XML/temp files; crafted = byte-patched ZIP; bridge = P/Invoke into the real libNPSEngine.so; headless = Avalonia.Headless real controls; logic = pure managed math; ABI smoke = entry-point call without semantic assert; structural = grep/nm/script scan.

Golden fixture

4-colors+Benchy+AMS+test-v2.3mf (repo root) = 1 plate / 16562 vertices / 33097 triangles / 4 palette colors (0xFFC12E1F, 0xFFFEC600, 0xFF00AE42, 0xFF0A2989). Constants pinned at engine_tests.cpp:97-98; resolver ResolveBenchyPath() (:106), RAII BenchyFixture (:143). The fixture-present pre-push hook (lefthook.yml:139-140) refuses to push without it — there is no synthetic fallback for loader tests.

Consumers (hard golden asserts, not smoke):

Harness Tests
C++ load :291/:1096; ZIP :343/:1106; mesh query :378; BenchyFixture suite :625/:634/:642 (exact palette)/:655 (first-vertex transforms)/:678 (bounds); metadata-only :710; missing-entry ZIP :1060; bounds overload :4760; viewport/warp :1798; perf :2025; render SHA :2650; gen+analyze :2772-:3149
C# EngineBridgeTests.cs:298 (full contract via Marshal.Copy), :607, :675, :750, :1014, :1065 (unsafe reads), :2214 (SHA parity); EngineSessionTests.cs:95,:142,:166,:185,:211; MeshControllerTests.cs:51,:91; ViewportControllerTests.cs:460,:509

Test-hook-gated exports (why they exist)

NPS_ENABLE_TEST_HOOKS (src/Engine/CMakeLists.txt:31, auto-ON when BUILD_TESTING=ON at :50-60, defined at :212-213) compiles extra C ABI entry points that let both harnesses drive internals without exposing them in production: TestParseModelXmlForHarness, TestZipReaderExtractModelAndMetadata, TestZipReaderDirectError, TestGetPlateThumbnailSize, GetMeshBounds (abi/nps_c_api.h:247-274), TestGcodeParseForHarness, TestThermalGridForHarness, TestStructuralScoreForHarness, TestAnalysisManagerThermal (:398-411). GetMeshBounds is test-gated because no app/C# consumer exists — production computes bounds from the vertex stream. The production gate (nps-n1m-12-production-gate.sh) asserts zero Test* symbols via nm -D; see quality-gates.md for why that gate never runs inside lefthook (hooks always build Debug+tests).

Feature × test matrix

C++/C# cells give line anchors (engine_tests.cpp / the named C# file).

Load / 3MF / ZIP

Feature Where C++ C# Scripts HOW Verdict
3MF load end-to-end engine.cpp:540/550 :291,:1096,:625,:634 EngineBridgeTests:298,:607; EngineSessionTests:95 fixture-present golden covered
ZIP/OPC reader engine_zip.cpp :343,:1106 indirect via load tests golden + Test* hooks covered (C++); partial C# (indirect only)
ZIP error paths (EOCD/truncated/sig/compression/deflate/missing/stored-size/null) engine_zip.cpp Zip error suite :969-:1088 (8 cases: 7 ZipReaderFixture + null-args plain TEST_CASE at :1088) only EngineBridgeTests:471 (magic/empty/size) crafted byte-patched ZIPs covered (C++); partial C#
3MF XML parser engine.cpp:2084/2325/2472 :1182,:1210,:1228,:1244 synthetic real-derived XML covered (C++ only)
Mesh queries (verts/tris/colors/plates/unit) engine.cpp:988-1109 :378,:655 EngineBridgeTests:298,:1065 golden, exact counts+samples covered
Mesh bounds (AABB) engine.cpp:1059/1077 :533,:678,:4760 — (test-gated export, by design) golden via test-gated export covered (C++); N/A C#
Palette decode (4-color AMS) engine_color.cpp :642 exact hex EngineBridgeTests:298; MeshControllerTests:51 golden exact-hex covered
Plate thumbnail engine.cpp:1116 size>1000B inside :378 golden, SIZE-only partial — PNG content never verified
Multi-plate / multi-object engine.cpp:885 hardcodes plate_1 no multi-plate fixture exists NOT TESTED (feature single-plate by design; deferred — tracked by bead nps-ai2.3, documented per nps-oro.6)
Loader error model engine.cpp:550-970 :728,:747,:820 EngineBridgeTests:452,:471,:561; EngineSessionTests:127 synthetic temp files + C ABI covered

G-code generation & parsing

Feature Where C++ C# Scripts HOW Verdict
GenerateGcode (demo toolpath, not slicing) engine.cpp:1215 :2772,:2871,:3014 EngineBridgeTests:750; EngineSessionTests:166 golden + demo gen covered (as demo toolpath)
Gen errors + C ABI buffer/file roundtrip engine.cpp:1593/2947-3028 :2934,:2963 synthetic + golden + ABI covered (C++); partial (no C# gen-error cases)
Real slicing (slice/ module) does not exist (engine.h:155) N/A — feature not implemented
Text gcode parse (layers, M82/83, G92, M204, arcs, Bambu markers) engine.cpp:3621 :1294,:1350,:1375,:1402,:1414,:3412 EngineBridgeTests:642 synthetic via Test*; optional real file covered
bgcode binary parse engine.cpp:3407/4049 :1513 (skips if fixture absent) EngineBridgeTests:829 (hard-requires, >1000 moves, maxL≥249) real test_cube_binary.bgcode covered — happy path + corrupt block CRC (byte-patched real fixture → warn-and-continue, EngineBridgeTests:1904, nps-oro.6)
Parsed/generated text split engine.cpp:1436/1453 :1451 EngineBridgeTests:929 synthetic via C ABI, sentinels covered
Move array (shared after gen or parse) engine.cpp:1460/1464 inside :1451,:2772,:2963 EngineSessionTests:142,:166 bridge pointer+count covered
Parser robustness (null/empty/long-line/malformed metadata/false banners) engine.cpp:4011 :3602-:3750 (8 cases) EngineBridgeTests:1576 (Theory, empty only) synthetic adversarial covered (C++ deep; C# one row)

Analysis & material

Feature Where C++ C# Scripts HOW Verdict
Thermal analyzer engine.cpp:4323 :1554 (golden: score == totHeat == 0.04, findingCount == 1 on pinned 3-move input, nps-oro.5), perf :1968 EngineBridgeTests:656 synthetic; golden derived from ThermalAnalyzer::analyze math covered
Structural analyzer engine.cpp:4653 :1594 (golden values on pinned 10-move input, nps-oro.5) EngineBridgeTests:656 synthetic; golden derived from StructuralAnalyzer::analyze math covered
Motion analyzer (junction velocity) engine.cpp:4806 :1640 (golden: tiny 2-move + cube junction-clamp at 14.4, nps-oro.5), E2E :1749; inferProfileFromGcode real M204 P/T/S inference :4096 (nps-ai2.2) via EngineBridgeTests:675 golden analyzer unit tests covered
Hole findings engine.cpp:6724 :3130 ("diameter" in message) indirect via EngineBridgeTests:1474 golden + demo gen covered
Retraction + stringing engine.cpp:6957 :3174 EngineBridgeTests:1639 (parity with C++ fixture: real messages + overlays, nps-oro.6) synthetic gcode covered
Flow + volumetric overlays engine.cpp:7041 :3149,:3775 (108B POD, cap 7.5) EngineBridgeTests:1351 golden + synthetic + ABI covered
Material catalog (10 rows, PLA fallback, key normalize) material_catalog.cpp :3483 (11 GENERATE rows),:3510,:3520,:3544 EngineBridgeTests:1770 (POD roundtrip, exact flow values, nps-oro.6) unit covered
Inferred profile (slicer/printer/material/FLAVOR/temp fallback) engine.cpp:176 :3255,:3326,:3365,:3388,:3565 EngineBridgeTests:1135,:1210,:1267 (Theory),:1313 (Theory) synthetic headers, both harnesses covered

Findings / overlays / viewport

Feature Where C++ C# Scripts HOW Verdict
Findings summary (16B) + detail (300B) contract engine.cpp:1513/1538 via analysis tests only EngineBridgeTests:1474 (count/row equality, id -1→InvalidArgument, past-end→NotFound),:1554; EngineSessionTests:185,:211,:233 bridge + synthetic covered (C# owns the contract)
Per-move overlay values + supported ids engine.cpp:1550/1557/5652-5702 :2223,:1749,:3867 + SECTION :3969 (manager-derived 17-id list, exact content + order, nps-ai2.2) EngineSessionTests:253,:261,:464 (exact 17-id manager-derived list + order),:501 (tight-buffer truncation + pinned NUL),:533/:549 (null/zero-cap no-op) synthetic + ABI covered — GetSupportedOverlayIds is manager-derived (un-stubbed nps-ai2.2), exact id order pinned
Overlay stats pipeline (Min/Max/Mean/SampleCount, zero-filter) ViewportController.cs:564-640 :4435,:4477 ViewportControllerTests:460,:509 bridge + golden + demo gen covered (controller level)
Heatmap colors (ramp/invert/vmax/null) engine.cpp:6304 :2260 EngineBridgeTests:2084-:2128 (exact (0,1,0) mid) unit + ABI covered
Warp grid (info + risk arrays) engine.cpp:5711/5717 :1798 (size==gridW*gridH + full-array content guard), :1912 (risk VALUES golden on pinned input, nps-oro.5) EngineSessionTests:241 (null guard) ABI shape + content golden covered
Viewport buffers (layer buckets/offsets/extrude counts) engine.cpp:5861 :2131 EngineBridgeTests:1014 (smoke, Assert.True(true) tail) synthetic; C# ABI smoke covered (C++); C# smoke-only
Viewport MVP + camera engine.cpp:6102/5761 :2189,:4368,:4742 ViewportControllerTests:84,:104 synthetic + mirror covered
ProjectOrbitXY engine.cpp:5400 :2291 (11 samples, 1e6 boundary) EngineBridgeTests:2139,:2183,:2195 golden math vs legacy oracle ±1e-4 covered
Golden render parity (SHA-256) tests/golden/g6_orbit_render.sha256 :2650 EngineBridgeTests:2214 golden + Bresenham oracle + SHA file covered — fail-closed (NPS_BLESS_GOLDEN=1 opt-in, see Golden blessing recipe)
Viewport move ownership / D5 copy engine.cpp:5714-5741 :4534,:4645 indirect ViewportControllerTests:138 bit-identical rebuild + sentinels covered
Viewport colors (TYPE_COLORS port) engine.cpp:5692/6152 :2108,:4797 unit covered (C++ only)
Value types (Vec3/Color3/BedGeometry/CameraState/Position) internal/engine_value_types.h :4319,:4721 unit + static_assert covered
Viewport snapshot (applySnapshot) engine.cpp:5840 :4405 synthetic covered (C++ only)

C# facades & UI

Feature Where C++ C# Scripts HOW Verdict
EngineSession facade (lifecycle/load/gen/analyze/findings/warp/overlay/dispose) src/Nps.EngineHost/EngineSession.cs EngineSessionTests:48-:617 (24 tests) bridge + golden covered — gap: Analyze only with ("PLA",210,60); no full-profile override matrix
MeshController (snapshot/reload-replace/spans) MeshController.cs MeshControllerTests:36,:51,:91,:132 bridge + golden covered
ViewportController (lifecycle/moves/camera/sim/overlay/warp) src/Nps.Shell/ViewportController.cs ViewportControllerTests:31-:218 bridge + guards covered
Camera presets + Zoom to Fit math ViewportController.cs:294-482 ViewportControllerTests:253,:305,:376,:415,:439 (exact values) bridge covered (math) — toolbar button wiring covered by ViewportToolbarTests preset/zoom-fit→controller facts (ViewportToolbarTests:438,:464,:561,:598, nps-oro.2)
GcodeToolpathPainter Controls/GcodeToolpathPainter.cs GcodeToolpathPainterTests:29,:52,:75 logic + native parser/viewport snapshot covered — parsed moves emit travel/extrusion Lines with asserted colors, finding Ellipse markers, and max-layer filtering
MeshCanvasPainter Controls/MeshCanvasPainter.cs MeshCanvasPainterTests:28,:47,:71,:106 logic + golden Benchy mesh snapshot covered — null/empty guards, empty-palette white fallback, and Benchy Polygon output capped at MaxTrianglesPerPlate
FindingsPanel (7 category chips, no search) Controls/FindingsPanel.axaml(.cs) FindingsPanelTests:43-:248 + ShellChromeTests:209-:374 headless; chip clicks via reflection, not pointer events covered (panel level); keyboard/a11y NOT TESTED
PlaybackPanel + timer logic Controls/PlaybackPanel.axaml(.cs); SimulatorApp MainWindow.axaml.cs:510-658 runtime AppHeadlessSmokeTests:1410-:1758 (6 Facts: play/pause+icon, step clamp, auto-pause \|Δ\|<2, scrubber latch press→pause release→resume-if-was-playing, speed→interval recompute, scrubber commit clamp) + math TimelineMarkerHelperTests (13 Facts) headless public panel-event surface (AvaloniaHeadless class fixture LoadedSimulatorWindow amortizes Benchy load across suite) covered — runtime/state observable contract end-to-end (panel events → MainWindow handlers → status/IconGeometry/timer.Interval/mirror)
SliceParams (Slicer VM) src/SlicerApp/SliceParams.cs SliceParamsTests:17,:30,:49,:64 logic covered (VM level) — ApplySliceButton chain NOT TESTED
Shell collapse + width memory MainWindowShell.axaml.cs:294-412 AppHeadlessSmokeTests:173 (250/350 restore) headless covered
Activity bar + panel host + tabs ActivityBarHost.cs; PanelHost.cs ShellChromeTests:130-:188 logic covered — per-app OnActivityTabClick(object?, RoutedEventArgs) handlers were dead code (never wired in XAML, no callers); bead nps-ai2.4 deleted both copies; only OnActivityTabClicked (event subscriber) remains
Keybindings (P / Ctrl+L / Left / Right — the only 4 that exist) ShellKeybindings.cs:82-113 ShellChromeTests:50,:69,:89,:114 logic covered
ViewportToolbar (10 code-built buttons) Controls/ViewportToolbar.cs ViewportToolbarTests:100 (10 controls), :120 (tooltip text), :141 (toggle defaults), :155 (distinct refs), :194 (noop subscribers), :213/229/245/261/277/293/309/325 (8 *Clicked once), :341/:372 (toggle bool payload), :395 (multi-toggle), :438 (reset preset→controller), :464 (all-six orientations), :522 (toggle→app payload), :561 (zoom-fit→controller), :598 (non-square zoom-fit), :628 (layer up/down seam) headless click + bridge covered — every button enumerated, click-dispatched exactly once per raise, preset/zoom-fit clicks reach ViewportController.Camera as the production apps wire
Viewport pointer gestures (drag orbit/pan) SlicerApp MainWindow.axaml.cs:560-593; SimulatorApp :661-692 AppHeadlessSmokeTests:157,:165 Avalonia.Headless synthetic mouse events covered — both apps exercise the viewport press latch, left-button orbit with RotationX clamp ±1.5, right-button pan scaling by zoom, and camera assertions
App wiring (Load+Gen+Analyze, ApplySliceButton, overlay radios incl "None"→"motion-type", layer slider, finding navigation) SlicerApp :190-241 (seam LoadAndAnalyzeFromPath:208) + :244-263 + :440-450; SimulatorApp :241-256 (seam LoadAndAnalyzeFromPath:512) + :557-568 + :578-583 covered (nps-oro.3): 15 active Facts in AppHeadlessSmokeTests:367-:1115 drive every reachable handler through the real LoadAndAnalyzeFromPath seam + XAML button + public FindingsPanel.FindingSelected + reflected OverlayPanel.ModeChanged. The gen-failed (SlicerApp/MainWindow.axaml.cs:441-443; SimulatorApp/MainWindow.axaml.cs:557-559) and analyze-failed (SlicerApp/MainWindow.axaml.cs:503-506; SimulatorApp/MainWindow.axaml.cs:579-582) branches are unreachable from production today — Engine::GenerateGcode returns NPS_RESULT_SUCCESS unconditionally (src/Engine/engine.cpp:1433) and Engine::AnalyzeGcode is void (src/Engine/engine.cpp:1479-1488); 4 Skip facts with bead-cited reasons document the engine-side coverage (AppHeadlessSmokeTests.cs:1447-1467, wrapped in #pragma warning disable xUnit1004 / restore xUnit1004). Observable contract: Shell.StatusText substring, LayerSlider.Value_maxLayer mirror, LayerLabel text, viewport.SimMoveIndex, playback.SimIndex. headless behaviour covered (nps-oro.3, reachable paths); engine-side-only (gen-failed/analyze-failed, Skip facts cite EngineSessionTests coverage)
App boot (Program.cs, ABI gate, window load) src/SlicerApp/Program.cs; src/SimulatorApp/Program.cs AppHeadlessSmokeTests:63,:146; EngineBridgeTests:200 (ABI==1) smoke-apps.sh (disabled, lefthook.yml:131-132) headless + bridge partial — Sim raw-ABI boot smoke only in the disabled script
StatusSink stderr dual-write StatusSink.cs:57 status TextBlock substring only (AppHeadlessSmokeTests:63/:146) _smoke_scan.py via disabled script headless (visible bar only) partial — stderr path only covered by disabled script

Errors, ABI, scripts, perf

Feature Where C++ C# Scripts HOW Verdict
Error paths: engine overall engine.cpp lastErrorMessage_ :728,:747,:820,:1244,:2934, ZIP suite EngineBridgeTests:452,:471,:561,:1554; EngineSessionTests:127,:233 synthetic/crafted covered
Error paths: UI (load-fail status, fixture-missing, no-moves, session-invalid guards) SlicerApp :210-219 (session guard + fixture-missing) + :222-226 (load-failed); SimulatorApp :514-520 (session guard + fixture-missing) + :528-534 (load-failed; seam at :512 shifts the handlers into LoadAndAnalyzeFromPath) covered (nps-oro.3): AppHeadlessSmokeTests:367 (Slicer missing-fixture → "ERROR: primary ..."), :420 (Slicer invalid-file → "Load failed: ..." + _modelLoaded==false), :791 (Simulator missing-fixture → same), :843 (Simulator invalid-file → "Load failed: ..." + _mesh.Reload() ran → PlateCount==0), :531 (Slicer Apply-before-load → "Load a model first"). Engine session stays valid in every error branch. headless + reflected private state covered (nps-oro.3)
C ABI surface contract (POD sizes, string-out, null-handle, enum/wire-id mirrors) abi/nps_c_api.h static_asserts nps_c_api.h:215-222; tests :3867,:3775 EngineBridgeTests:236 (Theory 7 rows),:261,:285 marshal sizeof + synthetic, both sides covered
layer-fitness gate scripts/layer-fitness.sh LIVE pre-push + ctest + mutation ctest structural + adversarial fixtures covered
structural-fitness gate scripts/structural-fitness.sh commented out (lefthook.yml:165-166) structural partial — disabled by design; mutation suite manual-only
closure-integrity scripts/closure-integrity.sh manual close protocol fail-closed branch tests, manual partial (manual-only)
no-placeholder-scan scripts/no-placeholder-scan.sh LIVE pre-push (:135-136) structural covered (gate live; no self-test)
Production Test*-export hygiene scripts/nps-n1m-12-production-gate.sh ctest only when BUILD_TESTING=OFF + header grep ctest nm -D scan covered — caveat: never runs in the lefthook path (always Debug+tests)
debug-mixed.sh launcher scripts/debug-mixed.sh :4213 (popen smoke) 4 ctest syntax/content tests popen + structural covered (bash); debug-mixed.ps1 NOT TESTED — wont-fix (nps-oro.6): Windows-only twin launcher, no PowerShell on the Linux dev/CI host; behavior is pinned by the bash twin's coverage
docs-deploy scripts/deploy-docs.sh LIVE pre-push on docs/guide/** fail-closed wrangler/zensical covered (gate live; no self-test)
Perf (parse/analyze/load/build timings) :1968 (<5000ms),:2025 synthetic 20k moves + golden covered (smoke thresholds only)
FixtureLocator walk src/Nps.Shell/FixtureLocator.cs:60-90 fixture-present hook implicit in every bridge/golden test partial (no walk-order unit test)

Zero-coverage rows (brutally honest)

  1. ViewportToolbarCLOSED (nps-oro.2): 22 Facts in ViewportToolbarTests enumerate the 10 code-built controls + tooltips (ViewportToolbarTests.cs:99:189), drive every button click through Button.ClickEvent and verify *Clicked fires exactly once (:193:339), drive both toggles through flipped-IsChecked + Click to verify the bool payload (:340:436 + :521:559), and wire the toolbar to a real ViewportController to verify preset clicks change vc.Camera across all six orientations (:437:520) and zoom-fit clicks change vc.Camera.Zoom / PanX / PanY (:560:626).
  2. Playback runtimeCLOSED (nps-oro.1): 6 Facts in AppHeadlessSmokeTests:1410-:1758 drive PlayPauseClicked / StepClicked / AutoPause / ScrubberPointerPressed/Released / SpeedChanged / ScrubberChanged through the public panel surface into the real MainWindow handlers (SimulatorApp/MainWindow.axaml.cs:510-658). Observable contract: panel.IsPlaying, status substring, _simMoveIndex mirror, _playTimer.Interval.
  3. App event handlersCLOSED (nps-oro.3) for all reachable branches: OnLoadAnalyzeClick driven through LoadAndAnalyzeFromPath seam with both fixture-missing and invalid-file paths (AppHeadlessSmokeTests:367,:420,:791,:843); OnApplySliceClick driven via XAML button before/after load (:531,:572); OnOverlayModeChanged driven via reflected OverlayPanel.ModeChanged (:657,:998); OnLayerSliderChanged driven via Slider.Value (:615,:958); OnFindingSelected driven via FindingsPanel.FindingSelected for both pinned and unpinned (-1) move indices (:727,:1052,:1115). Both apps covered. Engine-side-only (4 Skip facts, AppHeadlessSmokeTests:1447-:1467): RunGenerate gen-failed (SlicerApp/MainWindow.axaml.cs:441-443; SimulatorApp/MainWindow.axaml.cs:557-559) and analyze-failed (SlicerApp/MainWindow.axaml.cs:503-506; SimulatorApp/MainWindow.axaml.cs:579-582) branches are unreachable from production today — Engine::GenerateGcode returns NPS_RESULT_SUCCESS unconditionally (src/Engine/engine.cpp:1433) and Engine::AnalyzeGcode is void (src/Engine/engine.cpp:1479-1488); covered engine-side by EngineSessionTests.GenerateDemoToolpath_AfterBenchyLoad_ReturnsMoves (:166) and EngineSessionTests.Findings_AreEmptyBeforeAnalyze_AndPopulatedAfter (:185). The Skip facts cite these engine-side tests and flip to real asserts the moment a future engine revision makes either op return a failure code.
  4. Pointer-drag orbit/pan + Zoom-to-Fit buttonCLOSED (nps-oro.4 / nps-oro.2): synthetic press/drag/release through Avalonia.Headless asserts camera fields for both apps — unarmed move is a no-op, left-drag orbit clamps RotationXRadians at ±1.5 while applying the Z delta, right-drag pan scales by 0.5 / max(0.1, Zoom) (AppHeadlessSmokeTests:157 Slicer, :165 Simulator via the shared RunViewportPointerGestureSmoke:227). Zoom-to-Fit clicks reach ViewportController.Camera with aspect-preserving math (ViewportToolbarTests.cs:561,:598).
  5. UI error pathsCLOSED (nps-oro.3): 5 facts across both apps drive the load-failed / fixture-missing / Apply-before-load branches through the real OnLoadAnalyzeClick + OnApplySliceClick handlers (AppHeadlessSmokeTests:367,:420,:531,:791,:843). Each error branch asserts the user-visible Shell.StatusText substring and that the engine session stays valid (IsValid==true, _modelLoaded==false, no move buffer populated).
  6. MeshCanvasPainter + GcodeToolpathPainter happy pathCLOSED (nps-oro.4): GcodeToolpathPainterTests:75 draws parsed moves and asserts travel/extrusion Lines, colors, finding Ellipse markers, and the max-layer filter; MeshCanvasPainterTests:71 renders the golden Benchy mesh and asserts Polygon output stays within MaxTrianglesPerPlate=2000, :106 pins the empty-palette opaque-white fallback.
  7. Warp grid risk valuesCLOSED (nps-oro.5): engine_tests.cpp:1912 content-asserts the risk array cell-by-cell on a pinned synthetic input (values, not just size==gridW*gridH).
  8. Analyzer value correctnessCLOSED (nps-oro.5 / nps-ai2.2): golden values pinned per analyzer — thermal engine_tests.cpp:1554 (score == totHeat == 0.04, findingCount == 1), structural :1594, motion :1640 (2-move tiny + cube junction clamp at 14.4). Motion profile inference is un-stubbed: inferProfileFromGcode applies real M204 P/T/S declarations (engine_tests.cpp:4096).
  9. Retraction analyzer + MaterialCatalog C# parity, corrupt-bgcode, multi-plate fixtures, debug-mixed.ps1CLOSED (nps-oro.6): retraction C# parity (EngineBridgeTests:1639), MaterialCatalog POD roundtrip C# (:1770), corrupt-CRC bgcode warn-and-continue on the real fixture (:1904). Two gaps documented instead of tested: multi-plate stays untested by design (engine hardcodes plate_1, no fixture exists — tracked by feature bead nps-ai2.3) and debug-mixed.ps1 is wont-fix (Windows-only twin; bash twin covered at engine_tests.cpp:4213 + 4 ctest).

Golden blessing recipe (NPS_BLESS_GOLDEN)

The single visual-golden baseline (tests/golden/g6_orbit_render.sha256, tests/golden/g6_orbit_render.ppm) is fail-closed:

  • A missing baseline = hard FAIL (C++ TEST_CASE("Visual/golden render parity …") at engine_tests.cpp:2650; C# VisualGolden_RenderOrbit_BytesMatchCppBaseline at EngineBridgeTests.cs:2214). No auto-write.
  • A mismatch = hard FAIL + .drift PPM next to the baseline (C++ side only — for eog/xdg-open/byte-diff inspection).

Regenerating the baseline is an explicit, gated, human-reviewed operation. To (re)bless the baseline after a deliberate ABI/render change:

# C++ Catch2:
NPS_BLESS_GOLDEN=1 ctest --test-dir build --output-on-failure \
    -R "Visual/golden render parity"

# C# xUnit (mirrors the C++ test byte-for-byte):
NPS_BLESS_GOLDEN=1 dotnet test tests/NPSEngine.Tests \
    --filter "FullyQualifiedName~VisualGolden_RenderOrbit_BytesMatchCppBaseline"

Both harnesses gate on NPS_BLESS_GOLDEN=="1" exactly. The bless run WARNs in C++ (INFO log) and silently passes in C#; both write the new .sha256 (C++ also rewrites the .ppm). Subsequent runs without the env var then enforce the new baseline.

Mandatory review checklist before committing:

  1. git diff tests/golden/g6_orbit_render.sha256 — new SHA must match what the C++ side just wrote (C# bless is byte-identical because the Bresenham oracle is mirrored).
  2. Visually inspect the new .ppm against the previous one (eog tests/golden/g6_orbit_render.ppm or any image viewer). Drift should match the deliberate change (camera, color ramp, ABI).
  3. If a mismatch run wrote .drift, byte-diff it against the committed .ppm to confirm the diff is exactly the intended change.

The baseline is committed (tests/golden/g6_orbit_render.sha256) and MUST NOT be deleted as a workaround for a missing baseline. If it's missing, run the bless recipe above; do not git restore the previous SHA without reviewing.

How to run each harness

# C++ Catch2 (Debug build auto-enables NPS_ENABLE_TEST_HOOKS):
cmake -S src/Engine -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build --parallel
ctest --test-dir build --output-on-failure

# C# xUnit (build the engine first; lib must be on the loader path):
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 $HOME/.dotnet/dotnet test tests/NPSEngine.Tests
#   (lefthook.yml:110 — place libNPSEngine.so next to the test binary or set LD_LIBRARY_PATH)

# Script fitness gates:
./scripts/layer-fitness.sh                 # live in pre-push
./scripts/no-placeholder-scan.sh           # live in pre-push
./scripts/structural-fitness.sh            # manual (gate disabled by design)
./scripts/closure-integrity.sh <beadId>    # manual close protocol

Re-count baselines:

grep -c 'TEST_CASE(' src/Engine/tests/engine_tests.cpp        # 76 (+17 TEST_CASE_METHOD)
grep -rnE '^\s*\[Fact' tests/NPSEngine.Tests/*.cs | wc -l     # 154 (+4 [Theory], 163 cases after Theory row expansion)

Optional future: gcov/llvm-cov + coverlet for true % — not wired today.

Full test inventory (every name)

Mechanically extracted from the live tree (same grep the re-count one-liners use). The matrix above groups them by feature; this list is the complete checklist the refresh gate diffs against.

C++ Catch2 — all 93 TEST_CASEs (engine_tests.cpp)
  • Bead nps-f8v.5: Retraction events parsing and analysis on custom G-codeengine_tests.cpp:3174
  • Bead nps-f8v.8: Bambu comments parsing and override detectionengine_tests.cpp:3255
  • Bead nps-f8v.8: Bambu proprietary commands are tolerated without crashengine_tests.cpp:3412
  • Bead nps-f8v.8: Malformed / boundary inputs are tolerated without crash /engine_tests.cpp:3602
  • Bead nps-f8v.8: Malformed / boundary inputs are tolerated without crash / ;engine_tests.cpp:3659
  • Bead nps-f8v.8: Malformed / boundary inputs are tolerated without crash / ;FLAVOR: withengine_tests.cpp:3688
  • Bead nps-f8v.8: Malformed / boundary inputs are tolerated without crash / ParseGcodeengine_tests.cpp:3619
  • Bead nps-f8v.8: Malformed / boundary inputs are tolerated without crash / Very longengine_tests.cpp:3635
  • Bead nps-f8v.8: Marlin + Klipper firmware detection via FLAVOR comment / Klipper flavorengine_tests.cpp:3388
  • Bead nps-f8v.8: Marlin + Klipper firmware detection via FLAVOR comment / Marlin flavorengine_tests.cpp:3365
  • Bead nps-f8v.8: NpsMaterialProfile POD layout is 108 bytes and round-trips via C ABIengine_tests.cpp:3775
  • Bead nps-f8v.8: OrcaSlicer comments parsingengine_tests.cpp:3326
  • Bead nps-f8v.8: Slicer detection rejects non-banner CURA/BAMBU substrings / Commentengine_tests.cpp:3708
  • Bead nps-f8v.8: Slicer detection rejects non-banner CURA/BAMBU substrings / Commentengine_tests.cpp:3729
  • Bead nps-f8v.8: Slicer detection rejects non-banner CURA/BAMBU substrings / Real bannerengine_tests.cpp:3750
  • Benchy analysis populates flow overlaysengine_tests.cpp:3149
  • Benchy analysis reports hole findingsengine_tests.cpp:3130
  • Benchy parse + viewport build timing smoke (nps-n1m.40 G16)engine_tests.cpp:2025
  • Benchy validation exposes transformed mesh dataengine_tests.cpp:655
  • Benchy validation keeps bounds and indices consumableengine_tests.cpp:678
  • Benchy validation loads the primary fixtureengine_tests.cpp:625
  • Benchy validation preserves golden mesh countsengine_tests.cpp:634
  • Benchy validation preserves the four-color paletteengine_tests.cpp:642
  • Benchy validation supports metadata-only reloadengine_tests.cpp:710
  • C ABI string-output contract (nps-n1m.27): null/zero-cap no-op + UTF-8 NUL + truncationengine_tests.cpp:3867
  • Default material profiles are parameterized by material keyengine_tests.cpp:3483
  • E2E: mesh load + synthetic gcode parse/analyze + overlay data assert (nps-f8v.11)engine_tests.cpp:1749
  • Engine GetLastParsedGcode split semantics (nps-n1m.32)engine_tests.cpp:1451
  • Engine LoadModelFromFile error cases for robustness (nps-l7k.14)engine_tests.cpp:747
  • Engine LoadModelFromFile returns failure for missing fileengine_tests.cpp:728
  • Engine LoadModelFromFile wires parser via ZIP/OPC reader (nps-l7k.3) on real Benchyengine_tests.cpp:291
  • Engine ZipArchiveReader extracts model XML + metadata on primary Benchy (nps-l7k.3)engine_tests.cpp:343
  • Engine basic lifecycle and versionengine_tests.cpp:276
  • Engine core mesh and plate data structures + append/combine (nps-l7k.4)engine_tests.cpp:478
  • Engine mesh prep for scalar fields & shared viewport (nps-l7k.11)engine_tests.cpp:533
  • Engine mesh query API surface (nps-l7k.2 design)engine_tests.cpp:378
  • Gcode bgcode basic header + optional full decode (nps-f8v.4)engine_tests.cpp:1513
  • Gcode gen + C ABI buffer + file roundtrip (nps-f8v.10 interop)engine_tests.cpp:2963
  • Gcode generation error cases and defaults (nps-f8v.10)engine_tests.cpp:2934
  • Gcode generation from loaded mesh + params (nps-f8v.10 basic)engine_tests.cpp:2772
  • Gcode generation non-planar + roundtrip validate structure (nps-f8v.10)engine_tests.cpp:2871
  • Gcode generation real geometry and scalar fields (nps-f8v.7.1)engine_tests.cpp:3014
  • Gcode parse + analyze roundtrip via C ABI harness hooks (integration)engine_tests.cpp:1708
  • Gcode parse from real test_cube + roundtrip structure (nps-f8v.4 + Gcode files)engine_tests.cpp:1414
  • Gcode parser multi-format layers + Bambu markers (nps-f8v.4)engine_tests.cpp:1350
  • Gcode parser relative E + M82/M83 + G92 + accel M204 (nps-f8v.4)engine_tests.cpp:1375
  • Gcode parser section types + G2/G3 arcs (nps-f8v.4)engine_tests.cpp:1402
  • Gcode parser state machine + moves (nps-f8v.11 + f8v.9 model)engine_tests.cpp:1294
  • LoadModelFromFile ABI forwarder rejects null engine handle (nps-n1m.32)engine_tests.cpp:820
  • M104 metadata fallback is parameterized by hotend temperatureengine_tests.cpp:3565
  • MaterialCatalog table exposes expected entry count + PLA fallback at index 0engine_tests.cpp:3520
  • MaterialCatalog::forType normalizes key (case + underscore-to-dash) and falls back to PLAengine_tests.cpp:3544
  • ModelXMLParser direct nps::Parse populates full result incl trianglesengine_tests.cpp:1228
  • ModelXMLParser handles object/component graph, unit, build itemsengine_tests.cpp:1210
  • ModelXMLParser reports PARSE_ERROR on bad data (integrates .14 model)engine_tests.cpp:1244
  • ModelXMLParser streams vertices + triangles from real 3MF sampleengine_tests.cpp:1182
  • Motion analyzer golden values on pinned synthetic gcode (nps-oro.5)engine_tests.cpp:1640
  • Performance: large G-code parse + analysis time (nps-f8v.11)engine_tests.cpp:1968
  • Primary Benchy ZIP hook extracts model and metadataengine_tests.cpp:1106
  • Primary Benchy ZIP load preserves golden countsengine_tests.cpp:1096
  • ProjectOrbitXY C ABI parity with previous UI math (nps-n1m.30 G6)engine_tests.cpp:2291
  • Structural score analyzer with GcodeMove (nps-f8v.11 + f8v.9)engine_tests.cpp:1594
  • Thermal grid analyzer math with GcodeMove (nps-f8v.11 + f8v.9)engine_tests.cpp:1554
  • Unknown material profile falls back to PLAengine_tests.cpp:3510
  • Viewport camera MVP + layer vis + sim offsets (nps-f8v.3)engine_tests.cpp:2189
  • Viewport color logic matches TYPE_COLORS port (nps-f8v.3)engine_tests.cpp:2108
  • Viewport harness integration: moves from parse + analyze feed (nps-f8v.3 + f8v.11)engine_tests.cpp:2223
  • Viewport layer buffers + move offsets from GcodeMove (nps-f8v.3 + f8v.9)engine_tests.cpp:2131
  • ViewportGetHeatmapColor C ABI matches GcodeViewport::GetHeatmapColor (nps-n1m.30 G6)engine_tests.cpp:2260
  • Visual/golden render parity via engine C ABI (nps-n1m.30 G6)engine_tests.cpp:2650
  • Warp grid risk contents golden on pinned synthetic input (nps-oro.5)engine_tests.cpp:1912
  • WarpGrid ABI + viewport render smoke (nps-f8v.6.1)engine_tests.cpp:1798
  • Zip reader rejects a bad deflate streamengine_tests.cpp:1036
  • Zip reader rejects a bad local header signatureengine_tests.cpp:999
  • Zip reader rejects a corrupt EOCDengine_tests.cpp:969
  • Zip reader rejects a truncated archiveengine_tests.cpp:986
  • Zip reader rejects null argumentsengine_tests.cpp:1088
  • Zip reader rejects stored-size mismatchesengine_tests.cpp:1071
  • Zip reader rejects unsupported compressionengine_tests.cpp:1018
  • Zip reader reports a missing entryengine_tests.cpp:1060
  • nps-580 scripts/debug-mixed.sh --help and print-modesengine_tests.cpp:4213
  • nps-ai2.2: inferProfileFromGcode applies M204 P/T/S acceleration declarationsengine_tests.cpp:4096
  • nps-n1m.18 D5: Viewport SetGcodeMoves copies (engine buffer mutation after Set does notengine_tests.cpp:4645
  • nps-n1m.18 D5: Viewport survives engine Load/Parse after SetGcodeMoves (no UAF)engine_tests.cpp:4534
  • nps-n1m.41 G17: ApplyOverlay(OverlayState) collapses the three-setter sequenceengine_tests.cpp:4435
  • nps-n1m.41 G17: GetExtrudeColorForType Color3* overload matches float[3] overloadengine_tests.cpp:4797
  • nps-n1m.41 G17: GetMeshBounds Position* overload matches float[3] overloadengine_tests.cpp:4760
  • nps-n1m.41 G17: Mat4LookAt now takes three Vec3engine_tests.cpp:4742
  • nps-n1m.41 G17: Position alias exists and is a Vec3engine_tests.cpp:4721
  • nps-n1m.41 G17: SetCamera(CameraState) overload forwards all five floatsengine_tests.cpp:4368
  • nps-n1m.41 G17: Vec3/Color3/BedGeometry/CameraState aggregate value typesengine_tests.cpp:4319
  • nps-n1m.41 G17: ViewportApplyOverlay C ABI aggregate equals three-setter sequenceengine_tests.cpp:4477
  • nps-n1m.41 G17: applySnapshot(EngineSnapshot) feeds moves to viewportengine_tests.cpp:4405
C# xUnit — all 158 Facts/Theories (154 [Fact] + 4 [Theory], 163 test cases) (tests/NPSEngine.Tests)
  • MainWindowShell_Collapse_Width_Memory_SmokeAppHeadlessSmokeTests.cs:173
  • SimulatorApp_MainWindow_Loads_Layout_And_BindingsAppHeadlessSmokeTests.cs:146
  • SimulatorApp_ViewportPointerDrag_OrbitAndPan_UpdateCameraAppHeadlessSmokeTests.cs:165
  • SlicerApp_MainWindow_Loads_Layout_And_BindingsAppHeadlessSmokeTests.cs:63
  • SlicerApp_ViewportPointerDrag_OrbitAndPan_UpdateCameraAppHeadlessSmokeTests.cs:157
  • AbiPODLayout_FrozenEngineBridgeTests.cs:236
  • CreateInitializeVersionDestroy_WorksEngineBridgeTests.cs:174
  • E2E_MeshLoadPlusGcodeAnalyze_AssertsOverlaysEngineBridgeTests.cs:675
  • EnumMirrors_MatchFrozenAbiIntsEngineBridgeTests.cs:261
  • GcodeGenerate_RoundtripAndNonplanar_ValidatesEngineBridgeTests.cs:750
  • GcodeParse_RoundtripViaTestHook_WorksEngineBridgeTests.cs:642
  • GetAbiVersion_MatchesExpectedAtStartupEngineBridgeTests.cs:200
  • GetLastParsedGcode_SplitSemantics_RoundTripViaCAbiEngineBridgeTests.cs:929
  • LoadModelFromFile_ErrorCasesAndOptions_RobustnessEngineBridgeTests.cs:471
  • LoadModelFromFile_MissingFile_ReturnsSpecificErrorAndMessageEngineBridgeTests.cs:452
  • LoadModelFromFile_NullEngineHandle_ReturnsInvalidArgumentEngineBridgeTests.cs:561
  • LoadModelFromFile_OnBenchy3Mf_SucceedsWithAssertionEngineBridgeTests.cs:298
  • Loader_IntegratesViaEngineHost_SucceedsEngineBridgeTests.cs:607
  • MaterialProfilePod_FilamentDiameter_RoundTripsWithExactFlowValuesEngineBridgeTests.cs:1770
  • ParseBgcode_CorruptBlockCrc_ValidContainer_WarnAndContinueEngineBridgeTests.cs:1904
  • ParseBgcode_RealTestCubeBinary_FullRoundtripAssertsMovesAndLayersEngineBridgeTests.cs:829
  • ProjectOrbitXY_IdentityRotation_ZContributesToScreenXYEngineBridgeTests.cs:2183
  • ProjectOrbitXY_MatchesLegacyUiMathEngineBridgeTests.cs:2139
  • ProjectOrbitXY_NullOutIsNoopEngineBridgeTests.cs:2195
  • RetractionFindings_ParityWithCppFixture_RealMessagesAndOverlaysEngineBridgeTests.cs:1639
  • TestAnalysisFindingsSummary_BeforeAnalyze_ReportsNoDataEngineBridgeTests.cs:1554
  • TestAnalysisFindingsSummary_RoundTripsThroughDetailEngineBridgeTests.cs:1474
  • TestInferredMaterialTemperatureFallbackEngineBridgeTests.cs:1313
  • TestInferredPropertiesFromGcodeEngineBridgeTests.cs:1135
  • TestInferredSlicerFlavorEngineBridgeTests.cs:1267
  • TestInferredSlicerOrcaSlicerEngineBridgeTests.cs:1210
  • TestMaterialProfilePODRoundTripEngineBridgeTests.cs:1351
  • TestParseGcodeMalformedInputsEngineBridgeTests.cs:1576
  • ThermalAndStructural_AnalyzerInterop_ReturnsDataEngineBridgeTests.cs:656
  • ViewportGetHeatmapColor_InvertFlipsRampEngineBridgeTests.cs:2103
  • ViewportGetHeatmapColor_MidValue_IsGreenEngineBridgeTests.cs:2084
  • ViewportGetHeatmapColor_NullOutIsNoopEngineBridgeTests.cs:2128
  • ViewportGetHeatmapColor_VmaxMapsToRedEndEngineBridgeTests.cs:2117
  • ViewportMeshRender_BenchyFixture_ValidatesEngineBridgeTests.cs:1065
  • ViewportRenderLogic_Smoke_BridgeCalls_NoCrashEngineBridgeTests.cs:1014
  • VisualGolden_RenderOrbit_BytesMatchCppBaselineEngineBridgeTests.cs:2214
  • WireIdMirrors_MatchFrozenAbiIdsEngineBridgeTests.cs:285
  • Construction_AllControlsHaveExpectedTooltipTextViewportToolbarTests.cs:120
  • Construction_AllPublicButtonsAreDistinctInstancesViewportToolbarTests.cs:155
  • Construction_ExposesExactlyTenControlsViewportToolbarTests.cs:100
  • Construction_TravelsAndExtrudesToggle_StartCheckedViewportToolbarTests.cs:141
  • ExtrudesToggle_Click_PayloadReflectsPostToggleIsCheckedViewportToolbarTests.cs:372
  • FrontClick_RaisesFrontClickedExactlyOnceViewportToolbarTests.cs:245
  • IsometricClick_RaisesIsometricClickedExactlyOnceViewportToolbarTests.cs:229
  • LayerDownClick_RaisesLayerDownClickedExactlyOnceViewportToolbarTests.cs:325
  • LayerUpClick_RaisesLayerUpClickedExactlyOnceViewportToolbarTests.cs:309
  • LayerUpDownClick_SubscriptionPath_RaisesEventForHostLambdaViewportToolbarTests.cs:628
  • NoOpEventSubscription_DoesNotThrowAndDoesNotFireViewportToolbarTests.cs:194
  • PresetClicks_ReachesController_AllSixOrientationsViewportToolbarTests.cs:464
  • ResetClick_RaisesResetClickedExactlyOnceViewportToolbarTests.cs:213
  • ResetClick_ReachesController_AndAppliesResetPresetViewportToolbarTests.cs:438
  • RightClick_RaisesRightClickedExactlyOnceViewportToolbarTests.cs:277
  • ShowTravelsToggle_PayloadTracksIsChecked_ThroughMultipleTogglesViewportToolbarTests.cs:395
  • ToggleClicks_ReachAppSubscription_WithExpectedPayloadViewportToolbarTests.cs:522
  • TopClick_RaisesTopClickedExactlyOnceViewportToolbarTests.cs:261
  • TravelsToggle_Click_PayloadReflectsPostToggleIsCheckedViewportToolbarTests.cs:341
  • ZoomFitClick_NonSquareViewport_PreservesAspectMathViewportToolbarTests.cs:598
  • ZoomFitClick_RaisesZoomFitClickedExactlyOnceViewportToolbarTests.cs:293
  • ZoomFitClick_ReachesController_AndAppliesZoomFitMathViewportToolbarTests.cs:561
  • CreateAndInitialize_ProducesValidSessionEngineSessionTests.cs:48
  • Dispose_MakesSessionInvalidEngineSessionTests.cs:60
  • Dispose_Twice_IsIdempotentEngineSessionTests.cs:69
  • Findings_AreEmptyBeforeAnalyze_AndPopulatedAfterEngineSessionTests.cs:185
  • GenerateDemoToolpath_AfterBenchyLoad_ReturnsMovesEngineSessionTests.cs:166
  • GetFindingDetail_ReturnsFullRecordForKnownIdEngineSessionTests.cs:211
  • GetFindingDetail_StaleId_ReturnsNullEngineSessionTests.cs:233
  • GetOverlayValue_BeforeLoad_ReturnsZeroEngineSessionTests.cs:261
  • GetOverlayValue_ThrowsAfterDisposeEngineSessionTests.cs:253
  • GetSupportedOverlayIds_NullEngine_IsNoOpEngineSessionTests.cs:533
  • GetSupportedOverlayIds_ReturnsExactManagerDerivedListEngineSessionTests.cs:464
  • GetSupportedOverlayIds_TightBuffer_TruncatesAtCapMinusOneAndPinsNulEngineSessionTests.cs:501
  • GetSupportedOverlayIds_ZeroCapacity_IsNoOpEngineSessionTests.cs:549
  • GetWarpGrid_BeforeAnalyze_ReturnsNullEngineSessionTests.cs:241
  • LoadModel_ClearsPriorMoveBufferEngineSessionTests.cs:142
  • LoadModel_MissingFile_ReturnsFailureWithMessageEngineSessionTests.cs:127
  • LoadModel_OnBenchy3Mf_ReturnsStructuredPlatesAndPaletteEngineSessionTests.cs:95
  • ParseBgcode_AfterDispose_ThrowsObjectDisposedExceptionEngineSessionTests.cs:407
  • ParseBgcode_InvalidBytes_ReturnsFailureWithParseErrorEngineSessionTests.cs:362
  • ParseGcode_AfterDispose_ThrowsObjectDisposedExceptionEngineSessionTests.cs:395
  • ParseGcode_AsciiText_ReturnsSuccessWithMovesEngineSessionTests.cs:288
  • ParseGcode_CommandlessText_ReturnsSuccessWithoutMoves_AndClearsPriorSnapshotEngineSessionTests.cs:335
  • ParseGcode_EmptyText_ReturnsSuccessWithoutMoves_AndClearsPriorSnapshotEngineSessionTests.cs:311
  • ParseGcode_NoM204_LeavesReservedSlotZeroEngineSessionTests.cs:617
  • FindingsPanel_AllChip_RestoresBothAxesFindingsPanelTests.cs:156
  • FindingsPanel_CategoryFilter_AlsoUnchecksAllFindingsPanelTests.cs:130
  • FindingsPanel_DefaultChips_AllCheckedFindingsPanelTests.cs:43
  • FindingsPanel_Selection_RaisesFindingSelected_WithItemFindingsPanelTests.cs:189
  • FindingsPanel_SetFindings_RebuildsItemsSource_And_CountFindingsPanelTests.cs:73
  • FindingsPanel_SeverityFilter_ShrinksVisibleCountFindingsPanelTests.cs:94
  • FindingsPanel_TryGetCachedItem_ReturnsNull_ForUnknownFindingIdFindingsPanelTests.cs:248
  • FindingsPanel_UpdateDetail_PopulatesStyledPropertiesFindingsPanelTests.cs:218
  • RenderTo_FreshViewport_ZeroMoves_IsNoOpGcodeToolpathPainterTests.cs:52
  • RenderTo_NullViewport_IsNoOpGcodeToolpathPainterTests.cs:29
  • RenderTo_WithParsedMoves_DrawsLinesColorsMarkers_AndHonorsLayerFilterGcodeToolpathPainterTests.cs:75
  • RenderTo_Benchy_EmitsPolygonsWithinPerPlateCapMeshCanvasPainterTests.cs:71
  • RenderTo_EmptyMeshController_IsNoOpMeshCanvasPainterTests.cs:47
  • RenderTo_EmptyPalette_UsesOpaqueWhiteFallbackMeshCanvasPainterTests.cs:106
  • RenderTo_NullMesh_IsNoOpMeshCanvasPainterTests.cs:28
  • Constructor_BeforeReload_HasZeroPlatesAndEmptyPaletteMeshControllerTests.cs:36
  • PlateMesh_EmptyArrays_ReportZeroCountsAndEmptySpansMeshControllerTests.cs:132
  • Reload_AfterSecondLoad_ReplacesSnapshotInPlaceMeshControllerTests.cs:91
  • Reload_OnBenchy_SnapshotsOnePlateWithGoldenCountsMeshControllerTests.cs:51
  • ActivityBarHost_FiresTabClicked_ForRegisteredKeyShellChromeTests.cs:146
  • ActivityBarHost_NoTabClicked_When_Button_Tag_UnregisteredShellChromeTests.cs:130
  • FindingFormatter_CategoryLabel_And_Brush_For_All_Known_CategoriesShellChromeTests.cs:244
  • FindingFormatter_FromSummaryAndDetail_Stamps_Category_From_DetailShellChromeTests.cs:334
  • FindingItem_DefaultShape_Mirrors_Api_ContractShellChromeTests.cs:209
  • FindingsFilterState_Default_Matches_All_RowsShellChromeTests.cs:289
  • PanelHost_Show_FlipsExactlyOneVisible_And_FiresOnShownShellChromeTests.cs:164
  • PanelHost_Show_UnknownKey_NoOp_NoOnShownShellChromeTests.cs:188
  • SeverityPalette_Resolves_Fallback_BrushesShellChromeTests.cs:374
  • ShellKeybindings_Left_Right_Step_And_HandleShellChromeTests.cs:89
  • ShellKeybindings_Mod_L_TogglesInspector_Only_With_CtrlShellChromeTests.cs:69
  • ShellKeybindings_P_TogglesPlay_And_HandlesShellChromeTests.cs:50
  • ShellKeybindings_Unhandled_Key_FallsThroughShellChromeTests.cs:114
  • CreateDefaults_Matches_HardCoded_Demo_Toolpath_OptionsSliceParamsTests.cs:17
  • PropertyChanged_Does_Not_Fire_On_Same_ValueSliceParamsTests.cs:64
  • PropertyChanged_Fires_On_MutationSliceParamsTests.cs:49
  • ToGcodeGenOptions_Reflects_Mutated_FieldsSliceParamsTests.cs:30
  • BuildMarkers_EmptyFindings_ReturnsEmptyTimelineMarkerHelperTests.cs:110
  • BuildMarkers_EmptyTimeline_ReturnsEmptyTimelineMarkerHelperTests.cs:118
  • BuildMarkers_ExcludesMoveIndexMinusOneTimelineMarkerHelperTests.cs:138
  • BuildMarkers_NullFindings_ReturnsEmptyTimelineMarkerHelperTests.cs:102
  • BuildMarkers_PreservesInputOrderTimelineMarkerHelperTests.cs:184
  • BuildMarkers_ProjectOffsetsAcrossFullTimelineTimelineMarkerHelperTests.cs:163
  • Fraction_EmptyTimeline_ReturnsZeroTimelineMarkerHelperTests.cs:64
  • Fraction_FirstMove_ReturnsZeroTimelineMarkerHelperTests.cs:42
  • Fraction_LastMove_ReturnsOneTimelineMarkerHelperTests.cs:48
  • Fraction_Midpoint_ReturnsHalfTimelineMarkerHelperTests.cs:56
  • Fraction_MoveBeyondEnd_ClampsToOneTimelineMarkerHelperTests.cs:90
  • Fraction_NegativeMoveIndex_ClampsToZeroTimelineMarkerHelperTests.cs:82
  • Fraction_SingleMove_ReturnsZeroTimelineMarkerHelperTests.cs:74
  • ApplyOverlay_FromSession_ComputesStatsAndAppliesOverlayViewportControllerTests.cs:460
  • ApplyOverlay_MirrorsMode_AndDoesNotThrowViewportControllerTests.cs:168
  • ApplyOverlay_NonThermal_LastOverlayMeanMatchesStatsMeanAndSampleCountExcludesZerosViewportControllerTests.cs:509
  • ApplyOverlay_NullValues_ThrowsViewportControllerTests.cs:196
  • BuildBuffers_IsCallableAndDoesNotThrowViewportControllerTests.cs:128
  • CameraPresets_ProduceNonCollapsedProjectedBoundsAndDistinctOrientationsViewportControllerTests.cs:305
  • ComputeZoomFit_ReturnsPlacingContentAtApproximately90PercentFillViewportControllerTests.cs:415
  • ComputeZoomFit_WithMoves_ReturnsExpectedZoomAndPanViewportControllerTests.cs:376
  • ComputeZoomFit_WithNonSquareViewportAndContent_ReturnsExpectedZoomAndFillViewportControllerTests.cs:439
  • CreateAndInitialize_ProducesValidViewportViewportControllerTests.cs:31
  • Dispose_MakesViewportInvalidViewportControllerTests.cs:41
  • Dispose_Twice_IsIdempotentViewportControllerTests.cs:50
  • MovesSpan_EmptyBeforeSetMovesViewportControllerTests.cs:211
  • MovesSpan_ReflectsSetMovesCountViewportControllerTests.cs:218
  • SetCameraPreset_UpdatesCameraRotationAndZeroPanViewportControllerTests.cs:253
  • SetCamera_FiveArgOverload_MirrorsCameraStateViewportControllerTests.cs:104
  • SetCamera_RecordOverload_MirrorsCameraStateViewportControllerTests.cs:84
  • SetLayerVisibility_MirrorsMaxLayerViewportControllerTests.cs:76
  • SetMoves_MirrorsCountAndPointerViewportControllerTests.cs:138
  • SetSimulationState_MirrorsSimMoveIndexViewportControllerTests.cs:120
  • SetWarpParams_DoesNotThrowViewportControllerTests.cs:203

See also

  • quality-gates.md — lefthook/ctest wiring for every gate named here
  • overview.md — golden fixture in the architecture context
  • c-abi.md — the ABI surface the bridge tests pin