From 3684e7b5e78d301469fec599ad759aaaacb3602e Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 18 Aug 2026 11:30:47 +0200 Subject: [PATCH] test: classify prerequisite lanes and own Avalonia sessions --- docs/release-gate.md | 28 +++++++-- .../2026-08-18-r3-test-truth-ledger.md | 63 ++++++++++++++++++- .../Credentials/AppCredentialResolverTests.cs | 1 + .../ChargenPreviewEntityBuilderTests.cs | 1 + .../Rendering/CornerFloodReplayTests.cs | 6 ++ .../Rendering/FramePacingControllerTests.cs | 1 + .../Rendering/HouseExitWalkReplayTests.cs | 1 + .../Issue113DrawingBspFilterTests.cs | 1 + .../Issue113MeetingHallFloodTests.cs | 1 + .../Issue120ReciprocalPingPongTests.cs | 1 + .../Issue124LookInSeedRegionTests.cs | 1 + .../Rendering/Issue130DoorwayStripTests.cs | 1 + .../Rendering/Issue131SetupProbeTests.cs | 1 + .../Issue176177FacilityHubFloodReplayTests.cs | 1 + .../Issue177StairDescentCameraFloodTests.cs | 1 + .../Rendering/Issue181VisFlapReplayTests.cs | 1 + .../Issue181WallPressEquilibriumTests.cs | 1 + .../Issue95DungeonFloodDiagnosticTests.cs | 1 + .../LinuxMonotonicFramePacingWaiterTests.cs | 2 + .../Rendering/PortalTunnelAssetTests.cs | 1 + .../RetailParticleGeometryClassifierTests.cs | 3 + .../Rendering/RetailSelectionAssetTests.cs | 2 + .../Streaming/LandblockBuildFactoryTests.cs | 1 + .../AcDream.App.Tests/UI/IconComposerTests.cs | 3 + .../UI/Layout/CharacterLayoutImportProbe.cs | 1 + .../ChatIndicatorButtonLiveMountProbeTests.cs | 1 + .../UI/Layout/ChatOptionsDatDefaultsTests.cs | 1 + .../UI/Layout/FaPanelSlotProbeTests.cs | 1 + .../UI/Layout/InventoryFrameImportProbe.cs | 1 + .../Layout/ItemAppraisalTextFormatterTests.cs | 1 + .../UI/Layout/ItemListCellTemplateTests.cs | 1 + .../KeyboardConfigLiveMountProbeTests.cs | 1 + .../UI/Layout/MapHousePanelSlotProbeTests.cs | 1 + .../Layout/OptionsPanelLiveMountProbeTests.cs | 1 + .../UI/Layout/PaperdollClickMapTests.cs | 1 + .../UI/Layout/PaperdollSlotBackgroundTests.cs | 1 + .../UI/Layout/PowerbarLayoutProbeTests.cs | 1 + .../Layout/SocialPanelLiveMountProbeTests.cs | 1 + .../UI/Layout/SpellbookRowStyleTests.cs | 1 + .../UI/RetailCursorCatalogTests.cs | 2 + .../UI/SpewBoxLayoutDumpDiagnostic.cs | 1 + .../UI/UiDatFontBorderPixelTests.cs | 2 + .../UI/UiRenderContextAlphaTests.cs | 2 + .../LiveEntityPresentationControllerTests.cs | 1 + .../World/RecallTeleportAnimationTests.cs | 1 + .../BakeDeterminismTests.cs | 1 + ...5StaticSpherePopulationMeasurementTests.cs | 1 + .../ChargenAppearanceCatalogColorTests.cs | 1 + ...argenAppearanceCatalogInstalledDatTests.cs | 1 + .../ChargenTableReaderInstalledDatTests.cs | 1 + .../InstalledPreparedCollisionCatalogTests.cs | 1 + ...InstalledSetupBspPrimitiveDispatchTests.cs | 1 + ...nstalledSetupCollisionReachabilityTests.cs | 1 + ...ue334NeftetFormationCellMembershipTests.cs | 1 + .../PakEquivalenceTests.cs | 1 + .../SolidColorTextureCacheTests.cs | 1 + .../RetailSpellMetadataProjectorTests.cs | 2 + .../Vfx/RetailDatLoaderTests.cs | 1 + .../LiveHandshakeTests.cs | 1 + .../EnvCellSoundEmitterInventoryTests.cs | 1 + .../Audio/UiSoundTableResolutionTests.cs | 1 + .../CottageDoorwayCharacterizationTests.cs | 1 + .../Conformance/DatConcurrencyStressTests.cs | 1 + .../DungeonLandblockDatProbeTests.cs | 1 + .../FindCellListConformanceTests.cs | 3 + .../HoltburgTorchFalloffProbeTests.cs | 1 + .../Issue107SpawnDiagnosticTests.cs | 1 + .../Conformance/Issue112MembershipTests.cs | 1 + .../Issue113DoorVanishDiagnosticTests.cs | 1 + .../Issue113PhantomStairsDumpTests.cs | 1 + .../Conformance/Issue119TowerDumpTests.cs | 1 + .../Issue119UpNullGfxObjDumpTests.cs | 1 + .../StipplingSurfaceEquivalenceTests.cs | 1 + .../ThresholdDivergenceDiagnosticTests.cs | 1 + .../ThresholdPortalCrossingReplayTests.cs | 1 + .../RetailActionIdentityRoundTripTests.cs | 1 + .../Input/RetailActionMapReaderTests.cs | 1 + ...Ap157SortingSphereFloodMeasurementTests.cs | 1 + .../BoxIntersectsCellBspDifferentialTests.cs | 1 + .../Physics/CameraCornerSealReplayTests.cs | 1 + .../CellTransitFindTransitCellsBoxTests.cs | 1 + .../Physics/CellTransitTests.cs | 1 + .../Physics/DoorBugTrajectoryReplayTests.cs | 10 +++ .../Physics/DoorCollisionApparatusTests.cs | 1 + .../Physics/DoorSetupGfxObjInspectionTests.cs | 1 + .../Physics/FlatBspQueryDifferentialTests.cs | 1 + .../Physics/FlatCollisionInstalledDatTests.cs | 1 + .../HumanoidMotionTableRootMotionTests.cs | 1 + .../Issue108CellarAscentViewerReplayTests.cs | 1 + .../Issue137CorridorSeamInspectionTests.cs | 1 + .../Issue137CorridorSeamReplayTests.cs | 1 + .../Issue147ArwicBuildingsDumpTests.cs | 1 + .../Issue175HubDoorPoseInspectionTests.cs | 2 + .../Physics/Issue176177SeamTransitLagTests.cs | 1 + ...ue180CorridorSweepHysteresisReplayTests.cs | 1 + ...186ConnectorCellGeometryInspectionTests.cs | 1 + ...188FadingDoorMotionTableInspectionTests.cs | 1 + ...sue337NeftetRockGeometryInspectionTests.cs | 1 + .../Physics/MotionCommandCatalogDatTests.cs | 1 + ...RestrictionObjPrevalenceInspectionTests.cs | 1 + .../Issue176177DungeonSeamInspectionTests.cs | 1 + ...NetworkFountainRoomLightInspectionTests.cs | 1 + .../Terrain/TerrainModernConformanceTests.cs | 1 + .../HeadlessCredentialResolverTests.cs | 1 + .../LauncherProcessSupervisorTests.cs | 5 ++ .../LauncherExecutableSetTests.cs | 2 + .../Profiles/LauncherProfileHardeningTests.cs | 1 + .../Profiles/LauncherProfileStoreTests.cs | 2 + .../Status/StatusFileTailerTests.cs | 1 + .../Updates/ClientVersionStoreTests.cs | 1 + .../MainWindowViewTests.cs | 38 ++++++----- tools/audit-test-inventory.ps1 | 23 +++++++ tools/run-release-gate.ps1 | 2 +- 113 files changed, 273 insertions(+), 22 deletions(-) diff --git a/docs/release-gate.md b/docs/release-gate.md index 35c3cbcd..473a3e5d 100644 --- a/docs/release-gate.md +++ b/docs/release-gate.md @@ -12,9 +12,9 @@ The command verifies that `AcDream.slnx` contains every `.csproj` under `src/`, then discovers and runs every hermetic test in every default test assembly once in a fresh Release process. It does not retry failures. Tests carrying an explicit non-hermetic `Lane` trait (`InstalledDat`, `PreparedPackage`, `Live`, -or `Manual`), `Purpose=Diagnostic`, or `Status=KnownFailure` are excluded from -the hermetic total and run through their owned lane instead. The graph currently -contains 44 projects, +`Manual`, `Windows`, `Linux`, or `SystemFont`), `Purpose=Diagnostic`, or +`Status=KnownFailure` are excluded from the hermetic total and run through +their owned lane instead. The graph currently contains 44 projects, including all 13 maintained .NET tools; data-dependent tools are built but are not executed as tests. @@ -79,8 +79,18 @@ Installed-DAT tests require an explicit opt-in and a retail DAT directory: ```powershell $env:ACDREAM_RUN_INSTALLED_DAT_TESTS = '1' $env:ACDREAM_DAT_DIR = 'C:\path\to\Asherons Call' -dotnet test tests/AcDream.App.Tests/AcDream.App.Tests.csproj -c Release ` - --filter 'Lane=InstalledDat&Status!=KnownFailure&Purpose!=Diagnostic' +pwsh ./tools/run-release-gate.ps1 -SkipRestore -SkipBuild ` + -TestFilter 'Lane=InstalledDat&Status!=KnownFailure&Purpose!=Diagnostic' +``` + +The prepared-package lane additionally requires a validated `acdream.pak` +beside the DATs or at `ACDREAM_PAK_PATH`: + +```powershell +$env:ACDREAM_DAT_DIR = 'C:\path\to\Asherons Call' +$env:ACDREAM_PAK_PATH = 'C:\path\to\acdream.pak' +pwsh ./tools/run-release-gate.ps1 -SkipRestore -SkipBuild ` + -TestFilter 'Lane=PreparedPackage&Status!=KnownFailure&Purpose!=Diagnostic' ``` Regenerate all committed UI fixtures through the one comprehensive manual @@ -109,6 +119,14 @@ dotnet test tests/AcDream.Core.Tests/AcDream.Core.Tests.csproj -c Release ` --filter 'Purpose=Diagnostic' ``` +Operating-system contracts are likewise explicit. Run `Lane=Windows` on a +Windows host and `Lane=Linux` on a native Linux host; a lane is not portable +evidence when executed on the other operating system. + +`Lane=SystemFont` exercises the BitmapFont path against a host-provided TTF. +It is separate because the supported runtime can legitimately have none of the +well-known development fonts installed. + ## Updating dependencies Do not edit lock files by hand. To make an intentional dependency change: diff --git a/docs/reviews/2026-08-18-r3-test-truth-ledger.md b/docs/reviews/2026-08-18-r3-test-truth-ledger.md index 107704ee..09677293 100644 --- a/docs/reviews/2026-08-18-r3-test-truth-ledger.md +++ b/docs/reviews/2026-08-18-r3-test-truth-ledger.md @@ -127,7 +127,7 @@ identifiable in the lane report. | T-004 warning mismatches | resolved in R2 | Clean rebuild is zero-warning with repository-wide warnings-as-errors. | | T-005 unreachable panel stack | requires production reachability proof | Do not delete 52 meaningful tests until the dead presentation surface and any supported plugin compatibility promise are verified together. | | T-006 misleading installed-DAT reason | resolved in batch B | Shared opt-in is now `ACDREAM_RUN_INSTALLED_DAT_TESTS=1` (legacy switch retained), the reason names the lane, and all nine owners carry `Lane=InstalledDat`. | -| T-007 271 silent passing gates | active; current candidate set generated | Current syntax has 282 prerequisite-return candidates across seven projects. Inspect/classify from the generated manifest; the count changed with source growth and includes platform gates, so do not mechanically rewrite all 282. | +| T-007 271 silent passing gates | lane classification complete in batch D; body cleanup active | Of 282 current candidates, 280 are true prerequisite gates and now have an explicit lane. The two unlaned methods are reviewed false positives that assert the current Windows/Linux branch before returning. Empty-return removal remains, lane by lane. | | T-008 incapable-of-failing diagnostics | batch A plus diagnostic lane work | Delete the literal wiring smoke test; repair the GPU contract tautology; later re-home output-only apparatus. | | T-009 wall-clock double-click tests | open | Introduce a behavior-preserving injectable monotonic clock and deterministic fake time. | | T-010 two useless cases | high-confidence cleanup batch A | Delete `SmokeTest.TestProject_IsWired` and `ChaseCameraTests.ImplementsICamera`; compilation already proves both claims. | @@ -137,7 +137,7 @@ identifiable in the lane report. | T-014 seven load-sensitive tests | active; first mechanism reproduced | `PortalProjectionTests.ClipToRegion_FrameOwnedStore_ReusesExactResultArray` reported 6,904 B only while three App test hosts ran concurrently, then passed in an isolated run. Preserve both observations and remove ambient process-allocation sensitivity rather than loosening the zero-allocation oracle. | | T-015 four non-prerequisite skips | resolved in batches A/B | PVS scaffold deleted with rationale preserved; redundant chat/radar generators deleted in favor of the comprehensive Manual lane; tower oracle is `Status=KnownFailure`. | | T-016 historical test taxonomy | open | Rename/re-home only after each test's durable owner and oracle are established. | -| T-017 Avalonia ownership | resolved in R2 | All seven editor variants now execute in one owned application session; 11 focused passes plus the complete gate. | +| T-017 Avalonia ownership | reopened and closed in batch D | The full gate exposed the same compositor ownership class between six newer `MainWindowViewTests` facts. Their six named assertion phases now run in one owned Avalonia application session; 25 fresh-process stress iterations and the complete gate pass. | | T-018 stderr observer race | resolved in R2 | Live reader shares writes/deletes; 25 focused repetitions plus the complete gate. | ## Preserved rationale for removals in batch A @@ -251,3 +251,62 @@ An attempted parallel App/Core build collided on the shared `AcDream.Plugin.Abstractions` intermediate DLL. The repository gate serializes projects, so the authoritative verification is the two isolated clean builds above; no code or assertion was changed in response to that tooling collision. + +## Batch D prerequisite lanes and Avalonia ownership + +The reviewed prerequisite map classifies every true candidate without deleting +its existing guard: + +| Lane | Attributed methods | Prerequisite | +|---|---:|---| +| `InstalledDat` | 336 | Installed retail DAT directory; includes the 73 custom installed-DAT facts and whole DAT-backed investigation classes. | +| `PreparedPackage` | 2 | Installed DATs plus validated `acdream.pak`. | +| `Live` | 3 | Explicit live handshake opt-in and reachable service. | +| `Manual` | 1 | Explicit fixture-regeneration opt-in. | +| `Windows` | 7 | Windows-only filesystem/process/timer behavior. | +| `Linux` | 10 | Linux permission/signal/monotonic-clock behavior. | +| `SystemFont` | 2 | A host system TTF available to the BitmapFont path. | + +Class-level traits legitimately cover some additional methods that share the +same fixture owner, so the 336 installed-DAT method count is larger than the +280 syntax candidates. The only candidate methods without a lane are +`GraphicalHostPlatformServicesTests.CurrentPlatformOwnsPathsPacingAndNativeClosure` +and +`LinuxMonotonicFramePacingWaiterTests.PlatformFactorySelectsCurrentOperatingSystem`. +Both are hermetic cross-platform branch tests: on Windows or Linux they assert +the matching branch and return only after the assertion. They are not silent +prerequisite passes. + +The 11 conditional `SkipException.ForSkip` source sites are also reconciled. +They serve 12 test methods: installed-DAT asset contracts, one prepared-package +contract, and two system-font contracts. xUnit v2 reports that exception shape +as a failure rather than a dynamic skip, but the owning lanes now keep them out +of the hermetic total. A later body-cleanup batch will replace the misleading +skip wording/exception with explicit prerequisite failure or discovery-time +lane behavior. + +The first complete Batch D gate correctly failed in Launcher cleanup after +14,396 passes: the six `MainWindowViewTests` Avalonia facts could start and +destroy isolated thread-affine compositors on different xUnit workers. The +assertion bodies were preserved as six named private phases under one +`CompiledMarkupAndEveryModalFocusPathRunInOneOwnedAvaloniaSession` fact. The +focused two-case class then passed in 25 consecutive fresh processes (50/50 +results), and the same full-gate context passed. + +Batch D verification: + +- complete 44-project Release build: 0 warnings, 0 errors; +- final syntax manifest: 11,450 attributed methods, 51 diagnostics, one known + failure, 282 prerequisite-return candidates, and only the two reviewed + cross-platform false positives unlaned; +- complete hermetic Release gate: 14,392 passed / 0 skipped / 0 failed across + all 12 test assemblies in 131.518 seconds; and +- Launcher view stress: 25 fresh processes, 2/2 cases per process, no cleanup + or ownership failures. + +The 350-pass reduction from the clean R2 headline is exactly explained: batch A +netted minus one case; batch B removed six non-hermetic passes; batch C removed +68 newly classified diagnostic cases; batch D removed 270 prerequisite-lane +passes; and consolidating the six Avalonia sessions into one removed five case +IDs without removing any assertion phase. All 77 former default skips are also +accounted for by the PVS deletion and batch-B lane/deletion decisions. diff --git a/tests/AcDream.App.Tests/Credentials/AppCredentialResolverTests.cs b/tests/AcDream.App.Tests/Credentials/AppCredentialResolverTests.cs index 49eb9820..144a93c3 100644 --- a/tests/AcDream.App.Tests/Credentials/AppCredentialResolverTests.cs +++ b/tests/AcDream.App.Tests/Credentials/AppCredentialResolverTests.cs @@ -131,6 +131,7 @@ public sealed class AppCredentialResolverTests } [Fact] + [Trait("Lane", "Linux")] public void LinuxRejectsGroupOrOtherCredentialPermissions() { if (!OperatingSystem.IsLinux()) diff --git a/tests/AcDream.App.Tests/Rendering/ChargenPreviewEntityBuilderTests.cs b/tests/AcDream.App.Tests/Rendering/ChargenPreviewEntityBuilderTests.cs index 68fb5fcb..4cd35d74 100644 --- a/tests/AcDream.App.Tests/Rendering/ChargenPreviewEntityBuilderTests.cs +++ b/tests/AcDream.App.Tests/Rendering/ChargenPreviewEntityBuilderTests.cs @@ -20,6 +20,7 @@ namespace AcDream.App.Tests.Rendering; /// is resolving Setup/GfxObj/Surface/Animation dat data that /// receives pre-resolved). /// +[Trait("Lane", "InstalledDat")] public sealed class ChargenPreviewEntityBuilderTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.App.Tests/Rendering/CornerFloodReplayTests.cs b/tests/AcDream.App.Tests/Rendering/CornerFloodReplayTests.cs index 74da2f81..0abff4e9 100644 --- a/tests/AcDream.App.Tests/Rendering/CornerFloodReplayTests.cs +++ b/tests/AcDream.App.Tests/Rendering/CornerFloodReplayTests.cs @@ -198,6 +198,7 @@ public class CornerFloodReplayTests /// exact gate that flips. /// [Fact] + [Trait("Lane", "InstalledDat")] public void Diagnostic_TraceGoodVsGlitchStep() { var datDir = ResolveDatDir(); @@ -266,6 +267,7 @@ public class CornerFloodReplayTests /// transition background strobe). Guards the ApplyReciprocalClip pipeline. /// [Fact] + [Trait("Lane", "InstalledDat")] public void CornerSweep_FloodIsCompleteAndMonotone() { var datDir = ResolveDatDir(); @@ -363,6 +365,7 @@ public class CornerFloodReplayTests /// the tripwire count stays 0. /// [Fact] + [Trait("Lane", "InstalledDat")] public void PortalPlaneCrossings_InPlacePropagationConverges() { var datDir = ResolveDatDir(); @@ -433,6 +436,7 @@ public class CornerFloodReplayTests /// stays 0 across every Build. /// [Fact] + [Trait("Lane", "InstalledDat")] public void InCellDirectionSweep_InPlacePropagationConverges() { var datDir = ResolveDatDir(); @@ -495,6 +499,7 @@ public class CornerFloodReplayTests /// the collapsing intersection. /// [Fact] + [Trait("Lane", "InstalledDat")] public void Diagnostic_Hop2Microscope() { var datDir = ResolveDatDir(); @@ -625,6 +630,7 @@ public class CornerFloodReplayTests /// 0171/0173 — the screen area where the player stands then shows background. /// [Fact] + [Trait("Lane", "InstalledDat")] public void Diagnostic_CornerPress_FloodAcrossDoorwayPlane() { var datDir = ResolveDatDir(); diff --git a/tests/AcDream.App.Tests/Rendering/FramePacingControllerTests.cs b/tests/AcDream.App.Tests/Rendering/FramePacingControllerTests.cs index fded1c1b..7d9eaf5b 100644 --- a/tests/AcDream.App.Tests/Rendering/FramePacingControllerTests.cs +++ b/tests/AcDream.App.Tests/Rendering/FramePacingControllerTests.cs @@ -119,6 +119,7 @@ public sealed class FramePacingControllerTests } [Fact] + [Trait("Lane", "Windows")] public void Windows_high_resolution_timer_arms_and_disposes_its_handle() { if (!OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134)) diff --git a/tests/AcDream.App.Tests/Rendering/HouseExitWalkReplayTests.cs b/tests/AcDream.App.Tests/Rendering/HouseExitWalkReplayTests.cs index ab1f1604..e16970a3 100644 --- a/tests/AcDream.App.Tests/Rendering/HouseExitWalkReplayTests.cs +++ b/tests/AcDream.App.Tests/Rendering/HouseExitWalkReplayTests.cs @@ -49,6 +49,7 @@ namespace AcDream.App.Tests.Rendering; /// OutsideView ⇒ outdoor dynamics trivially cone-pass). /// [Collection(CameraDiagnosticsCollection.Name)] +[Trait("Lane", "InstalledDat")] public class HouseExitWalkReplayTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.App.Tests/Rendering/Issue113DrawingBspFilterTests.cs b/tests/AcDream.App.Tests/Rendering/Issue113DrawingBspFilterTests.cs index a1c95cff..5cabba02 100644 --- a/tests/AcDream.App.Tests/Rendering/Issue113DrawingBspFilterTests.cs +++ b/tests/AcDream.App.Tests/Rendering/Issue113DrawingBspFilterTests.cs @@ -19,6 +19,7 @@ namespace AcDream.App.Tests.Rendering; /// iterated the dictionary and drew the "phantom staircase". These pins hold /// ObjectMeshManager.CollectDrawingBspPolygonIds to the dat facts. /// +[Trait("Lane", "InstalledDat")] public class Issue113DrawingBspFilterTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.App.Tests/Rendering/Issue113MeetingHallFloodTests.cs b/tests/AcDream.App.Tests/Rendering/Issue113MeetingHallFloodTests.cs index 14b0e6c3..7b379aba 100644 --- a/tests/AcDream.App.Tests/Rendering/Issue113MeetingHallFloodTests.cs +++ b/tests/AcDream.App.Tests/Rendering/Issue113MeetingHallFloodTests.cs @@ -29,6 +29,7 @@ namespace AcDream.App.Tests.Rendering; /// production assembler from the user's click-time viewpoint and pins which /// hall cells draw and with what clip. /// +[Trait("Lane", "InstalledDat")] public class Issue113MeetingHallFloodTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.App.Tests/Rendering/Issue120ReciprocalPingPongTests.cs b/tests/AcDream.App.Tests/Rendering/Issue120ReciprocalPingPongTests.cs index c1b86334..403f08a5 100644 --- a/tests/AcDream.App.Tests/Rendering/Issue120ReciprocalPingPongTests.cs +++ b/tests/AcDream.App.Tests/Rendering/Issue120ReciprocalPingPongTests.cs @@ -34,6 +34,7 @@ namespace AcDream.App.Tests.Rendering; /// contained polygons, which makes union growth strictly area-increasing and /// the flood convergent regardless of clip-numerics drift. /// +[Trait("Lane", "InstalledDat")] public class Issue120ReciprocalPingPongTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.App.Tests/Rendering/Issue124LookInSeedRegionTests.cs b/tests/AcDream.App.Tests/Rendering/Issue124LookInSeedRegionTests.cs index 75a964b1..775a8b9f 100644 --- a/tests/AcDream.App.Tests/Rendering/Issue124LookInSeedRegionTests.cs +++ b/tests/AcDream.App.Tests/Rendering/Issue124LookInSeedRegionTests.cs @@ -18,6 +18,7 @@ namespace AcDream.App.Tests.Rendering; /// seedRegion parameter — the port of that installed-view clip — against the /// real Holtburg corner-building door. /// +[Trait("Lane", "InstalledDat")] public class Issue124LookInSeedRegionTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.App.Tests/Rendering/Issue130DoorwayStripTests.cs b/tests/AcDream.App.Tests/Rendering/Issue130DoorwayStripTests.cs index 2f779822..4c643f8b 100644 --- a/tests/AcDream.App.Tests/Rendering/Issue130DoorwayStripTests.cs +++ b/tests/AcDream.App.Tests/Rendering/Issue130DoorwayStripTests.cs @@ -38,6 +38,7 @@ namespace AcDream.App.Tests.Rendering; /// cut). Fixed by the conservative NdcScissorRect bound; the assertions below /// pin both properties. /// +[Trait("Lane", "InstalledDat")] public class Issue130DoorwayStripTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.App.Tests/Rendering/Issue131SetupProbeTests.cs b/tests/AcDream.App.Tests/Rendering/Issue131SetupProbeTests.cs index 808c2ab1..7f6b7ccb 100644 --- a/tests/AcDream.App.Tests/Rendering/Issue131SetupProbeTests.cs +++ b/tests/AcDream.App.Tests/Rendering/Issue131SetupProbeTests.cs @@ -15,6 +15,7 @@ namespace AcDream.App.Tests.Rendering; /// translucent swirl; lamp posts / creatures / signs identify by part shape. /// [Trait("Purpose", "Diagnostic")] +[Trait("Lane", "InstalledDat")] public class Issue131SetupProbeTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.App.Tests/Rendering/Issue176177FacilityHubFloodReplayTests.cs b/tests/AcDream.App.Tests/Rendering/Issue176177FacilityHubFloodReplayTests.cs index e95dc97b..6307eecd 100644 --- a/tests/AcDream.App.Tests/Rendering/Issue176177FacilityHubFloodReplayTests.cs +++ b/tests/AcDream.App.Tests/Rendering/Issue176177FacilityHubFloodReplayTests.cs @@ -33,6 +33,7 @@ namespace AcDream.App.Tests.Rendering; /// D. #176 walk — eye tracks down the corridor across two seams, gaze /// locked +X: per-step admitted-set diffs (drop-for-one-step churn). /// +[Trait("Lane", "InstalledDat")] public class Issue176177FacilityHubFloodReplayTests { private const uint FacilityHub = 0x8A020000u; diff --git a/tests/AcDream.App.Tests/Rendering/Issue177StairDescentCameraFloodTests.cs b/tests/AcDream.App.Tests/Rendering/Issue177StairDescentCameraFloodTests.cs index f10f0bc7..357f5a96 100644 --- a/tests/AcDream.App.Tests/Rendering/Issue177StairDescentCameraFloodTests.cs +++ b/tests/AcDream.App.Tests/Rendering/Issue177StairDescentCameraFloodTests.cs @@ -32,6 +32,7 @@ namespace AcDream.App.Tests.Rendering; /// admitted, the flood is exonerated and the artifact lives downstream. /// [Collection(CameraDiagnosticsCollection.Name)] +[Trait("Lane", "InstalledDat")] public class Issue177StairDescentCameraFloodTests { private const uint FacilityHub = 0x8A020000u; diff --git a/tests/AcDream.App.Tests/Rendering/Issue181VisFlapReplayTests.cs b/tests/AcDream.App.Tests/Rendering/Issue181VisFlapReplayTests.cs index c1da7914..d6e4efec 100644 --- a/tests/AcDream.App.Tests/Rendering/Issue181VisFlapReplayTests.cs +++ b/tests/AcDream.App.Tests/Rendering/Issue181VisFlapReplayTests.cs @@ -22,6 +22,7 @@ namespace AcDream.App.Tests.Rendering; /// axis; ANY admitted-set difference at sub-mm perturbation is the #181 /// instability, and the symmetric difference names the flapping cell. /// +[Trait("Lane", "InstalledDat")] public class Issue181VisFlapReplayTests { private const uint FacilityHub = 0x8A020000u; diff --git a/tests/AcDream.App.Tests/Rendering/Issue181WallPressEquilibriumTests.cs b/tests/AcDream.App.Tests/Rendering/Issue181WallPressEquilibriumTests.cs index 3930723d..5f5fee5b 100644 --- a/tests/AcDream.App.Tests/Rendering/Issue181WallPressEquilibriumTests.cs +++ b/tests/AcDream.App.Tests/Rendering/Issue181WallPressEquilibriumTests.cs @@ -33,6 +33,7 @@ namespace AcDream.App.Tests.Rendering; /// [Collection(CameraDiagnosticsCollection.Name)] [Trait("Purpose", "Diagnostic")] +[Trait("Lane", "InstalledDat")] public class Issue181WallPressEquilibriumTests { private const uint FacilityHubLandblock = 0x8A020000u; diff --git a/tests/AcDream.App.Tests/Rendering/Issue95DungeonFloodDiagnosticTests.cs b/tests/AcDream.App.Tests/Rendering/Issue95DungeonFloodDiagnosticTests.cs index 5e5f1228..a1bce2f9 100644 --- a/tests/AcDream.App.Tests/Rendering/Issue95DungeonFloodDiagnosticTests.cs +++ b/tests/AcDream.App.Tests/Rendering/Issue95DungeonFloodDiagnosticTests.cs @@ -25,6 +25,7 @@ namespace AcDream.App.Tests.Rendering; /// root's stab_list size (), plus how many visited cells /// cross landblocks. The single assertion just guarantees the test ran; the VALUE is the output. /// +[Trait("Lane", "InstalledDat")] public class Issue95DungeonFloodDiagnosticTests { private const uint TownNetwork = 0x00070000u; diff --git a/tests/AcDream.App.Tests/Rendering/LinuxMonotonicFramePacingWaiterTests.cs b/tests/AcDream.App.Tests/Rendering/LinuxMonotonicFramePacingWaiterTests.cs index 53876839..e62336fd 100644 --- a/tests/AcDream.App.Tests/Rendering/LinuxMonotonicFramePacingWaiterTests.cs +++ b/tests/AcDream.App.Tests/Rendering/LinuxMonotonicFramePacingWaiterTests.cs @@ -48,6 +48,7 @@ public sealed class LinuxMonotonicFramePacingWaiterTests } [Fact] + [Trait("Lane", "Linux")] public void LinuxWaitBlocksUntilRequestedMonotonicDeadline() { if (!OperatingSystem.IsLinux()) @@ -70,6 +71,7 @@ public sealed class LinuxMonotonicFramePacingWaiterTests } [Fact] + [Trait("Lane", "Linux")] public void LinuxWaiterRejectsUseAfterDisposal() { if (!OperatingSystem.IsLinux()) diff --git a/tests/AcDream.App.Tests/Rendering/PortalTunnelAssetTests.cs b/tests/AcDream.App.Tests/Rendering/PortalTunnelAssetTests.cs index 1a825b82..a913d15d 100644 --- a/tests/AcDream.App.Tests/Rendering/PortalTunnelAssetTests.cs +++ b/tests/AcDream.App.Tests/Rendering/PortalTunnelAssetTests.cs @@ -52,6 +52,7 @@ public sealed class PortalTunnelAssetTests } [Fact] + [Trait("Lane", "InstalledDat")] public void InstalledDat_ResolvesRetailPortalSetupAndAnimation() { string? datDir = ResolveDatDir(); diff --git a/tests/AcDream.App.Tests/Rendering/RetailParticleGeometryClassifierTests.cs b/tests/AcDream.App.Tests/Rendering/RetailParticleGeometryClassifierTests.cs index f1a2f6e9..0a1f7421 100644 --- a/tests/AcDream.App.Tests/Rendering/RetailParticleGeometryClassifierTests.cs +++ b/tests/AcDream.App.Tests/Rendering/RetailParticleGeometryClassifierTests.cs @@ -206,6 +206,7 @@ public sealed class RetailParticleGeometryClassifierTests } [Fact] + [Trait("Lane", "InstalledDat")] public void InstalledArmorSelfShieldPieces_areModeOneMeshesWithAuthoredApexFaces() { string? datDir = ResolveDatDir(); @@ -264,6 +265,7 @@ public sealed class RetailParticleGeometryClassifierTests } [Fact] + [Trait("Lane", "InstalledDat")] public void InstalledHumanEffectTable_MapsPortalVisibilityScripts() { string? datDir = ResolveDatDir(); @@ -278,6 +280,7 @@ public sealed class RetailParticleGeometryClassifierTests } [Fact] + [Trait("Lane", "InstalledDat")] public void InstalledAerlintheSwarmEmitter_UsesItsHardwareGfxDegradeDistance() { string? datDir = ResolveDatDir(); diff --git a/tests/AcDream.App.Tests/Rendering/RetailSelectionAssetTests.cs b/tests/AcDream.App.Tests/Rendering/RetailSelectionAssetTests.cs index 8a6f3c61..8be5c77e 100644 --- a/tests/AcDream.App.Tests/Rendering/RetailSelectionAssetTests.cs +++ b/tests/AcDream.App.Tests/Rendering/RetailSelectionAssetTests.cs @@ -16,6 +16,7 @@ namespace AcDream.App.Tests.Rendering; public sealed class RetailSelectionAssetTests { [Fact] + [Trait("Lane", "InstalledDat")] public void InstalledDat_ResolvesAllTwelveVividTargetImages() { string datDir = ResolveDatDir(); @@ -58,6 +59,7 @@ public sealed class RetailSelectionAssetTests } [Fact] + [Trait("Lane", "InstalledDat")] public void DoorSelectionGeometry_UsesDrawingBspRootSphereAndDatPolygonOrder() { const uint doorGfxObjId = 0x010044B5u; diff --git a/tests/AcDream.App.Tests/Streaming/LandblockBuildFactoryTests.cs b/tests/AcDream.App.Tests/Streaming/LandblockBuildFactoryTests.cs index 0fc1c0c0..64cd75d1 100644 --- a/tests/AcDream.App.Tests/Streaming/LandblockBuildFactoryTests.cs +++ b/tests/AcDream.App.Tests/Streaming/LandblockBuildFactoryTests.cs @@ -318,6 +318,7 @@ public sealed class LandblockBuildFactoryTests } [Fact] + [Trait("Lane", "PreparedPackage")] public void InstalledDatNearBuild_IsDeterministicAndClosesEntityPhysicsPayload() { string? datDirectory = ResolveDatDirectory(); diff --git a/tests/AcDream.App.Tests/UI/IconComposerTests.cs b/tests/AcDream.App.Tests/UI/IconComposerTests.cs index ba35d60d..619b91eb 100644 --- a/tests/AcDream.App.Tests/UI/IconComposerTests.cs +++ b/tests/AcDream.App.Tests/UI/IconComposerTests.cs @@ -75,6 +75,7 @@ public class IconComposerTests } [Fact] + [Trait("Lane", "InstalledDat")] public void ResolveUnderlayDid_goldenValues_matchDat() { var datDir = ResolveDatDir(); @@ -103,6 +104,7 @@ public class IconComposerTests } [Fact] + [Trait("Lane", "InstalledDat")] public void ResolveEffectDid_goldenValues_matchDat() { var datDir = ResolveDatDir(); @@ -128,6 +130,7 @@ public class IconComposerTests } [Fact] + [Trait("Lane", "InstalledDat")] public void TryGetEffectTile_noEffectBlack_magicalTextured() { var datDir = ResolveDatDir(); diff --git a/tests/AcDream.App.Tests/UI/Layout/CharacterLayoutImportProbe.cs b/tests/AcDream.App.Tests/UI/Layout/CharacterLayoutImportProbe.cs index 73d3d0c7..352098b0 100644 --- a/tests/AcDream.App.Tests/UI/Layout/CharacterLayoutImportProbe.cs +++ b/tests/AcDream.App.Tests/UI/Layout/CharacterLayoutImportProbe.cs @@ -11,6 +11,7 @@ using Xunit; namespace AcDream.App.Tests.UI.Layout; +[Trait("Lane", "InstalledDat")] public sealed class CharacterLayoutImportProbe { private const uint CharacterLayout = 0x2100002Eu; diff --git a/tests/AcDream.App.Tests/UI/Layout/ChatIndicatorButtonLiveMountProbeTests.cs b/tests/AcDream.App.Tests/UI/Layout/ChatIndicatorButtonLiveMountProbeTests.cs index 57ef524b..1fbc6e1f 100644 --- a/tests/AcDream.App.Tests/UI/Layout/ChatIndicatorButtonLiveMountProbeTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/ChatIndicatorButtonLiveMountProbeTests.cs @@ -54,6 +54,7 @@ namespace AcDream.App.Tests.UI.Layout; /// see its own class doc) are unaffected. /// /// +[Trait("Lane", "InstalledDat")] public sealed class ChatIndicatorButtonLiveMountProbeTests { [Fact] diff --git a/tests/AcDream.App.Tests/UI/Layout/ChatOptionsDatDefaultsTests.cs b/tests/AcDream.App.Tests/UI/Layout/ChatOptionsDatDefaultsTests.cs index a3638377..e28b9693 100644 --- a/tests/AcDream.App.Tests/UI/Layout/ChatOptionsDatDefaultsTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/ChatOptionsDatDefaultsTests.cs @@ -16,6 +16,7 @@ namespace AcDream.App.Tests.UI.Layout; public sealed class ChatOptionsDatDefaultsTests { [Fact] + [Trait("Lane", "InstalledDat")] public void InstalledDat_ResolvesTheByteVerifiedSliderDefaults() { string datDir = ResolveDatDir(); diff --git a/tests/AcDream.App.Tests/UI/Layout/FaPanelSlotProbeTests.cs b/tests/AcDream.App.Tests/UI/Layout/FaPanelSlotProbeTests.cs index afee951e..5a8e0520 100644 --- a/tests/AcDream.App.Tests/UI/Layout/FaPanelSlotProbeTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/FaPanelSlotProbeTests.cs @@ -15,6 +15,7 @@ namespace AcDream.App.Tests.UI.Layout; /// and 0x10000263 (swear-allegiance button). Env-gated like the other probes. /// [Trait("Purpose", "Diagnostic")] +[Trait("Lane", "InstalledDat")] public sealed class FaPanelSlotProbeTests { [Fact] diff --git a/tests/AcDream.App.Tests/UI/Layout/InventoryFrameImportProbe.cs b/tests/AcDream.App.Tests/UI/Layout/InventoryFrameImportProbe.cs index 32e074fe..3925141e 100644 --- a/tests/AcDream.App.Tests/UI/Layout/InventoryFrameImportProbe.cs +++ b/tests/AcDream.App.Tests/UI/Layout/InventoryFrameImportProbe.cs @@ -18,6 +18,7 @@ namespace AcDream.App.Tests.UI.Layout; /// backdrop (ZLevel 100 → ≈ −1,000,000), and the backdrop washed out the panels' captions, /// burden meter, and item cells. Skips when the live dat directory is absent (CI). /// +[Trait("Lane", "InstalledDat")] public class InventoryFrameImportProbe { private const uint Frame = 0x21000023u; diff --git a/tests/AcDream.App.Tests/UI/Layout/ItemAppraisalTextFormatterTests.cs b/tests/AcDream.App.Tests/UI/Layout/ItemAppraisalTextFormatterTests.cs index 24e4fe75..e4d66bd5 100644 --- a/tests/AcDream.App.Tests/UI/Layout/ItemAppraisalTextFormatterTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/ItemAppraisalTextFormatterTests.cs @@ -749,6 +749,7 @@ public sealed class ItemAppraisalTextFormatterTests } [Fact] + [Trait("Lane", "InstalledDat")] public void EndOfRetailDatNameResolver_LoadsMaterialAndCreatureNames() { string? datDirectory = ResolveDatDirectory(); diff --git a/tests/AcDream.App.Tests/UI/Layout/ItemListCellTemplateTests.cs b/tests/AcDream.App.Tests/UI/Layout/ItemListCellTemplateTests.cs index 635364b9..f4facea0 100644 --- a/tests/AcDream.App.Tests/UI/Layout/ItemListCellTemplateTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/ItemListCellTemplateTests.cs @@ -15,6 +15,7 @@ namespace AcDream.App.Tests.UI.Layout; /// square 0x060074CF. Also PRINTS the resolved ids — the "pin the exact asset" record. /// Skips when the live dat directory is absent (CI). /// +[Trait("Lane", "InstalledDat")] public class ItemListCellTemplateTests { private const uint Generic = 0x060074CFu; // generic toolbar-shortcut empty square (the bug) diff --git a/tests/AcDream.App.Tests/UI/Layout/KeyboardConfigLiveMountProbeTests.cs b/tests/AcDream.App.Tests/UI/Layout/KeyboardConfigLiveMountProbeTests.cs index c5ec5d80..2ba9e7da 100644 --- a/tests/AcDream.App.Tests/UI/Layout/KeyboardConfigLiveMountProbeTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/KeyboardConfigLiveMountProbeTests.cs @@ -16,6 +16,7 @@ namespace AcDream.App.Tests.UI.Layout; /// rect + caption evidence for each observation. Env-gated like the other /// live probes so CI/dat-less runs skip it. /// +[Trait("Lane", "InstalledDat")] public sealed class KeyboardConfigLiveMountProbeTests { [Fact] diff --git a/tests/AcDream.App.Tests/UI/Layout/MapHousePanelSlotProbeTests.cs b/tests/AcDream.App.Tests/UI/Layout/MapHousePanelSlotProbeTests.cs index e9696d0f..18b02e1e 100644 --- a/tests/AcDream.App.Tests/UI/Layout/MapHousePanelSlotProbeTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/MapHousePanelSlotProbeTests.cs @@ -26,6 +26,7 @@ namespace AcDream.App.Tests.UI.Layout; /// /// [Trait("Purpose", "Diagnostic")] +[Trait("Lane", "InstalledDat")] public sealed class MapHousePanelSlotProbeTests { private const uint HostLayoutId = 0x2100006Eu; diff --git a/tests/AcDream.App.Tests/UI/Layout/OptionsPanelLiveMountProbeTests.cs b/tests/AcDream.App.Tests/UI/Layout/OptionsPanelLiveMountProbeTests.cs index 540ab27d..7fca9a45 100644 --- a/tests/AcDream.App.Tests/UI/Layout/OptionsPanelLiveMountProbeTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/OptionsPanelLiveMountProbeTests.cs @@ -16,6 +16,7 @@ namespace AcDream.App.Tests.UI.Layout; /// page controller actually resolves. Env-gated like the fixture /// generator so CI/dat-less runs skip it. /// +[Trait("Lane", "InstalledDat")] public sealed class OptionsPanelLiveMountProbeTests { [Fact] diff --git a/tests/AcDream.App.Tests/UI/Layout/PaperdollClickMapTests.cs b/tests/AcDream.App.Tests/UI/Layout/PaperdollClickMapTests.cs index 44fc107c..e9c85a2c 100644 --- a/tests/AcDream.App.Tests/UI/Layout/PaperdollClickMapTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/PaperdollClickMapTests.cs @@ -45,6 +45,7 @@ public sealed class PaperdollClickMapTests } [Fact] + [Trait("Lane", "InstalledDat")] public void LiveDat_resolvesRetailClickMapAndAllNineBodyRegions() { string datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR") diff --git a/tests/AcDream.App.Tests/UI/Layout/PaperdollSlotBackgroundTests.cs b/tests/AcDream.App.Tests/UI/Layout/PaperdollSlotBackgroundTests.cs index d641952b..90999c0c 100644 --- a/tests/AcDream.App.Tests/UI/Layout/PaperdollSlotBackgroundTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/PaperdollSlotBackgroundTests.cs @@ -47,6 +47,7 @@ public class PaperdollSlotBackgroundTests } [Fact] + [Trait("Lane", "InstalledDat")] public void Live_dat_resolves_all_pinned_retail_backgrounds() { string datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR") diff --git a/tests/AcDream.App.Tests/UI/Layout/PowerbarLayoutProbeTests.cs b/tests/AcDream.App.Tests/UI/Layout/PowerbarLayoutProbeTests.cs index 7a79ea84..22ede98e 100644 --- a/tests/AcDream.App.Tests/UI/Layout/PowerbarLayoutProbeTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/PowerbarLayoutProbeTests.cs @@ -15,6 +15,7 @@ namespace AcDream.App.Tests.UI.Layout; /// INSTALLED DAT, so the "Height"/"Power"/"Accuracy" fix binds exactly what /// retail authors instead of guessing. /// +[Trait("Lane", "InstalledDat")] public sealed class PowerbarLayoutProbeTests { [Fact] diff --git a/tests/AcDream.App.Tests/UI/Layout/SocialPanelLiveMountProbeTests.cs b/tests/AcDream.App.Tests/UI/Layout/SocialPanelLiveMountProbeTests.cs index 5e4eeb8f..2fe07b29 100644 --- a/tests/AcDream.App.Tests/UI/Layout/SocialPanelLiveMountProbeTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/SocialPanelLiveMountProbeTests.cs @@ -18,6 +18,7 @@ namespace AcDream.App.Tests.UI.Layout; /// its button→page pairing + default entry can be recorded — coordinator /// addendum, docs/research/2026-08-11-fa-panel-structure.md §10. /// +[Trait("Lane", "InstalledDat")] public sealed class SocialPanelLiveMountProbeTests { [Fact] diff --git a/tests/AcDream.App.Tests/UI/Layout/SpellbookRowStyleTests.cs b/tests/AcDream.App.Tests/UI/Layout/SpellbookRowStyleTests.cs index 5adbab21..60cf82e7 100644 --- a/tests/AcDream.App.Tests/UI/Layout/SpellbookRowStyleTests.cs +++ b/tests/AcDream.App.Tests/UI/Layout/SpellbookRowStyleTests.cs @@ -4,6 +4,7 @@ using DatReaderWriter.Options; namespace AcDream.App.Tests.UI.Layout; +[Trait("Lane", "InstalledDat")] public sealed class SpellbookRowStyleTests { [Fact] diff --git a/tests/AcDream.App.Tests/UI/RetailCursorCatalogTests.cs b/tests/AcDream.App.Tests/UI/RetailCursorCatalogTests.cs index 8a34765b..ea6aad85 100644 --- a/tests/AcDream.App.Tests/UI/RetailCursorCatalogTests.cs +++ b/tests/AcDream.App.Tests/UI/RetailCursorCatalogTests.cs @@ -24,6 +24,7 @@ public sealed class RetailCursorCatalogTests } [Fact] + [Trait("Lane", "InstalledDat")] public void WindowControlCursorSpecs_resolveGoldenDatSurfaces() { string? datDir = ResolveDatDir(); @@ -82,6 +83,7 @@ public sealed class RetailCursorCatalogTests } [Fact] + [Trait("Lane", "InstalledDat")] public void ReachableGlobalCursorSpecs_resolveGoldenDatSurfaces() { string? datDir = ResolveDatDir(); diff --git a/tests/AcDream.App.Tests/UI/SpewBoxLayoutDumpDiagnostic.cs b/tests/AcDream.App.Tests/UI/SpewBoxLayoutDumpDiagnostic.cs index 6d47c7ec..3d575f65 100644 --- a/tests/AcDream.App.Tests/UI/SpewBoxLayoutDumpDiagnostic.cs +++ b/tests/AcDream.App.Tests/UI/SpewBoxLayoutDumpDiagnostic.cs @@ -76,6 +76,7 @@ namespace AcDream.App.Tests.UI; /// /// [Trait("Purpose", "Diagnostic")] +[Trait("Lane", "InstalledDat")] public sealed class SpewBoxLayoutDumpDiagnostic { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.App.Tests/UI/UiDatFontBorderPixelTests.cs b/tests/AcDream.App.Tests/UI/UiDatFontBorderPixelTests.cs index a89293e2..01588929 100644 --- a/tests/AcDream.App.Tests/UI/UiDatFontBorderPixelTests.cs +++ b/tests/AcDream.App.Tests/UI/UiDatFontBorderPixelTests.cs @@ -35,6 +35,7 @@ public sealed class UiDatFontBorderPixelTests [InlineData(0x40000001u, 4u, 4u)] // 18px bold serif — SpewBox face (round 4) [InlineData(0x40000002u, 3u, 3u)] // 14px bold serif [InlineData(0x40000025u, 3u, 3u)] // 11px — the pre-round-4 SpewBox placeholder face + [Trait("Lane", "InstalledDat")] public void RealDatFont_HasExpectedBorderPixels(uint fontId, uint expectedHorizontal, uint expectedVertical) { string? datDir = ResolveDatDir(); @@ -49,6 +50,7 @@ public sealed class UiDatFontBorderPixelTests } [Fact] + [Trait("Lane", "InstalledDat")] public void RealDatFont_EveryFontWithABackgroundAtlas_HasANonZeroBorder() { // docs/research/2026-08-10-retail-ui-text-style.md §1.2: "every font that diff --git a/tests/AcDream.App.Tests/UI/UiRenderContextAlphaTests.cs b/tests/AcDream.App.Tests/UI/UiRenderContextAlphaTests.cs index f152b8da..aed10073 100644 --- a/tests/AcDream.App.Tests/UI/UiRenderContextAlphaTests.cs +++ b/tests/AcDream.App.Tests/UI/UiRenderContextAlphaTests.cs @@ -237,6 +237,7 @@ public sealed class UiRenderContextAlphaTests // -- DrawString (BitmapFont path): the same alpha chokepoint, guarded --- [Fact] + [Trait("Lane", "SystemFont")] public void FullOpacity_DrawString_BitmapFontPath_MatchesRequestedAlpha_Identity() { // CH6c review NIT: DrawStringDat (retail dat-font glyphs) had its own @@ -258,6 +259,7 @@ public sealed class UiRenderContextAlphaTests } [Fact] + [Trait("Lane", "SystemFont")] public void HalfOpacityWindow_MultipliesBitmapFontGlyphAlpha() { var device = new RecordingGpuDevice(); diff --git a/tests/AcDream.App.Tests/World/LiveEntityPresentationControllerTests.cs b/tests/AcDream.App.Tests/World/LiveEntityPresentationControllerTests.cs index b5864daf..9256b77b 100644 --- a/tests/AcDream.App.Tests/World/LiveEntityPresentationControllerTests.cs +++ b/tests/AcDream.App.Tests/World/LiveEntityPresentationControllerTests.cs @@ -145,6 +145,7 @@ public sealed class LiveEntityPresentationControllerTests } [Fact] + [Trait("Lane", "InstalledDat")] public void SpellRecall_HiddenAndUnHide_RetireMagicTimelineThroughController() { const uint humanSetup = 0x02000001u; diff --git a/tests/AcDream.App.Tests/World/RecallTeleportAnimationTests.cs b/tests/AcDream.App.Tests/World/RecallTeleportAnimationTests.cs index bcdc8ee0..afc65343 100644 --- a/tests/AcDream.App.Tests/World/RecallTeleportAnimationTests.cs +++ b/tests/AcDream.App.Tests/World/RecallTeleportAnimationTests.cs @@ -185,6 +185,7 @@ public sealed class RecallTeleportAnimationTests } [Fact] + [Trait("Lane", "InstalledDat")] public void InstalledRecall_HiddenEnterWorldPublishesFinishedCyclicPoseWithoutAdvancingTime() { string datDir = @"C:\Turbine\Asheron's Call"; diff --git a/tests/AcDream.Bake.Tests/BakeDeterminismTests.cs b/tests/AcDream.Bake.Tests/BakeDeterminismTests.cs index 894e742f..39f2659f 100644 --- a/tests/AcDream.Bake.Tests/BakeDeterminismTests.cs +++ b/tests/AcDream.Bake.Tests/BakeDeterminismTests.cs @@ -15,6 +15,7 @@ namespace AcDream.Bake.Tests; /// are absent (CI), same convention as /// tests/AcDream.Core.Tests/Conformance/DatConcurrencyStressTests. /// +[Trait("Lane", "InstalledDat")] public sealed class BakeDeterminismTests : IDisposable { private readonly List _tempFiles = new(); diff --git a/tests/AcDream.Content.Tests/Ap155StaticSpherePopulationMeasurementTests.cs b/tests/AcDream.Content.Tests/Ap155StaticSpherePopulationMeasurementTests.cs index 00896777..935f9248 100644 --- a/tests/AcDream.Content.Tests/Ap155StaticSpherePopulationMeasurementTests.cs +++ b/tests/AcDream.Content.Tests/Ap155StaticSpherePopulationMeasurementTests.cs @@ -23,6 +23,7 @@ namespace AcDream.Content.Tests; /// of the 3,605 "sphere-only, no cylinder" Setups the reachability sweep /// already counted fall into exactly that trap. /// +[Trait("Lane", "InstalledDat")] public sealed class Ap155StaticSpherePopulationMeasurementTests { [Fact] diff --git a/tests/AcDream.Content.Tests/CharGen/ChargenAppearanceCatalogColorTests.cs b/tests/AcDream.Content.Tests/CharGen/ChargenAppearanceCatalogColorTests.cs index 75666ece..447d923b 100644 --- a/tests/AcDream.Content.Tests/CharGen/ChargenAppearanceCatalogColorTests.cs +++ b/tests/AcDream.Content.Tests/CharGen/ChargenAppearanceCatalogColorTests.cs @@ -22,6 +22,7 @@ namespace AcDream.Content.Tests.CharGen; /// ChargenAppearanceCatalogInstalledDatTests): returns green with a /// console SKIP note when no installed dat directory is configured. /// +[Trait("Lane", "InstalledDat")] public sealed class ChargenAppearanceCatalogColorTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Content.Tests/CharGen/ChargenAppearanceCatalogInstalledDatTests.cs b/tests/AcDream.Content.Tests/CharGen/ChargenAppearanceCatalogInstalledDatTests.cs index 98c0d0a4..0c66b5ac 100644 --- a/tests/AcDream.Content.Tests/CharGen/ChargenAppearanceCatalogInstalledDatTests.cs +++ b/tests/AcDream.Content.Tests/CharGen/ChargenAppearanceCatalogInstalledDatTests.cs @@ -28,6 +28,7 @@ namespace AcDream.Content.Tests.CharGen; /// consistent with the rest of the suite rather than introducing a new /// convention. /// +[Trait("Lane", "InstalledDat")] public sealed class ChargenAppearanceCatalogInstalledDatTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Content.Tests/CharGen/ChargenTableReaderInstalledDatTests.cs b/tests/AcDream.Content.Tests/CharGen/ChargenTableReaderInstalledDatTests.cs index 60a015f5..cab1bd8f 100644 --- a/tests/AcDream.Content.Tests/CharGen/ChargenTableReaderInstalledDatTests.cs +++ b/tests/AcDream.Content.Tests/CharGen/ChargenTableReaderInstalledDatTests.cs @@ -14,6 +14,7 @@ namespace AcDream.Content.Tests.CharGen; /// cleanly (with a console note) when no DAT directory is configured, /// matching e.g. PakEquivalenceTests / RetailDatLoaderTests. /// +[Trait("Lane", "InstalledDat")] public sealed class ChargenTableReaderInstalledDatTests { // ACE ACE.Entity.Enum.HeritageGroup — the four heritages CC1's spec diff --git a/tests/AcDream.Content.Tests/InstalledPreparedCollisionCatalogTests.cs b/tests/AcDream.Content.Tests/InstalledPreparedCollisionCatalogTests.cs index 04bff25c..8fcb9963 100644 --- a/tests/AcDream.Content.Tests/InstalledPreparedCollisionCatalogTests.cs +++ b/tests/AcDream.Content.Tests/InstalledPreparedCollisionCatalogTests.cs @@ -4,6 +4,7 @@ using DatReaderWriter.Options; namespace AcDream.Content.Tests; +[Trait("Lane", "PreparedPackage")] public sealed class InstalledPreparedCollisionCatalogTests { [Fact] diff --git a/tests/AcDream.Content.Tests/InstalledSetupBspPrimitiveDispatchTests.cs b/tests/AcDream.Content.Tests/InstalledSetupBspPrimitiveDispatchTests.cs index 7343f4d7..f7d96d5b 100644 --- a/tests/AcDream.Content.Tests/InstalledSetupBspPrimitiveDispatchTests.cs +++ b/tests/AcDream.Content.Tests/InstalledSetupBspPrimitiveDispatchTests.cs @@ -33,6 +33,7 @@ namespace AcDream.Content.Tests; /// predicate used here. /// /// +[Trait("Lane", "InstalledDat")] public sealed class InstalledSetupBspPrimitiveDispatchTests { // EXTERNAL constants. The four bucket controls are the ones already diff --git a/tests/AcDream.Content.Tests/InstalledSetupCollisionReachabilityTests.cs b/tests/AcDream.Content.Tests/InstalledSetupCollisionReachabilityTests.cs index 576643a0..4a2f1686 100644 --- a/tests/AcDream.Content.Tests/InstalledSetupCollisionReachabilityTests.cs +++ b/tests/AcDream.Content.Tests/InstalledSetupCollisionReachabilityTests.cs @@ -12,6 +12,7 @@ namespace AcDream.Content.Tests; /// asserts no such Setup exists, so the deletion cannot remove collision from /// any real object. /// +[Trait("Lane", "InstalledDat")] public sealed class InstalledSetupCollisionReachabilityTests { // Positive controls. These are EXTERNAL constants, measured on 2026-08-06 diff --git a/tests/AcDream.Content.Tests/Issue334NeftetFormationCellMembershipTests.cs b/tests/AcDream.Content.Tests/Issue334NeftetFormationCellMembershipTests.cs index a430c835..1c5a115c 100644 --- a/tests/AcDream.Content.Tests/Issue334NeftetFormationCellMembershipTests.cs +++ b/tests/AcDream.Content.Tests/Issue334NeftetFormationCellMembershipTests.cs @@ -42,6 +42,7 @@ namespace AcDream.Content.Tests; /// columns 0..4 on both axes. /// /// +[Trait("Lane", "InstalledDat")] public sealed class Issue334NeftetFormationCellMembershipTests { private const uint NeftetLandblock = 0x87640000u; diff --git a/tests/AcDream.Content.Tests/PakEquivalenceTests.cs b/tests/AcDream.Content.Tests/PakEquivalenceTests.cs index e1cf99c4..905b2c24 100644 --- a/tests/AcDream.Content.Tests/PakEquivalenceTests.cs +++ b/tests/AcDream.Content.Tests/PakEquivalenceTests.cs @@ -20,6 +20,7 @@ namespace AcDream.Content.Tests; /// Skips cleanly when the real dats are absent (CI), matching /// DatConcurrencyStressTests' convention. /// +[Trait("Lane", "InstalledDat")] public sealed class PakEquivalenceTests { // Known-tricky GfxObj ids reused from existing conformance fixtures: // 0x010002B4 / 0x010008A8 — #119 "[up-null] upload returned null" dump diff --git a/tests/AcDream.Content.Tests/SolidColorTextureCacheTests.cs b/tests/AcDream.Content.Tests/SolidColorTextureCacheTests.cs index b4b2ea3c..f8281cc8 100644 --- a/tests/AcDream.Content.Tests/SolidColorTextureCacheTests.cs +++ b/tests/AcDream.Content.Tests/SolidColorTextureCacheTests.cs @@ -17,6 +17,7 @@ namespace AcDream.Content.Tests; /// construct (its ctor builds a RetailPhysicsScriptLoader from dats.Portal). /// Skips cleanly when dats are absent, matching ContentConformanceDats convention. /// +[Trait("Lane", "InstalledDat")] public sealed class SolidColorTextureCacheTests { [Fact] public void GetOrCreateSolidColorTexture_SameColor_ReturnsSameSharedArray() { diff --git a/tests/AcDream.Content.Tests/Spells/RetailSpellMetadataProjectorTests.cs b/tests/AcDream.Content.Tests/Spells/RetailSpellMetadataProjectorTests.cs index 23d1a8b0..2a8517a5 100644 --- a/tests/AcDream.Content.Tests/Spells/RetailSpellMetadataProjectorTests.cs +++ b/tests/AcDream.Content.Tests/Spells/RetailSpellMetadataProjectorTests.cs @@ -73,6 +73,7 @@ public sealed class RetailSpellMetadataProjectorTests } [Fact] + [Trait("Lane", "InstalledDat")] public void Load_EndOfRetailDat_ResolvesEveryLateLearnedSpellMissingFromCsv() { string? datDir = ResolveDatDir(); @@ -101,6 +102,7 @@ public sealed class RetailSpellMetadataProjectorTests } [Fact] + [Trait("Lane", "InstalledDat")] public void Load_EndOfRetailDat_UsesRetailFormulaTargetsInsteadOfLegacyExportMasks() { string? datDir = ResolveDatDir(); diff --git a/tests/AcDream.Content.Tests/Vfx/RetailDatLoaderTests.cs b/tests/AcDream.Content.Tests/Vfx/RetailDatLoaderTests.cs index 7594c5f6..3abf1950 100644 --- a/tests/AcDream.Content.Tests/Vfx/RetailDatLoaderTests.cs +++ b/tests/AcDream.Content.Tests/Vfx/RetailDatLoaderTests.cs @@ -432,6 +432,7 @@ public sealed class RetailDatLoaderTests } [Fact] + [Trait("Lane", "InstalledDat")] public void InstalledBlockingScripts_ParseThroughRetailShape_WhenDatsAvailable() { string? datDir = ResolveDatDirectory(); diff --git a/tests/AcDream.Core.Net.Tests/LiveHandshakeTests.cs b/tests/AcDream.Core.Net.Tests/LiveHandshakeTests.cs index 52ac51d6..f60caf53 100644 --- a/tests/AcDream.Core.Net.Tests/LiveHandshakeTests.cs +++ b/tests/AcDream.Core.Net.Tests/LiveHandshakeTests.cs @@ -29,6 +29,7 @@ namespace AcDream.Core.Net.Tests; /// the env-var setup are distinguishable from server errors. /// /// +[Trait("Lane", "Live")] public class LiveHandshakeTests { [Fact] diff --git a/tests/AcDream.Core.Tests/Audio/EnvCellSoundEmitterInventoryTests.cs b/tests/AcDream.Core.Tests/Audio/EnvCellSoundEmitterInventoryTests.cs index f9f1e24d..c0ccf4da 100644 --- a/tests/AcDream.Core.Tests/Audio/EnvCellSoundEmitterInventoryTests.cs +++ b/tests/AcDream.Core.Tests/Audio/EnvCellSoundEmitterInventoryTests.cs @@ -38,6 +38,7 @@ namespace AcDream.Core.Tests.Audio; /// absent. /// /// +[Trait("Lane", "InstalledDat")] public sealed class EnvCellSoundEmitterInventoryTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Audio/UiSoundTableResolutionTests.cs b/tests/AcDream.Core.Tests/Audio/UiSoundTableResolutionTests.cs index 3f7be452..11e62d90 100644 --- a/tests/AcDream.Core.Tests/Audio/UiSoundTableResolutionTests.cs +++ b/tests/AcDream.Core.Tests/Audio/UiSoundTableResolutionTests.cs @@ -38,6 +38,7 @@ namespace AcDream.Core.Tests.Audio; /// installed-dat test in this suite. /// /// +[Trait("Lane", "InstalledDat")] public sealed class UiSoundTableResolutionTests { /// diff --git a/tests/AcDream.Core.Tests/Conformance/CottageDoorwayCharacterizationTests.cs b/tests/AcDream.Core.Tests/Conformance/CottageDoorwayCharacterizationTests.cs index 43276346..7d6d4f39 100644 --- a/tests/AcDream.Core.Tests/Conformance/CottageDoorwayCharacterizationTests.cs +++ b/tests/AcDream.Core.Tests/Conformance/CottageDoorwayCharacterizationTests.cs @@ -15,6 +15,7 @@ namespace AcDream.Core.Tests.Conformance; /// not the master plan's loose "0031↔0170↔0171". The cottage cellar is the /// 0x014x range (#98 fixtures); the doorway room/vestibule is in 0x017x. /// +[Trait("Lane", "InstalledDat")] public class CottageDoorwayCharacterizationTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Conformance/DatConcurrencyStressTests.cs b/tests/AcDream.Core.Tests/Conformance/DatConcurrencyStressTests.cs index 542c7724..c0b0966a 100644 --- a/tests/AcDream.Core.Tests/Conformance/DatConcurrencyStressTests.cs +++ b/tests/AcDream.Core.Tests/Conformance/DatConcurrencyStressTests.cs @@ -39,6 +39,7 @@ namespace AcDream.Core.Tests.Conformance; /// (e.g. dispose-during-read at teardown) or layers above the dat reader. /// [Trait("Category", "Conformance")] +[Trait("Lane", "InstalledDat")] public class DatConcurrencyStressTests { private const int HammerThreads = 8; diff --git a/tests/AcDream.Core.Tests/Conformance/DungeonLandblockDatProbeTests.cs b/tests/AcDream.Core.Tests/Conformance/DungeonLandblockDatProbeTests.cs index 70d1307c..0ceeebd5 100644 --- a/tests/AcDream.Core.Tests/Conformance/DungeonLandblockDatProbeTests.cs +++ b/tests/AcDream.Core.Tests/Conformance/DungeonLandblockDatProbeTests.cs @@ -17,6 +17,7 @@ namespace AcDream.Core.Tests.Conformance; /// LandBlockInfo + EnvCells? Output-only — no assertions. /// [Trait("Purpose", "Diagnostic")] +[Trait("Lane", "InstalledDat")] public sealed class DungeonLandblockDatProbeTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Conformance/FindCellListConformanceTests.cs b/tests/AcDream.Core.Tests/Conformance/FindCellListConformanceTests.cs index 7e617e36..88e8a366 100644 --- a/tests/AcDream.Core.Tests/Conformance/FindCellListConformanceTests.cs +++ b/tests/AcDream.Core.Tests/Conformance/FindCellListConformanceTests.cs @@ -30,6 +30,7 @@ public class FindCellListConformanceTests } [Fact] + [Trait("Lane", "InstalledDat")] public void FindCellList_DeepInsideRoom0171_Returns0171() { var datDir = ConformanceDats.ResolveDatDir(); @@ -47,6 +48,7 @@ public class FindCellListConformanceTests } [Fact] + [Trait("Lane", "InstalledDat")] public void FindCellList_DeepInsideVestibule0170_Returns0170() { var datDir = ConformanceDats.ResolveDatDir(); @@ -70,6 +72,7 @@ public class FindCellListConformanceTests /// property P1 must preserve. /// [Fact] + [Trait("Lane", "InstalledDat")] public void FindCellList_InVestibule_SeededFromRoom_Returns0170() { var datDir = ConformanceDats.ResolveDatDir(); diff --git a/tests/AcDream.Core.Tests/Conformance/HoltburgTorchFalloffProbeTests.cs b/tests/AcDream.Core.Tests/Conformance/HoltburgTorchFalloffProbeTests.cs index dfd8ec02..9ce2922a 100644 --- a/tests/AcDream.Core.Tests/Conformance/HoltburgTorchFalloffProbeTests.cs +++ b/tests/AcDream.Core.Tests/Conformance/HoltburgTorchFalloffProbeTests.cs @@ -21,6 +21,7 @@ namespace AcDream.Core.Tests.Conformance; /// separately in the decomp). Output-only — no assertions; read the log. /// [Trait("Purpose", "Diagnostic")] +[Trait("Lane", "InstalledDat")] public sealed class HoltburgTorchFalloffProbeTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Conformance/Issue107SpawnDiagnosticTests.cs b/tests/AcDream.Core.Tests/Conformance/Issue107SpawnDiagnosticTests.cs index e171b324..bf9f3e7a 100644 --- a/tests/AcDream.Core.Tests/Conformance/Issue107SpawnDiagnosticTests.cs +++ b/tests/AcDream.Core.Tests/Conformance/Issue107SpawnDiagnosticTests.cs @@ -27,6 +27,7 @@ namespace AcDream.Core.Tests.Conformance; /// find_visible_child_cell also cannot recover a cross-building claim and /// falls to seen_outside → adjust_to_outside, acclient :280037). /// +[Trait("Lane", "InstalledDat")] public sealed class Issue107SpawnDiagnosticTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Conformance/Issue112MembershipTests.cs b/tests/AcDream.Core.Tests/Conformance/Issue112MembershipTests.cs index 5141770e..6d728430 100644 --- a/tests/AcDream.Core.Tests/Conformance/Issue112MembershipTests.cs +++ b/tests/AcDream.Core.Tests/Conformance/Issue112MembershipTests.cs @@ -19,6 +19,7 @@ namespace AcDream.Core.Tests.Conformance; /// (pc:308788-308825). These tests pin the replacement semantics against the /// real dats. /// +[Trait("Lane", "InstalledDat")] public sealed class Issue112MembershipTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Conformance/Issue113DoorVanishDiagnosticTests.cs b/tests/AcDream.Core.Tests/Conformance/Issue113DoorVanishDiagnosticTests.cs index 010b13c5..c14b3d02 100644 --- a/tests/AcDream.Core.Tests/Conformance/Issue113DoorVanishDiagnosticTests.cs +++ b/tests/AcDream.Core.Tests/Conformance/Issue113DoorVanishDiagnosticTests.cs @@ -21,6 +21,7 @@ namespace AcDream.Core.Tests.Conformance; /// carry polygon references in properties the walk missed (portal-type /// nodes / leaf subclasses)? Pure diagnostic — no production code. /// +[Trait("Lane", "InstalledDat")] public sealed class Issue113DoorVanishDiagnosticTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Conformance/Issue113PhantomStairsDumpTests.cs b/tests/AcDream.Core.Tests/Conformance/Issue113PhantomStairsDumpTests.cs index 91545d8c..1d44bc9a 100644 --- a/tests/AcDream.Core.Tests/Conformance/Issue113PhantomStairsDumpTests.cs +++ b/tests/AcDream.Core.Tests/Conformance/Issue113PhantomStairsDumpTests.cs @@ -24,6 +24,7 @@ namespace AcDream.Core.Tests.Conformance; /// interior cell's Position + world AABB + SeenOutside flag + stair signature /// (distinct horizontal-face heights), and containment of the two key points. /// +[Trait("Lane", "InstalledDat")] public sealed class Issue113PhantomStairsDumpTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Conformance/Issue119TowerDumpTests.cs b/tests/AcDream.Core.Tests/Conformance/Issue119TowerDumpTests.cs index 6f011285..c8f09929 100644 --- a/tests/AcDream.Core.Tests/Conformance/Issue119TowerDumpTests.cs +++ b/tests/AcDream.Core.Tests/Conformance/Issue119TowerDumpTests.cs @@ -24,6 +24,7 @@ namespace AcDream.Core.Tests.Conformance; /// static object (id + position) — the barrel candidate and the stair /// owners read directly off the output. /// +[Trait("Lane", "InstalledDat")] public sealed class Issue119TowerDumpTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Conformance/Issue119UpNullGfxObjDumpTests.cs b/tests/AcDream.Core.Tests/Conformance/Issue119UpNullGfxObjDumpTests.cs index 0b123199..51a23fc3 100644 --- a/tests/AcDream.Core.Tests/Conformance/Issue119UpNullGfxObjDumpTests.cs +++ b/tests/AcDream.Core.Tests/Conformance/Issue119UpNullGfxObjDumpTests.cs @@ -23,6 +23,7 @@ namespace AcDream.Core.Tests.Conformance; /// ObjectMeshManager in MP1a) /// so the zeroing gate reads directly off the output. /// +[Trait("Lane", "InstalledDat")] public sealed class Issue119UpNullGfxObjDumpTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Conformance/StipplingSurfaceEquivalenceTests.cs b/tests/AcDream.Core.Tests/Conformance/StipplingSurfaceEquivalenceTests.cs index db553c80..ccb5362a 100644 --- a/tests/AcDream.Core.Tests/Conformance/StipplingSurfaceEquivalenceTests.cs +++ b/tests/AcDream.Core.Tests/Conformance/StipplingSurfaceEquivalenceTests.cs @@ -30,6 +30,7 @@ namespace AcDream.Core.Tests.Conformance; /// Violations of (b) on PLAIN OBJECT GfxObjs are allowed — retail's bypass /// draws solid batches for non-building/non-cell meshes, and so do we. /// +[Trait("Lane", "InstalledDat")] public sealed class StipplingSurfaceEquivalenceTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Conformance/ThresholdDivergenceDiagnosticTests.cs b/tests/AcDream.Core.Tests/Conformance/ThresholdDivergenceDiagnosticTests.cs index 860b9946..3b415fd4 100644 --- a/tests/AcDream.Core.Tests/Conformance/ThresholdDivergenceDiagnosticTests.cs +++ b/tests/AcDream.Core.Tests/Conformance/ThresholdDivergenceDiagnosticTests.cs @@ -14,6 +14,7 @@ namespace AcDream.Core.Tests.Conformance; /// (real pick-criterion divergence vs a test/sphere artifact). /// [Trait("Purpose", "Diagnostic")] +[Trait("Lane", "InstalledDat")] public class ThresholdDivergenceDiagnosticTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Conformance/ThresholdPortalCrossingReplayTests.cs b/tests/AcDream.Core.Tests/Conformance/ThresholdPortalCrossingReplayTests.cs index 356f4396..6bca27a4 100644 --- a/tests/AcDream.Core.Tests/Conformance/ThresholdPortalCrossingReplayTests.cs +++ b/tests/AcDream.Core.Tests/Conformance/ThresholdPortalCrossingReplayTests.cs @@ -27,6 +27,7 @@ namespace AcDream.Core.Tests.Conformance; /// building-cell cache. The outdoor-involving segments (0031↔0170) need the landcell + /// building portal and are a follow-up. /// +[Trait("Lane", "InstalledDat")] public class ThresholdPortalCrossingReplayTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Input/RetailActionIdentityRoundTripTests.cs b/tests/AcDream.Core.Tests/Input/RetailActionIdentityRoundTripTests.cs index 480c6e15..0d01a329 100644 --- a/tests/AcDream.Core.Tests/Input/RetailActionIdentityRoundTripTests.cs +++ b/tests/AcDream.Core.Tests/Input/RetailActionIdentityRoundTripTests.cs @@ -54,6 +54,7 @@ namespace AcDream.Core.Tests.Input; /// here. Reported, not silently resolved either way. /// /// +[Trait("Lane", "InstalledDat")] public sealed class RetailActionIdentityRoundTripTests { /// Actions with a citation-backed, pre-existing reason their DAT-union diff --git a/tests/AcDream.Core.Tests/Input/RetailActionMapReaderTests.cs b/tests/AcDream.Core.Tests/Input/RetailActionMapReaderTests.cs index 211993ec..7bb93d7f 100644 --- a/tests/AcDream.Core.Tests/Input/RetailActionMapReaderTests.cs +++ b/tests/AcDream.Core.Tests/Input/RetailActionMapReaderTests.cs @@ -204,6 +204,7 @@ public sealed class RetailActionMapReaderTests /// Live-DAT conformance: pins the exact shape of the installed /// client_portal.dat/client_local_English.dat ActionMap + /// MasterInputMap objects. Skips cleanly when the dats are unavailable. +[Trait("Lane", "InstalledDat")] public sealed class RetailActionMapReader_LiveDatTests { [Fact] diff --git a/tests/AcDream.Core.Tests/Physics/Ap157SortingSphereFloodMeasurementTests.cs b/tests/AcDream.Core.Tests/Physics/Ap157SortingSphereFloodMeasurementTests.cs index 347b9e0f..6cbc4d09 100644 --- a/tests/AcDream.Core.Tests/Physics/Ap157SortingSphereFloodMeasurementTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Ap157SortingSphereFloodMeasurementTests.cs @@ -59,6 +59,7 @@ namespace AcDream.Core.Tests.Physics; /// the flood-sphere list, not a subset or approximation of it. /// /// +[Trait("Lane", "InstalledDat")] public sealed class Ap157SortingSphereFloodMeasurementTests { /// Arbitrary non-zero landblock id — only its prefix matters for diff --git a/tests/AcDream.Core.Tests/Physics/BoxIntersectsCellBspDifferentialTests.cs b/tests/AcDream.Core.Tests/Physics/BoxIntersectsCellBspDifferentialTests.cs index 1a8625e2..7666abfd 100644 --- a/tests/AcDream.Core.Tests/Physics/BoxIntersectsCellBspDifferentialTests.cs +++ b/tests/AcDream.Core.Tests/Physics/BoxIntersectsCellBspDifferentialTests.cs @@ -189,6 +189,7 @@ public sealed class BoxIntersectsCellBspDifferentialTests } [Fact] + [Trait("Lane", "InstalledDat")] public void InstalledDat_RandomizedBoxSweepOverEnvCellContainmentBsps_HasZeroMismatch() { string? datDirectory = ConformanceDats.ResolveDatDir(); diff --git a/tests/AcDream.Core.Tests/Physics/CameraCornerSealReplayTests.cs b/tests/AcDream.Core.Tests/Physics/CameraCornerSealReplayTests.cs index ff5cf518..4676ac78 100644 --- a/tests/AcDream.Core.Tests/Physics/CameraCornerSealReplayTests.cs +++ b/tests/AcDream.Core.Tests/Physics/CameraCornerSealReplayTests.cs @@ -38,6 +38,7 @@ namespace AcDream.Core.Tests.Physics; /// L20104 / L20224 / L20386 (door-exit) + L23035 / L81340 / L87958 (corner press); /// pivot = player + (0,0,1.5) per RetailChaseCamera.PivotHeight. /// +[Trait("Lane", "InstalledDat")] public class CameraCornerSealReplayTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Physics/CellTransitFindTransitCellsBoxTests.cs b/tests/AcDream.Core.Tests/Physics/CellTransitFindTransitCellsBoxTests.cs index 29ddbce0..ad7e0671 100644 --- a/tests/AcDream.Core.Tests/Physics/CellTransitFindTransitCellsBoxTests.cs +++ b/tests/AcDream.Core.Tests/Physics/CellTransitFindTransitCellsBoxTests.cs @@ -263,6 +263,7 @@ public sealed class CellTransitFindTransitCellsBoxTests /// for the exact counts from this run. /// [Fact] + [Trait("Lane", "InstalledDat")] public void InstalledDat_RandomizedPartSweepNearRealPortals_PostFixMembershipIsSubsetOfPreFix() { string? datDirectory = ConformanceDats.ResolveDatDir(); diff --git a/tests/AcDream.Core.Tests/Physics/CellTransitTests.cs b/tests/AcDream.Core.Tests/Physics/CellTransitTests.cs index 92d2ca31..ce198da1 100644 --- a/tests/AcDream.Core.Tests/Physics/CellTransitTests.cs +++ b/tests/AcDream.Core.Tests/Physics/CellTransitTests.cs @@ -28,6 +28,7 @@ namespace AcDream.Core.Tests.Physics; /// semantics on real Holtburg dat geometry. /// /// +[Trait("Lane", "InstalledDat")] public class CellTransitTests { [Fact] diff --git a/tests/AcDream.Core.Tests/Physics/DoorBugTrajectoryReplayTests.cs b/tests/AcDream.Core.Tests/Physics/DoorBugTrajectoryReplayTests.cs index 875afd23..208324fe 100644 --- a/tests/AcDream.Core.Tests/Physics/DoorBugTrajectoryReplayTests.cs +++ b/tests/AcDream.Core.Tests/Physics/DoorBugTrajectoryReplayTests.cs @@ -82,6 +82,7 @@ public class DoorBugTrajectoryReplayTests /// door's outdoor cell when production's doesn't. /// [Fact] + [Trait("Lane", "InstalledDat")] public void LiveCompare_DoorOffCenterWalkthrough_Tick13558() { var datDir = ResolveDatDir(); @@ -117,6 +118,7 @@ public class DoorBugTrajectoryReplayTests /// registration itself is wrong. /// [Fact] + [Trait("Lane", "InstalledDat")] public void LiveCompare_DoorBlocksFromOutside_Tick22760() { var datDir = ResolveDatDir(); @@ -159,6 +161,7 @@ public class DoorBugTrajectoryReplayTests /// hard-stopped with cn=(0,0,1). Always passes; read the console dump. /// [Fact] + [Trait("Lane", "InstalledDat")] public void Diagnostic_Tick22760_DumpEngineInternals() { var datDir = ResolveDatDir(); @@ -211,6 +214,7 @@ public class DoorBugTrajectoryReplayTests } [Fact] + [Trait("Lane", "InstalledDat")] public void Diagnostic_Tick13558_DumpEngineInternals() { var datDir = ResolveDatDir(); @@ -272,6 +276,7 @@ public class DoorBugTrajectoryReplayTests /// portal traversal IS the bug. /// [Fact] + [Trait("Lane", "InstalledDat")] public void FindTransitCellsSphere_IndoorExitPortal_AddsOutsideForCapturedSpherePos() { var datDir = ResolveDatDir(); @@ -472,6 +477,7 @@ public class DoorBugTrajectoryReplayTests /// /// [Fact] + [Trait("Lane", "InstalledDat")] public void InsideOut_Tick3254_WithCottageWalls_ShouldBlock() { var datDir = ResolveDatDir(); @@ -543,6 +549,7 @@ public class DoorBugTrajectoryReplayTests /// (133.5, 17.10) to end up at X > 133.5 Y > 17.10, bug reproduced. /// [Fact] + [Trait("Lane", "InstalledDat")] public void CornerSlide_AlcoveEastToCottageNorth_ShouldBlock() { var datDir = ResolveDatDir(); @@ -770,6 +777,7 @@ public class DoorBugTrajectoryReplayTests } [Fact] + [Trait("Lane", "InstalledDat")] public void Geometric_DoorSlabAtSphereHeight_OverlapsInZ() { var datDir = ResolveDatDir(); @@ -821,6 +829,7 @@ public class DoorBugTrajectoryReplayTests } [Fact] + [Trait("Lane", "InstalledDat")] public void Directional_OutsideIn_SouthApproach_BlocksAtSlabSouthFace() { var datDir = ResolveDatDir(); @@ -848,6 +857,7 @@ public class DoorBugTrajectoryReplayTests } [Fact] + [Trait("Lane", "InstalledDat")] public void Directional_InsideOut_NorthApproach_BlocksAtSlabNorthFace() { var datDir = ResolveDatDir(); diff --git a/tests/AcDream.Core.Tests/Physics/DoorCollisionApparatusTests.cs b/tests/AcDream.Core.Tests/Physics/DoorCollisionApparatusTests.cs index 396e1c0f..95561d0c 100644 --- a/tests/AcDream.Core.Tests/Physics/DoorCollisionApparatusTests.cs +++ b/tests/AcDream.Core.Tests/Physics/DoorCollisionApparatusTests.cs @@ -40,6 +40,7 @@ namespace AcDream.Core.Tests.Physics; /// CI stays green. Local developer machines always have it. /// /// +[Trait("Lane", "InstalledDat")] public class DoorCollisionApparatusTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Physics/DoorSetupGfxObjInspectionTests.cs b/tests/AcDream.Core.Tests/Physics/DoorSetupGfxObjInspectionTests.cs index f3e72b9a..b59e20d9 100644 --- a/tests/AcDream.Core.Tests/Physics/DoorSetupGfxObjInspectionTests.cs +++ b/tests/AcDream.Core.Tests/Physics/DoorSetupGfxObjInspectionTests.cs @@ -26,6 +26,7 @@ namespace AcDream.Core.Tests.Physics; /// keeps CI green. Local developer runs always have it. /// /// +[Trait("Lane", "InstalledDat")] public class DoorSetupGfxObjInspectionTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Physics/FlatBspQueryDifferentialTests.cs b/tests/AcDream.Core.Tests/Physics/FlatBspQueryDifferentialTests.cs index 99a9eee1..26a9d2f6 100644 --- a/tests/AcDream.Core.Tests/Physics/FlatBspQueryDifferentialTests.cs +++ b/tests/AcDream.Core.Tests/Physics/FlatBspQueryDifferentialTests.cs @@ -412,6 +412,7 @@ public sealed class FlatBspQueryDifferentialTests } [Fact] + [Trait("Lane", "InstalledDat")] public void InstalledDat_LargeRandomizedSweep_HasZeroBitMismatch() { string? datDirectory = ConformanceDats.ResolveDatDir(); diff --git a/tests/AcDream.Core.Tests/Physics/FlatCollisionInstalledDatTests.cs b/tests/AcDream.Core.Tests/Physics/FlatCollisionInstalledDatTests.cs index 43ed3820..9265d142 100644 --- a/tests/AcDream.Core.Tests/Physics/FlatCollisionInstalledDatTests.cs +++ b/tests/AcDream.Core.Tests/Physics/FlatCollisionInstalledDatTests.cs @@ -9,6 +9,7 @@ using Xunit.Abstractions; namespace AcDream.Core.Tests.Physics; +[Trait("Lane", "InstalledDat")] public sealed class FlatCollisionInstalledDatTests { private readonly ITestOutputHelper _output; diff --git a/tests/AcDream.Core.Tests/Physics/HumanoidMotionTableRootMotionTests.cs b/tests/AcDream.Core.Tests/Physics/HumanoidMotionTableRootMotionTests.cs index 4f47eee9..256aee0d 100644 --- a/tests/AcDream.Core.Tests/Physics/HumanoidMotionTableRootMotionTests.cs +++ b/tests/AcDream.Core.Tests/Physics/HumanoidMotionTableRootMotionTests.cs @@ -15,6 +15,7 @@ namespace AcDream.Core.Tests.Physics; /// The packet-driven remote mover must use these values, not a velocity guessed /// from the interpreted command. /// +[Trait("Lane", "InstalledDat")] public sealed class HumanoidMotionTableRootMotionTests { private const uint HumanoidMotionTable = 0x09000001u; diff --git a/tests/AcDream.Core.Tests/Physics/Issue108CellarAscentViewerReplayTests.cs b/tests/AcDream.Core.Tests/Physics/Issue108CellarAscentViewerReplayTests.cs index abd691a8..8bdf42ad 100644 --- a/tests/AcDream.Core.Tests/Physics/Issue108CellarAscentViewerReplayTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Issue108CellarAscentViewerReplayTests.cs @@ -66,6 +66,7 @@ namespace AcDream.Core.Tests.Physics; /// eye projects into the aperture band at y 9.8–17) paints the doorway. /// These tests stay as the characterization pin for the healthy layer. /// +[Trait("Lane", "InstalledDat")] public class Issue108CellarAscentViewerReplayTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Physics/Issue137CorridorSeamInspectionTests.cs b/tests/AcDream.Core.Tests/Physics/Issue137CorridorSeamInspectionTests.cs index 6a63d73c..1fb4d502 100644 --- a/tests/AcDream.Core.Tests/Physics/Issue137CorridorSeamInspectionTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Issue137CorridorSeamInspectionTests.cs @@ -20,6 +20,7 @@ namespace AcDream.Core.Tests.Physics; /// (normal ≈ ±X at the portal's local X) — i.e., are portal-sealing polys in /// our collision set where retail filters them? /// +[Trait("Lane", "InstalledDat")] public class Issue137CorridorSeamInspectionTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Physics/Issue137CorridorSeamReplayTests.cs b/tests/AcDream.Core.Tests/Physics/Issue137CorridorSeamReplayTests.cs index 3724db77..8c91fda5 100644 --- a/tests/AcDream.Core.Tests/Physics/Issue137CorridorSeamReplayTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Issue137CorridorSeamReplayTests.cs @@ -38,6 +38,7 @@ namespace AcDream.Core.Tests.Physics; /// running must keep advancing (no absorbing wedge). /// /// +[Trait("Lane", "InstalledDat")] public class Issue137CorridorSeamReplayTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Physics/Issue147ArwicBuildingsDumpTests.cs b/tests/AcDream.Core.Tests/Physics/Issue147ArwicBuildingsDumpTests.cs index 610b87d2..793bb47e 100644 --- a/tests/AcDream.Core.Tests/Physics/Issue147ArwicBuildingsDumpTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Issue147ArwicBuildingsDumpTests.cs @@ -17,6 +17,7 @@ namespace AcDream.Core.Tests.Physics; /// (a separate shadow-object collision path). Dat-data-dependent; SKIPs cleanly /// without ACDREAM_DAT_DIR / the real dats. /// +[Trait("Lane", "InstalledDat")] public sealed class Issue147ArwicBuildingsDumpTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Physics/Issue175HubDoorPoseInspectionTests.cs b/tests/AcDream.Core.Tests/Physics/Issue175HubDoorPoseInspectionTests.cs index 6cd9bf4f..7d772ebe 100644 --- a/tests/AcDream.Core.Tests/Physics/Issue175HubDoorPoseInspectionTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Issue175HubDoorPoseInspectionTests.cs @@ -39,6 +39,7 @@ public class Issue175HubDoorPoseInspectionTests private const uint HubDoorSetupId = 0x02000C9Du; [Fact] + [Trait("Lane", "InstalledDat")] public void HubDoorSetup_PlacementVsMotionPose_DatInspection() { var datDir = Env.GetEnvironmentVariable("ACDREAM_DAT_DIR") @@ -161,6 +162,7 @@ public class Issue175HubDoorPoseInspectionTests /// NonCombat/Ready) and asserts the derivation actually resolves a pose. /// [Fact] + [Trait("Lane", "InstalledDat")] public void MotionTablePose_DefaultState_ResolvesOnRealTable() { var datDir = Env.GetEnvironmentVariable("ACDREAM_DAT_DIR") diff --git a/tests/AcDream.Core.Tests/Physics/Issue176177SeamTransitLagTests.cs b/tests/AcDream.Core.Tests/Physics/Issue176177SeamTransitLagTests.cs index 33bf9952..61e1daad 100644 --- a/tests/AcDream.Core.Tests/Physics/Issue176177SeamTransitLagTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Issue176177SeamTransitLagTests.cs @@ -24,6 +24,7 @@ namespace AcDream.Core.Tests.Physics; /// stair pop). This replay measures OUR resolver's flip point across the /// x=85 seam in a controlled run. /// +[Trait("Lane", "InstalledDat")] public class Issue176177SeamTransitLagTests { private const uint SeamCellWest = 0x8A02016Eu; // x 75..85 diff --git a/tests/AcDream.Core.Tests/Physics/Issue180CorridorSweepHysteresisReplayTests.cs b/tests/AcDream.Core.Tests/Physics/Issue180CorridorSweepHysteresisReplayTests.cs index 8a8ddb46..12423967 100644 --- a/tests/AcDream.Core.Tests/Physics/Issue180CorridorSweepHysteresisReplayTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Issue180CorridorSweepHysteresisReplayTests.cs @@ -35,6 +35,7 @@ namespace AcDream.Core.Tests.Physics; /// 3. the clipped eye is the CONSTANT surface-contact point (pre-fix it /// tracked the target one step back: eyeBack = s − ~0.27). /// +[Trait("Lane", "InstalledDat")] public class Issue180CorridorSweepHysteresisReplayTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Physics/Issue186ConnectorCellGeometryInspectionTests.cs b/tests/AcDream.Core.Tests/Physics/Issue186ConnectorCellGeometryInspectionTests.cs index dcf8d68f..66f12691 100644 --- a/tests/AcDream.Core.Tests/Physics/Issue186ConnectorCellGeometryInspectionTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Issue186ConnectorCellGeometryInspectionTests.cs @@ -20,6 +20,7 @@ namespace AcDream.Core.Tests.Physics; /// bare connector? And does it carry collision geometry (so the camera sweep would /// hard-stop) or none (so the boom coasts to a degenerate spot)? Skips without the dat. /// +[Trait("Lane", "InstalledDat")] public class Issue186ConnectorCellGeometryInspectionTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Physics/Issue188FadingDoorMotionTableInspectionTests.cs b/tests/AcDream.Core.Tests/Physics/Issue188FadingDoorMotionTableInspectionTests.cs index a78498d1..e3c0d176 100644 --- a/tests/AcDream.Core.Tests/Physics/Issue188FadingDoorMotionTableInspectionTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Issue188FadingDoorMotionTableInspectionTests.cs @@ -74,6 +74,7 @@ public class Issue188FadingDoorMotionTableInspectionTests } [Fact] + [Trait("Lane", "InstalledDat")] public void Dump_PedestalWeakSpot_MotionTable_HookContents() { var datDir = DatDir(); diff --git a/tests/AcDream.Core.Tests/Physics/Issue337NeftetRockGeometryInspectionTests.cs b/tests/AcDream.Core.Tests/Physics/Issue337NeftetRockGeometryInspectionTests.cs index b8e9daf9..f19c168c 100644 --- a/tests/AcDream.Core.Tests/Physics/Issue337NeftetRockGeometryInspectionTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Issue337NeftetRockGeometryInspectionTests.cs @@ -38,6 +38,7 @@ namespace AcDream.Core.Tests.Physics; /// /// Dat-data dependent; SKIPs cleanly without ACDREAM_DAT_DIR. /// +[Trait("Lane", "InstalledDat")] public sealed class Issue337NeftetRockGeometryInspectionTests { private const uint Landblock = 0x8766_0000u; diff --git a/tests/AcDream.Core.Tests/Physics/MotionCommandCatalogDatTests.cs b/tests/AcDream.Core.Tests/Physics/MotionCommandCatalogDatTests.cs index da169456..80e7d728 100644 --- a/tests/AcDream.Core.Tests/Physics/MotionCommandCatalogDatTests.cs +++ b/tests/AcDream.Core.Tests/Physics/MotionCommandCatalogDatTests.cs @@ -40,6 +40,7 @@ namespace AcDream.Core.Tests.Physics; /// present (CI has no local AC install). /// /// +[Trait("Lane", "InstalledDat")] public class MotionCommandCatalogDatTests { /// diff --git a/tests/AcDream.Core.Tests/Physics/RestrictionObjPrevalenceInspectionTests.cs b/tests/AcDream.Core.Tests/Physics/RestrictionObjPrevalenceInspectionTests.cs index dbd8b71d..0198c18b 100644 --- a/tests/AcDream.Core.Tests/Physics/RestrictionObjPrevalenceInspectionTests.cs +++ b/tests/AcDream.Core.Tests/Physics/RestrictionObjPrevalenceInspectionTests.cs @@ -18,6 +18,7 @@ namespace AcDream.Core.Tests.Physics; /// when the installed DATs are absent (CI), following the /// DoorSetupGfxObjInspectionTests pattern. /// +[Trait("Lane", "InstalledDat")] public sealed class RestrictionObjPrevalenceInspectionTests { private readonly ITestOutputHelper _output; diff --git a/tests/AcDream.Core.Tests/Rendering/Issue176177DungeonSeamInspectionTests.cs b/tests/AcDream.Core.Tests/Rendering/Issue176177DungeonSeamInspectionTests.cs index 54064199..7c109789 100644 --- a/tests/AcDream.Core.Tests/Rendering/Issue176177DungeonSeamInspectionTests.cs +++ b/tests/AcDream.Core.Tests/Rendering/Issue176177DungeonSeamInspectionTests.cs @@ -31,6 +31,7 @@ namespace AcDream.Core.Tests.Rendering; /// CellPortal.PolygonId indexes CellStruct.Polygons (VISUAL), never /// PhysicsPolygons — same ids in both tables are unrelated polygons. /// +[Trait("Lane", "InstalledDat")] public class Issue176177DungeonSeamInspectionTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Rendering/Issue93TownNetworkFountainRoomLightInspectionTests.cs b/tests/AcDream.Core.Tests/Rendering/Issue93TownNetworkFountainRoomLightInspectionTests.cs index cc820caf..784efdf8 100644 --- a/tests/AcDream.Core.Tests/Rendering/Issue93TownNetworkFountainRoomLightInspectionTests.cs +++ b/tests/AcDream.Core.Tests/Rendering/Issue93TownNetworkFountainRoomLightInspectionTests.cs @@ -26,6 +26,7 @@ namespace AcDream.Core.Tests.Rendering; /// fountain room and its immediate neighbors observed this session, so the answer /// is read from the dat directly instead of inferred from aggregate counts. /// +[Trait("Lane", "InstalledDat")] public class Issue93TownNetworkFountainRoomLightInspectionTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Core.Tests/Terrain/TerrainModernConformanceTests.cs b/tests/AcDream.Core.Tests/Terrain/TerrainModernConformanceTests.cs index c02f7cc2..c4deed3d 100644 --- a/tests/AcDream.Core.Tests/Terrain/TerrainModernConformanceTests.cs +++ b/tests/AcDream.Core.Tests/Terrain/TerrainModernConformanceTests.cs @@ -24,6 +24,7 @@ namespace AcDream.Core.Tests.Terrain; /// the directory doesn't exist, the test logs a SKIP and passes — keeps CI /// (no dat data) green while still firing locally on every developer run. /// +[Trait("Lane", "InstalledDat")] public class TerrainModernConformanceTests { private readonly ITestOutputHelper _out; diff --git a/tests/AcDream.Headless.Tests/HeadlessCredentialResolverTests.cs b/tests/AcDream.Headless.Tests/HeadlessCredentialResolverTests.cs index f21a79fb..97258dd0 100644 --- a/tests/AcDream.Headless.Tests/HeadlessCredentialResolverTests.cs +++ b/tests/AcDream.Headless.Tests/HeadlessCredentialResolverTests.cs @@ -122,6 +122,7 @@ public sealed class HeadlessCredentialResolverTests } [Fact] + [Trait("Lane", "Linux")] public void LinuxRejectsGroupOrOtherCredentialPermissions() { if (!OperatingSystem.IsLinux()) diff --git a/tests/AcDream.Launcher.Core.Tests/Launching/LauncherProcessSupervisorTests.cs b/tests/AcDream.Launcher.Core.Tests/Launching/LauncherProcessSupervisorTests.cs index ae66fb73..f4409444 100644 --- a/tests/AcDream.Launcher.Core.Tests/Launching/LauncherProcessSupervisorTests.cs +++ b/tests/AcDream.Launcher.Core.Tests/Launching/LauncherProcessSupervisorTests.cs @@ -9,6 +9,7 @@ namespace AcDream.Launcher.Core.Tests.Launching; public sealed class LauncherProcessSupervisorTests { [Fact] + [Trait("Lane", "Windows")] public void WindowsFactoryUsesNativeProcessGroupsOnlyForConsoleChildren() { if (!OperatingSystem.IsWindows()) @@ -148,6 +149,7 @@ public sealed class LauncherProcessSupervisorTests } [Fact] + [Trait("Lane", "Linux")] public void GracefulStopSignalSendsSigintToARealChildOnLinux() { // Review finding F3, proven end to end against the real @@ -221,6 +223,7 @@ public sealed class LauncherProcessSupervisorTests } [Fact] + [Trait("Lane", "Windows")] public async Task WindowsCtrlBreakStopsOnlyTheTargetProcessGroupWithoutKill() { if (!OperatingSystem.IsWindows()) @@ -316,6 +319,7 @@ public sealed class LauncherProcessSupervisorTests } [Fact] + [Trait("Lane", "Windows")] public async Task WindowsConsolelessParentStillTargetsDistinctChildProcessGroups() { if (!OperatingSystem.IsWindows()) @@ -655,6 +659,7 @@ public sealed class LauncherProcessSupervisorTests } [Fact] + [Trait("Lane", "Windows")] public async Task RealChildStderrIsCapturedForTheWindowsNativeConsolePath() { // Fix #406 sibling gap: on Windows, console-capable children diff --git a/tests/AcDream.Launcher.Core.Tests/Orchestration/LauncherExecutableSetTests.cs b/tests/AcDream.Launcher.Core.Tests/Orchestration/LauncherExecutableSetTests.cs index a8442f65..03e5adc6 100644 --- a/tests/AcDream.Launcher.Core.Tests/Orchestration/LauncherExecutableSetTests.cs +++ b/tests/AcDream.Launcher.Core.Tests/Orchestration/LauncherExecutableSetTests.cs @@ -78,6 +78,7 @@ public sealed class LauncherExecutableSetTests : IDisposable } [Fact] + [Trait("Lane", "Linux")] public void LinuxRequiresExecutePermissionForBothCoDeployedHosts() { if (!OperatingSystem.IsLinux()) @@ -118,6 +119,7 @@ public sealed class LauncherExecutableSetTests : IDisposable } [Fact] + [Trait("Lane", "Windows")] public void WindowsPreservesExistenceOnlyAvailability() { if (!OperatingSystem.IsWindows()) diff --git a/tests/AcDream.Launcher.Core.Tests/Profiles/LauncherProfileHardeningTests.cs b/tests/AcDream.Launcher.Core.Tests/Profiles/LauncherProfileHardeningTests.cs index 2da292a4..7994bdeb 100644 --- a/tests/AcDream.Launcher.Core.Tests/Profiles/LauncherProfileHardeningTests.cs +++ b/tests/AcDream.Launcher.Core.Tests/Profiles/LauncherProfileHardeningTests.cs @@ -128,6 +128,7 @@ public sealed class LauncherProfileHardeningTests : IDisposable } [Fact] + [Trait("Lane", "Linux")] public void LinuxLoadNormalizesAnExistingCredentialFileTo0600BeforeReading() { if (!OperatingSystem.IsLinux()) diff --git a/tests/AcDream.Launcher.Core.Tests/Profiles/LauncherProfileStoreTests.cs b/tests/AcDream.Launcher.Core.Tests/Profiles/LauncherProfileStoreTests.cs index e02072ad..72eab62c 100644 --- a/tests/AcDream.Launcher.Core.Tests/Profiles/LauncherProfileStoreTests.cs +++ b/tests/AcDream.Launcher.Core.Tests/Profiles/LauncherProfileStoreTests.cs @@ -317,6 +317,7 @@ public sealed class LauncherProfileStoreTests : IDisposable } [Fact] + [Trait("Lane", "Linux")] public void SaveSetsOwnerOnlyPermissionsOnLinux() { // Linux-conditional: 0600 is a Linux-only hygiene step (spec §5, @@ -361,6 +362,7 @@ public sealed class LauncherProfileStoreTests : IDisposable } [Fact] + [Trait("Lane", "Linux")] public void TempCredentialFileIsOwnerOnlyFromItsFirstObservableLinuxState() { // Deterministic proof of the exact production create path: inspect diff --git a/tests/AcDream.Launcher.Core.Tests/Status/StatusFileTailerTests.cs b/tests/AcDream.Launcher.Core.Tests/Status/StatusFileTailerTests.cs index 4f9314aa..5e3b31bd 100644 --- a/tests/AcDream.Launcher.Core.Tests/Status/StatusFileTailerTests.cs +++ b/tests/AcDream.Launcher.Core.Tests/Status/StatusFileTailerTests.cs @@ -157,6 +157,7 @@ public sealed class StatusFileTailerTests : IDisposable } [Fact] + [Trait("Lane", "Windows")] public void ReadNewEventsReturnsEmptyRatherThanThrowingOnASharingViolation() { // A deterministic proxy for the File.Exists -> new FileStream diff --git a/tests/AcDream.Launcher.Core.Tests/Updates/ClientVersionStoreTests.cs b/tests/AcDream.Launcher.Core.Tests/Updates/ClientVersionStoreTests.cs index ede382c9..9b9322c1 100644 --- a/tests/AcDream.Launcher.Core.Tests/Updates/ClientVersionStoreTests.cs +++ b/tests/AcDream.Launcher.Core.Tests/Updates/ClientVersionStoreTests.cs @@ -178,6 +178,7 @@ public sealed class ClientVersionStoreTests : IDisposable } [Fact] + [Trait("Lane", "Linux")] public async Task LinuxTreatsNonCanonicalInstallJsonCasingAsUnrecordedContent() { if (!OperatingSystem.IsLinux()) diff --git a/tests/AcDream.Launcher.Tests/MainWindowViewTests.cs b/tests/AcDream.Launcher.Tests/MainWindowViewTests.cs index 0fd62668..e01a0dce 100644 --- a/tests/AcDream.Launcher.Tests/MainWindowViewTests.cs +++ b/tests/AcDream.Launcher.Tests/MainWindowViewTests.cs @@ -19,8 +19,8 @@ namespace AcDream.Launcher.Tests; /// generated InitializeComponent()) reached the user gate through /// 14,012 green tests that were all ViewModel-only. /// -/// Every test here constructs a real against the -/// real compiled XAML and drives it exactly the way App.axaml.cs +/// The Avalonia test constructs real instances against +/// the compiled XAML and drives them exactly the way App.axaml.cs /// does: assign a live as /// DataContext, then exercise the modal open/close paths that /// dereference the named controls (the bug class lives in @@ -28,7 +28,7 @@ namespace AcDream.Launcher.Tests; /// FocusActiveModal). That focus work is queued via /// Dispatcher.UIThread.Post, so every test pumps the headless /// dispatcher with before asserting — a -/// test that only sets a property and asserts would pass vacuously +/// phase that only sets a property and asserts would pass vacuously /// without ever running FocusActiveModal. /// public sealed class MainWindowViewTests @@ -49,7 +49,22 @@ public sealed class MainWindowViewTests ]; [AvaloniaFact] - public void EveryExplicitlyNamedControlIsAssignedAfterConstruction() + public async Task CompiledMarkupAndEveryModalFocusPathRunInOneOwnedAvaloniaSession() + { + // Avalonia's headless compositor is thread-affine. Keep the complete + // MainWindow matrix inside one runner-owned application session so + // xUnit cannot tear one compositor down on a different worker while + // starting the next scenario. Each named method remains a separate + // assertion phase for readable failure stacks. + EveryExplicitlyNamedControlIsAssignedAfterConstruction(); + ReflectionSweepOfEveryXNameInMarkupFindsANonNullBackingField(); + OpeningEveryEditorKindFocusesItsPrimaryFieldAndClosingRunsTheFallbackWithoutThrowing(); + OpeningAndClosingTheFirstRunWizardFocusesAndRunsTheCloseFallbackWithoutThrowing(); + await OpeningAndClosingTheUpdatePromptFocusesAndRunsTheCloseFallbackWithoutThrowing(); + ClosingAModalRestoresThePreviouslyFocusedControlWithoutThrowing(); + } + + private static void EveryExplicitlyNamedControlIsAssignedAfterConstruction() { var window = new MainWindow(); @@ -66,8 +81,7 @@ public sealed class MainWindowViewTests } } - [AvaloniaFact] - public void ReflectionSweepOfEveryXNameInMarkupFindsANonNullBackingField() + private static void ReflectionSweepOfEveryXNameInMarkupFindsANonNullBackingField() { string markupPath = Path.Combine( FindRepositoryRoot(), @@ -114,8 +128,7 @@ public sealed class MainWindowViewTests } } - [AvaloniaFact] - public void OpeningEveryEditorKindFocusesItsPrimaryFieldAndClosingRunsTheFallbackWithoutThrowing() + private static void OpeningEveryEditorKindFocusesItsPrimaryFieldAndClosingRunsTheFallbackWithoutThrowing() { (ProfileEditorKind Kind, string FocusFieldName)[] cases = [ @@ -168,8 +181,7 @@ public sealed class MainWindowViewTests } } - [AvaloniaFact] - public void OpeningAndClosingTheFirstRunWizardFocusesAndRunsTheCloseFallbackWithoutThrowing() + private static void OpeningAndClosingTheFirstRunWizardFocusesAndRunsTheCloseFallbackWithoutThrowing() { using LauncherWindowViewModel viewModel = CreateViewModel(); var window = new MainWindow { DataContext = viewModel }; @@ -198,8 +210,7 @@ public sealed class MainWindowViewTests } } - [AvaloniaFact] - public async Task OpeningAndClosingTheUpdatePromptFocusesAndRunsTheCloseFallbackWithoutThrowing() + private static async Task OpeningAndClosingTheUpdatePromptFocusesAndRunsTheCloseFallbackWithoutThrowing() { using LauncherWindowViewModel viewModel = CreateViewModel(); var window = new MainWindow { DataContext = viewModel }; @@ -228,8 +239,7 @@ public sealed class MainWindowViewTests } } - [AvaloniaFact] - public void ClosingAModalRestoresThePreviouslyFocusedControlWithoutThrowing() + private static void ClosingAModalRestoresThePreviouslyFocusedControlWithoutThrowing() { using LauncherWindowViewModel viewModel = CreateViewModel(); var window = new MainWindow { DataContext = viewModel }; diff --git a/tools/audit-test-inventory.ps1 b/tools/audit-test-inventory.ps1 index 5eb93737..a0ef134a 100644 --- a/tools/audit-test-inventory.ps1 +++ b/tools/audit-test-inventory.ps1 @@ -354,6 +354,29 @@ $summary = [ordered]@{ KnownFailureMethods = @($orderedRecords | Where-Object { $_.Traits -contains 'Status, KnownFailure' }).Count + LaneMethods = [ordered]@{ + InstalledDat = @($orderedRecords | Where-Object { + $_.Traits -contains 'Lane, InstalledDat' + }).Count + PreparedPackage = @($orderedRecords | Where-Object { + $_.Traits -contains 'Lane, PreparedPackage' + }).Count + Live = @($orderedRecords | Where-Object { + $_.Traits -contains 'Lane, Live' + }).Count + Manual = @($orderedRecords | Where-Object { + $_.Traits -contains 'Lane, Manual' + }).Count + Windows = @($orderedRecords | Where-Object { + $_.Traits -contains 'Lane, Windows' + }).Count + Linux = @($orderedRecords | Where-Object { + $_.Traits -contains 'Lane, Linux' + }).Count + SystemFont = @($orderedRecords | Where-Object { + $_.Traits -contains 'Lane, SystemFont' + }).Count + } ThreadSleepMethods = @($orderedRecords | Where-Object { $_.HasThreadSleep }).Count TaskDelayMethods = @($orderedRecords | Where-Object { $_.HasTaskDelay }).Count DirectEnvironmentVariableMethods = @($orderedRecords | Where-Object { diff --git a/tools/run-release-gate.ps1 b/tools/run-release-gate.ps1 index d434c13b..6665a7d9 100644 --- a/tools/run-release-gate.ps1 +++ b/tools/run-release-gate.ps1 @@ -23,7 +23,7 @@ param( [int]$BuildTimeoutSeconds = 900, [int]$TestTimeoutSeconds = 600, [int]$HangTimeoutSeconds = 180, - [string]$TestFilter = 'Lane!=InstalledDat&Lane!=PreparedPackage&Lane!=Live&Lane!=Manual&Purpose!=Diagnostic&Status!=KnownFailure', + [string]$TestFilter = 'Lane!=InstalledDat&Lane!=PreparedPackage&Lane!=Live&Lane!=Manual&Lane!=Windows&Lane!=Linux&Lane!=SystemFont&Purpose!=Diagnostic&Status!=KnownFailure', [switch]$SkipRestore, [switch]$SkipBuild )