test: make prerequisite lanes fail honestly

This commit is contained in:
Erik 2026-08-18 12:09:41 +02:00
parent dfc841b779
commit 6faeb4a103
113 changed files with 424 additions and 336 deletions

View file

@ -135,7 +135,7 @@ public sealed class AppCredentialResolverTests
public void LinuxRejectsGroupOrOtherCredentialPermissions()
{
if (!OperatingSystem.IsLinux())
return;
throw new PlatformNotSupportedException("Lane=Linux requires a native Linux host.");
string path = Path.Combine(
Path.GetTempPath(),

View file

@ -49,7 +49,7 @@ public sealed class ChargenPreviewControllerTests
public void Rebuild_SameSelectionTwice_IsANoOpSecondTime()
{
if (!TryOpen(out DatCollection? dats, out DatCollectionAdapter? adapter))
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using (dats)
using (adapter)
{
@ -72,7 +72,7 @@ public sealed class ChargenPreviewControllerTests
public void Rebuild_HeritageChange_ResetsCameraToTheNewHeritagesDefaultEye()
{
if (!TryOpen(out DatCollection? dats, out DatCollectionAdapter? adapter))
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using (dats)
using (adapter)
{
@ -119,7 +119,7 @@ public sealed class ChargenPreviewControllerTests
public void Rebuild_AppearanceOnlyChange_LeavesTheCameraUntouched()
{
if (!TryOpen(out DatCollection? dats, out DatCollectionAdapter? adapter))
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using (dats)
using (adapter)
{
@ -147,7 +147,7 @@ public sealed class ChargenPreviewControllerTests
public void Rebuild_PreservesZoomState_AcrossAnAppearanceOnlyChange()
{
if (!TryOpen(out DatCollection? dats, out DatCollectionAdapter? adapter))
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using (dats)
using (adapter)
{
@ -178,7 +178,7 @@ public sealed class ChargenPreviewControllerTests
public void Rebuild_ThenRender_SeedsTheEntityHeadingToTheRetailDefault180Degrees()
{
if (!TryOpen(out DatCollection? dats, out DatCollectionAdapter? adapter))
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using (dats)
using (adapter)
{
@ -215,7 +215,7 @@ public sealed class ChargenPreviewControllerTests
public void Rebuild_HeritageWithEnvironmentSetupId_SetsANonNullBackdrop()
{
if (!TryOpen(out DatCollection? dats, out DatCollectionAdapter? adapter))
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using (dats)
using (adapter)
{
@ -250,7 +250,7 @@ public sealed class ChargenPreviewControllerTests
public void Rebuild_HeritageWithNoEnvironmentSetupId_LeavesTheBackdropAbsent()
{
if (!TryOpen(out DatCollection? dats, out DatCollectionAdapter? adapter))
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using (dats)
using (adapter)
{
@ -292,7 +292,7 @@ public sealed class ChargenPreviewControllerTests
public void Rebuild_HeritageChange_SwapsTheBackdropEntity()
{
if (!TryOpen(out DatCollection? dats, out DatCollectionAdapter? adapter))
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using (dats)
using (adapter)
{
@ -345,7 +345,7 @@ public sealed class ChargenPreviewControllerTests
public void Rebuild_AppearanceOnlyChange_DoesNotRebuildTheBackdrop()
{
if (!TryOpen(out DatCollection? dats, out DatCollectionAdapter? adapter))
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using (dats)
using (adapter)
{
@ -371,7 +371,7 @@ public sealed class ChargenPreviewControllerTests
public void Render_WhilePageInvisible_SkipsRenderAndTexturePublication()
{
if (!TryOpen(out DatCollection? dats, out DatCollectionAdapter? adapter))
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using (dats)
using (adapter)
{

View file

@ -30,7 +30,7 @@ public sealed class ChargenPreviewEntityBuilderTests
public void TryBuild_AluvianMaleDefaultSelection_ProducesANonEmptyStaticPoseEntity()
{
string? datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
using var adapter = new DatCollectionAdapter(dats);
@ -88,7 +88,7 @@ public sealed class ChargenPreviewEntityBuilderTests
ChargenPreviewEntityBuilder.SummaryPreviewBackdropRenderId);
string? datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
using var adapter = new DatCollectionAdapter(dats);
@ -122,7 +122,7 @@ public sealed class ChargenPreviewEntityBuilderTests
public void TryBuild_UnknownSetupId_ReturnsNull()
{
string? datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
using var adapter = new DatCollectionAdapter(dats);
@ -146,7 +146,7 @@ public sealed class ChargenPreviewEntityBuilderTests
public void TryBuild_OlthoiHeritage_ResolvesADifferentRestPoseDidThanStandardHeritages()
{
string? datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
using var adapter = new DatCollectionAdapter(dats);
@ -187,7 +187,7 @@ public sealed class ChargenPreviewEntityBuilderTests
public void TryBuildAnimated_AluvianMaleDefaultSelection_ResolvesARealIdleCycle()
{
string? datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
using var adapter = new DatCollectionAdapter(dats);
@ -233,7 +233,7 @@ public sealed class ChargenPreviewEntityBuilderTests
public void TryBuildAnimated_UnknownSetupId_ReturnsNull()
{
string? datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
using var adapter = new DatCollectionAdapter(dats);
@ -275,7 +275,7 @@ public sealed class ChargenPreviewEntityBuilderTests
public void OlthoiFamily_SharedIdleRestEnumKey_ResolvesToARealInstalledDid(uint sharedEnumKey)
{
string? datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
using var adapter = new DatCollectionAdapter(dats);
@ -298,7 +298,7 @@ public sealed class ChargenPreviewEntityBuilderTests
public void TryBuildAnimated_OlthoiHeritage_ResolvesARealIdleAnimationToo()
{
string? datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
using var adapter = new DatCollectionAdapter(dats);
@ -338,7 +338,7 @@ public sealed class ChargenPreviewEntityBuilderTests
public void TryBuildBackdrop_AluvianHeritage_ResolvesANonEmptyMesh()
{
string? datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
using var adapter = new DatCollectionAdapter(dats);
@ -377,7 +377,7 @@ public sealed class ChargenPreviewEntityBuilderTests
public void TryBuildBackdrop_ExplicitRenderId_StampsThatIdOnTheEntity()
{
string? datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
using var adapter = new DatCollectionAdapter(dats);
@ -406,7 +406,7 @@ public sealed class ChargenPreviewEntityBuilderTests
public void TryBuildBackdrop_UnsetEnvironmentSetupId_ReturnsNull()
{
string? datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
using var adapter = new DatCollectionAdapter(dats);
@ -420,7 +420,7 @@ public sealed class ChargenPreviewEntityBuilderTests
public void TryBuildBackdrop_UnknownSetupId_ReturnsNull()
{
string? datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
using var adapter = new DatCollectionAdapter(dats);
@ -441,7 +441,7 @@ public sealed class ChargenPreviewEntityBuilderTests
public void TryBuildBackdrop_AllThirteenHeritages_ResolveOrAreReportedByName()
{
string? datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
using var adapter = new DatCollectionAdapter(dats);

View file

@ -202,7 +202,7 @@ public class CornerFloodReplayTests
public void Diagnostic_TraceGoodVsGlitchStep()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = LoadBuilding(dats);
@ -271,7 +271,7 @@ public class CornerFloodReplayTests
public void CornerSweep_FloodIsCompleteAndMonotone()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = LoadBuilding(dats);
@ -369,7 +369,7 @@ public class CornerFloodReplayTests
public void PortalPlaneCrossings_InPlacePropagationConverges()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = LoadBuilding(dats);
@ -440,7 +440,7 @@ public class CornerFloodReplayTests
public void InCellDirectionSweep_InPlacePropagationConverges()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = LoadBuilding(dats);
@ -503,7 +503,7 @@ public class CornerFloodReplayTests
public void Diagnostic_Hop2Microscope()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = LoadBuilding(dats);
@ -634,7 +634,7 @@ public class CornerFloodReplayTests
public void Diagnostic_CornerPress_FloodAcrossDoorwayPlane()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = LoadBuilding(dats);

View file

@ -123,7 +123,7 @@ public sealed class FramePacingControllerTests
public void Windows_high_resolution_timer_arms_and_disposes_its_handle()
{
if (!OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134))
return;
throw new PlatformNotSupportedException("Lane=Windows requires a Windows host.");
using var timer = WindowsHighResolutionFramePacingWaiter.Create();
timer.Wait(1, System.Diagnostics.Stopwatch.Frequency);

View file

@ -372,7 +372,7 @@ public class HouseExitWalkReplayTests
public void ExitWalk_PlayerStaysConeVisible_EveryStep()
{
var steps = RunExitWalk();
if (steps is null) return;
if (steps is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
var failures = steps.FindAll(s => !s.ConeVisible);
if (failures.Count > 0)
@ -394,7 +394,7 @@ public class HouseExitWalkReplayTests
public void ExitWalk_PlayerSurvivesSealDepth_WhenConeVisible()
{
var steps = RunExitWalk();
if (steps is null) return;
if (steps is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
var applicable = steps.FindAll(s => s.DepthCheckApplies);
_out.WriteLine($"depth check applies on {applicable.Count}/{steps.Count} steps");
@ -420,7 +420,7 @@ public class HouseExitWalkReplayTests
public void ExitWalk_StraddlingPlayerDrawsInOutsideStage()
{
var steps = RunExitWalk();
if (steps is null) return;
if (steps is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
var straddling = steps.FindAll(s =>
s.RootCellId != 0u && MathF.Abs(s.CenterS) < PlayerSphereRadius);
@ -440,7 +440,7 @@ public class HouseExitWalkReplayTests
public void Diagnostic_ExitWalk_PerStepTable()
{
var steps = RunExitWalk();
if (steps is null) return;
if (steps is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
DumpSteps(steps);
// transition summary
int firstOutPlayer = steps.FindIndex(s => s.CenterS > 0f);
@ -460,7 +460,7 @@ public class HouseExitWalkReplayTests
public void Diagnostic_StaleRootWindow_EyeJustOutside()
{
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = CornerFloodReplayTests.LoadBuilding(dats);

View file

@ -40,7 +40,7 @@ public class Issue113DrawingBspFilterTests
public void MeetingHall_OrphanStairPolys_AreExcludedFromDrawSet()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var hall = dats.Get<DatReaderWriter.DBObjs.GfxObj>(0x010014C3u)!;
@ -60,7 +60,7 @@ public class Issue113DrawingBspFilterTests
public void HillCottage_OrphanPolys_AreExcludedFromDrawSet()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cottage = dats.Get<DatReaderWriter.DBObjs.GfxObj>(0x01000827u)!;

View file

@ -181,7 +181,7 @@ public class Issue113MeetingHallFloodTests
public void WestApproach_HallCellSlices_HaveUsableClip()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = LoadHall(dats);

View file

@ -79,7 +79,7 @@ public class Issue120ReciprocalPingPongTests
public void CapturedPingPongSites_Converge(uint landblock, uint lowA, uint lowB, float ex, float ey, float ez)
{
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = LoadAllInteriorCells(dats, landblock);
@ -136,7 +136,7 @@ public class Issue120ReciprocalPingPongTests
{
_ = ex; _ = ey; _ = ez; // geometric variant derives its own eyes
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = LoadAllInteriorCells(dats, landblock);

View file

@ -89,7 +89,7 @@ public class Issue124LookInSeedRegionTests
public void SeedRegion_ContainingAperture_Floods_DisjointRegion_DoesNot()
{
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var (cells, exitCell, exitIdx, centroid, outward) = LoadFixture(dats);
LoadedCell? Lookup(uint id) => cells.TryGetValue(id, out var c) ? c : null;
@ -138,7 +138,7 @@ public class Issue124LookInSeedRegionTests
// interior-root gather pass ALL nearby buildings including the
// viewer's own without special-casing.
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var (cells, exitCell, _, centroid, outward) = LoadFixture(dats);
LoadedCell? Lookup(uint id) => cells.TryGetValue(id, out var c) ? c : null;

View file

@ -60,7 +60,7 @@ public class Issue130DoorwayStripTests
public void Diagnostic_ExitDoorTopEdge_GateVsAperture()
{
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = CornerFloodReplayTests.LoadBuilding(dats);
@ -213,7 +213,7 @@ public class Issue130DoorwayStripTests
public void UnliftedGate_LeavesTheStripAtTheDrawnTopEdge()
{
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = CornerFloodReplayTests.LoadBuilding(dats);

View file

@ -30,7 +30,7 @@ public class Issue131SetupProbeTests
public void Diagnostic_LookInFlood_AdmitsHallPorchFromCottage()
{
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = Issue120ReciprocalPingPongTests.LoadAllInteriorCells(dats, 0xA9B40000u);
@ -68,7 +68,7 @@ public class Issue131SetupProbeTests
public void Diagnostic_DumpOutstageCandidateSetups()
{
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
uint[] candidates =

View file

@ -68,7 +68,7 @@ public class Issue176177FacilityHubFloodReplayTests
public void ScenarioA_StairApproach_AdmissionsFromCorridor()
{
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); return; }
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = Issue120ReciprocalPingPongTests.LoadAllInteriorCells(dats, FacilityHub);
Assert.True(cells.ContainsKey(FacilityHub | 0x0178u), "0x0178 not loaded");
@ -103,7 +103,7 @@ public class Issue176177FacilityHubFloodReplayTests
public void Diagnostic_ScenarioB_StairDescent_RampCellRetention()
{
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); return; }
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = Issue120ReciprocalPingPongTests.LoadAllInteriorCells(dats, FacilityHub);
@ -146,7 +146,7 @@ public class Issue176177FacilityHubFloodReplayTests
public void Diagnostic_ScenarioC_CorridorSeamGazeSweep_Bistability()
{
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); return; }
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = Issue120ReciprocalPingPongTests.LoadAllInteriorCells(dats, FacilityHub);
@ -222,7 +222,7 @@ public class Issue176177FacilityHubFloodReplayTests
uint rootLow, uint forwardLow, float planeX, float eyeZ)
{
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); return; }
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = Issue120ReciprocalPingPongTests.LoadAllInteriorCells(dats, FacilityHub);
@ -247,7 +247,7 @@ public class Issue176177FacilityHubFloodReplayTests
public void Diagnostic_ScenarioD_CorridorWalk_PerStepChurn()
{
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); return; }
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = Issue120ReciprocalPingPongTests.LoadAllInteriorCells(dats, FacilityHub);

View file

@ -110,7 +110,7 @@ public class Issue177StairDescentCameraFloodTests
public void Diagnostic_StairCellComposition_ShellVsStatics()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); return; }
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
foreach (uint low in new uint[] { 0x01C8, 0x01C4, 0x01C9, 0x0210, 0x020E, 0x01C1, 0x01C0 })
@ -172,7 +172,7 @@ public class Issue177StairDescentCameraFloodTests
public void Diagnostic_RealStaircase_FineYawZoomSweep_FindKnifeEdge()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); return; }
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var renderCells = Issue120ReciprocalPingPongTests.LoadAllInteriorCells(dats, FacilityHub);
var engine = BuildHubEngine(dats);
@ -235,7 +235,7 @@ public class Issue177StairDescentCameraFloodTests
public void Diagnostic_FloodDepthFrom015E_VsRetail26()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); return; }
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var renderCells = Issue120ReciprocalPingPongTests.LoadAllInteriorCells(dats, FacilityHub);
var engine = BuildHubEngine(dats);
@ -296,7 +296,7 @@ public class Issue177StairDescentCameraFloodTests
public void EdgeOnCeilingPortal_DropsUpperCell_OffPlaneReadmits()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); return; }
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = Issue120ReciprocalPingPongTests.LoadAllInteriorCells(dats, FacilityHub);
Func<uint, LoadedCell?> lookup = id => cells.TryGetValue(id, out var c) ? c : null;
@ -357,7 +357,7 @@ public class Issue177StairDescentCameraFloodTests
public void Diagnostic_StaircaseSweep_EyeClearanceFromCeilingPortal()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); return; }
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var renderCells = Issue120ReciprocalPingPongTests.LoadAllInteriorCells(dats, FacilityHub);
var engine = BuildHubEngine(dats);
@ -404,7 +404,7 @@ public class Issue177StairDescentCameraFloodTests
public void Diagnostic_ParkedYawZoomSweep_StairAdmission(float px, uint pcell, string label)
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); return; }
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var renderCells = Issue120ReciprocalPingPongTests.LoadAllInteriorCells(dats, FacilityHub);
var engine = BuildHubEngine(dats);
@ -461,7 +461,7 @@ public class Issue177StairDescentCameraFloodTests
public void Diagnostic_Descent_RealCameraSweep_StairCellRetention()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); return; }
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var renderCells = Issue120ReciprocalPingPongTests.LoadAllInteriorCells(dats, FacilityHub);

View file

@ -61,7 +61,7 @@ public class Issue181VisFlapReplayTests
public void Diagnostic_FlappingCellViewRegion_SliverOrLarge()
{
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); return; }
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = Issue120ReciprocalPingPongTests.LoadAllInteriorCells(dats, FacilityHub);
uint flapper = FacilityHub | 0x0181u;
@ -120,7 +120,7 @@ public class Issue181VisFlapReplayTests
public void Diagnostic_SubMillimeterEyePerturbation_MustNotChangeAdmission()
{
var datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); return; }
if (datDir is null) { _out.WriteLine("SKIP: no dat dir"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var cells = Issue120ReciprocalPingPongTests.LoadAllInteriorCells(dats, FacilityHub);
Assert.True(cells.ContainsKey(LiveRoot), "live root 0x0142 not loaded");

View file

@ -82,7 +82,7 @@ public class Issue181WallPressEquilibriumTests
public void Diagnostic_WallPressedCamera_EyeWanderAndViewerCellStability()
{
var datDir = ResolveDatDir();
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); return; }
if (datDir is null) { _out.WriteLine("SKIP: dats unavailable"); Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); }
using var dats = new DatCollection(datDir, DatAccessType.Read);
var (engine, _) = BuildCorridorEngine(dats);

View file

@ -52,7 +52,7 @@ public class Issue95DungeonFloodDiagnosticTests
_out.WriteLine("SKIP: dat dir did not resolve (ACDREAM_DAT_DIR unset and "
+ "%USERPROFILE%\\Documents\\Asheron's Call absent). No numbers measured.");
// Diagnostic test: do not hard-fail when dats are absent (matches sibling harnesses).
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
}
_out.WriteLine($"dat dir resolved: {datDir}");

View file

@ -52,7 +52,7 @@ public sealed class LinuxMonotonicFramePacingWaiterTests
public void LinuxWaitBlocksUntilRequestedMonotonicDeadline()
{
if (!OperatingSystem.IsLinux())
return;
throw new PlatformNotSupportedException("Lane=Linux requires a native Linux host.");
LinuxMonotonicFramePacingWaiter waiter =
LinuxMonotonicFramePacingWaiter.Create();
@ -75,7 +75,7 @@ public sealed class LinuxMonotonicFramePacingWaiterTests
public void LinuxWaiterRejectsUseAfterDisposal()
{
if (!OperatingSystem.IsLinux())
return;
throw new PlatformNotSupportedException("Lane=Linux requires a native Linux host.");
LinuxMonotonicFramePacingWaiter waiter =
LinuxMonotonicFramePacingWaiter.Create();

View file

@ -7,7 +7,6 @@ using DatReaderWriter;
using DatReaderWriter.DBObjs;
using DatReaderWriter.Enums;
using DatReaderWriter.Options;
using Xunit.Sdk;
namespace AcDream.App.Tests.Rendering;
@ -57,8 +56,8 @@ public sealed class PortalTunnelAssetTests
{
string? datDir = ResolveDatDir();
if (datDir is null)
throw SkipException.ForSkip(
"Installed client_portal.dat is required for the portal-space asset gate.");
throw new InvalidOperationException(
"Lane=InstalledDat requires client_portal.dat for the portal-space asset gate; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
uint setupDid = RetailDataIdResolver.Resolve(

View file

@ -8,7 +8,6 @@ using DatReaderWriter.DBObjs;
using DatReaderWriter.Enums;
using DatReaderWriter.Options;
using DatReaderWriter.Types;
using Xunit.Sdk;
namespace AcDream.App.Tests.Rendering;
@ -211,8 +210,8 @@ public sealed class RetailParticleGeometryClassifierTests
{
string? datDir = ResolveDatDir();
if (datDir is null)
throw SkipException.ForSkip(
"Installed client_portal.dat is required for the Armor Self asset-chain gate.");
throw new InvalidOperationException(
"Lane=InstalledDat requires client_portal.dat for the Armor Self asset-chain gate; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
var tableResolver = new PhysicsScriptTableResolver(
@ -270,7 +269,8 @@ public sealed class RetailParticleGeometryClassifierTests
{
string? datDir = ResolveDatDir();
if (datDir is null)
throw SkipException.ForSkip("Installed client_portal.dat is required.");
throw new InvalidOperationException(
"Lane=InstalledDat requires client_portal.dat; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
var resolver = new PhysicsScriptTableResolver(id => dats.Get<PhysicsScriptTable>(id));
@ -285,7 +285,8 @@ public sealed class RetailParticleGeometryClassifierTests
{
string? datDir = ResolveDatDir();
if (datDir is null)
throw SkipException.ForSkip("Installed client_portal.dat is required.");
throw new InvalidOperationException(
"Lane=InstalledDat requires client_portal.dat; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
var emitters = new EmitterDescRegistry(dats);

View file

@ -8,7 +8,6 @@ using AcDream.Core.Selection;
using DatReaderWriter;
using DatReaderWriter.DBObjs;
using DatReaderWriter.Options;
using Xunit.Sdk;
using SysEnv = System.Environment;
namespace AcDream.App.Tests.Rendering;
@ -116,6 +115,7 @@ public sealed class RetailSelectionAssetTests
if (File.Exists(Path.Combine(conventional, "client_portal.dat")))
return conventional;
throw SkipException.ForSkip("Installed client_portal.dat is required.");
throw new InvalidOperationException(
"Lane=InstalledDat requires client_portal.dat; see docs/release-gate.md.");
}
}

View file

@ -8,7 +8,6 @@ using AcDream.Core.World;
using DatReaderWriter;
using DatReaderWriter.DBObjs;
using DatReaderWriter.Types;
using Xunit.Sdk;
namespace AcDream.App.Tests.Streaming;
@ -348,7 +347,8 @@ public sealed class LandblockBuildFactoryTests
{
string? datDirectory = ResolveDatDirectory();
if (datDirectory is null)
throw SkipException.ForSkip("Installed retail DATs are required.");
throw new InvalidOperationException(
"Lane=PreparedPackage requires installed retail DATs; see docs/release-gate.md.");
using var dat = new BoundedTestDatCollection(datDirectory);
var bounded = (IDatReaderWriter)dat;
@ -358,7 +358,8 @@ public sealed class LandblockBuildFactoryTests
Assert.True(heights.Length >= 256);
string? pakPath = ResolvePreparedPackagePath(datDirectory);
if (pakPath is null)
throw SkipException.ForSkip("Installed acdream.pak is required.");
throw new InvalidOperationException(
"Lane=PreparedPackage requires a validated acdream.pak; see docs/release-gate.md.");
using var prepared = new PakPreparedAssetSource(pakPath, bounded);
var factory = new LandblockBuildFactory(
bounded,

View file

@ -80,7 +80,7 @@ public class IconComposerTests
{
var datDir = ResolveDatDir();
if (datDir is null)
return; // dats absent (CI) — skip cleanly
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); // dats absent (CI) — skip cleanly
using var dats = new DatCollection(datDir, DatAccessType.Read);
// TextureCache is not needed for the resolve path; pass a null-safe stub
@ -108,7 +108,7 @@ public class IconComposerTests
public void ResolveEffectDid_goldenValues_matchDat()
{
var datDir = ResolveDatDir();
if (datDir is null) return; // dats absent (CI) — skip cleanly
if (datDir is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); // dats absent (CI) — skip cleanly
using var dats = new DatCollection(datDir, DatAccessType.Read);
var composer = new IconComposer(dats, null!);
@ -134,7 +134,7 @@ public class IconComposerTests
public void TryGetEffectTile_noEffectBlack_magicalTextured()
{
var datDir = ResolveDatDir();
if (datDir is null) return; // dats absent (CI) — skip cleanly
if (datDir is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); // dats absent (CI) — skip cleanly
using var dats = new DatCollection(datDir, DatAccessType.Read);
var composer = new IconComposer(dats, null!);

View file

@ -28,7 +28,7 @@ public sealed class CharacterLayoutImportProbe
public void Selected_attribute_shows_raise_buttons_on_visible_footer_state()
{
var datDir = DatDir();
if (datDir is null) return;
if (datDir is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
var layout = LayoutImporter.Import(dats, CharacterLayout, _ => (1u, 30, 26), null);
@ -59,7 +59,7 @@ public sealed class CharacterLayoutImportProbe
public void Close_button_resolves_and_invokes_controller_close_callback()
{
var datDir = DatDir();
if (datDir is null) return;
if (datDir is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
var layout = LayoutImporter.Import(dats, CharacterLayout, _ => (1u, 30, 26), null);
@ -81,7 +81,7 @@ public sealed class CharacterLayoutImportProbe
public void Footer_title_exposes_retail_append_text_palette()
{
string? datDir = DatDir();
if (datDir is null) return;
if (datDir is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
ImportedLayout? layout = LayoutImporter.Import(

View file

@ -54,14 +54,15 @@ namespace AcDream.App.Tests.UI.Layout;
/// see its own class doc) are unaffected.
/// </para>
/// </summary>
[Trait("Lane", "InstalledDat")]
[Trait("Lane", "Manual")]
[Trait("ManualTask", "LiveMountProbe")]
public sealed class ChatIndicatorButtonLiveMountProbeTests
{
[Fact]
public void IndicatorButtons_ResolveNormalStateAtRest_ThroughTheLiveImportPath()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_LIVE_MOUNT") != "1")
return;
Assert.Fail("Lane=Manual live-mount probe requires ACDREAM_PROBE_LIVE_MOUNT=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(

View file

@ -1,7 +1,6 @@
using AcDream.App.UI.Layout;
using DatReaderWriter;
using DatReaderWriter.Options;
using Xunit.Sdk;
using SysEnv = System.Environment;
namespace AcDream.App.Tests.UI.Layout;
@ -53,6 +52,7 @@ public sealed class ChatOptionsDatDefaultsTests
if (File.Exists(Path.Combine(conventional, "client_portal.dat")))
return conventional;
throw SkipException.ForSkip("Installed client_portal.dat is required.");
throw new InvalidOperationException(
"Lane=InstalledDat requires client_portal.dat; see docs/release-gate.md.");
}
}

View file

@ -15,14 +15,15 @@ namespace AcDream.App.Tests.UI.Layout;
/// and 0x10000263 (swear-allegiance button). Env-gated like the other probes.
/// </summary>
[Trait("Purpose", "Diagnostic")]
[Trait("Lane", "InstalledDat")]
[Trait("Lane", "Manual")]
[Trait("ManualTask", "LiveMountProbe")]
public sealed class FaPanelSlotProbeTests
{
[Fact]
public void ProbePanelSlotTable()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_LIVE_MOUNT") != "1")
return;
Assert.Fail("Lane=Manual live-mount probe requires ACDREAM_PROBE_LIVE_MOUNT=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(

View file

@ -41,7 +41,7 @@ public class InventoryFrameImportProbe
public void Paperdoll_equip_slots_resolve_to_item_lists()
{
var datDir = DatDir();
if (datDir is null) return; // CI: no live dat — skip
if (datDir is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); // CI: no live dat — skip
using var dats = new DatCollection(datDir, DatAccessType.Read);
var layout = LayoutImporter.Import(dats, Frame, _ => (0u, 0, 0), null);
@ -61,7 +61,7 @@ public class InventoryFrameImportProbe
public void Mounted_panels_sit_in_front_of_the_backdrop()
{
var datDir = DatDir();
if (datDir is null) return; // CI: no live dat — skip (this is a smoke test)
if (datDir is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); // CI: no live dat — skip (this is a smoke test)
using var dats = new DatCollection(datDir, DatAccessType.Read);
var layout = LayoutImporter.Import(dats, Frame, _ => (0u, 0, 0), null);
@ -93,7 +93,7 @@ public class InventoryFrameImportProbe
public void Close_button_resolves_and_invokes_controller_close_callback()
{
var datDir = DatDir();
if (datDir is null) return; // CI: no live dat - skip
if (datDir is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); // CI: no live dat - skip
using var dats = new DatCollection(datDir, DatAccessType.Read);
var layout = LayoutImporter.Import(dats, Frame, _ => (0u, 0, 0), null);

View file

@ -754,7 +754,7 @@ public sealed class ItemAppraisalTextFormatterTests
{
string? datDirectory = ResolveDatDirectory();
if (datDirectory is null)
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using var dats =
new AcDream.App.Tests.BoundedTestDatCollection(datDirectory);

View file

@ -39,7 +39,7 @@ public class ItemListCellTemplateTests
public void Inventory_lists_resolve_a_real_nongeneric_empty_sprite()
{
var datDir = DatDir();
if (datDir is null) return; // CI: no live dat — skip (smoke test)
if (datDir is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); // CI: no live dat — skip (smoke test)
using var dats = new DatCollection(datDir, DatAccessType.Read);
@ -62,7 +62,7 @@ public class ItemListCellTemplateTests
public void Inventory_lists_resolve_the_pinned_retail_sprites()
{
var datDir = DatDir();
if (datDir is null) return; // CI: no live dat — skip
if (datDir is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); // CI: no live dat — skip
using var dats = new DatCollection(datDir, DatAccessType.Read);
// Pinned from the live dat + the 2026-06-22 visual gate. Contents = the 32x32 prototype's
@ -78,7 +78,7 @@ public class ItemListCellTemplateTests
public void Spell_favorite_list_resolves_its_cross_layout_pinned_empty_sprite()
{
var datDir = DatDir();
if (datDir is null) return; // CI: no live dat — skip
if (datDir is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md."); // CI: no live dat — skip
using var dats = new DatCollection(datDir, DatAccessType.Read);
ElementInfo infos = Assert.IsType<ElementInfo>(
@ -98,7 +98,7 @@ public class ItemListCellTemplateTests
public void Shared_UIItem_resolves_all_ten_cooldown_overlays()
{
var datDir = DatDir();
if (datDir is null) return;
if (datDir is null) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
ItemCooldownAssets? assets = ItemCooldownAssets.TryLoad(dats);

View file

@ -16,14 +16,15 @@ 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.
/// </summary>
[Trait("Lane", "InstalledDat")]
[Trait("Lane", "Manual")]
[Trait("ManualTask", "LiveMountProbe")]
public sealed class KeyboardConfigLiveMountProbeTests
{
[Fact]
public void ProbeKeyboardLiveMount()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_LIVE_MOUNT") != "1")
return;
Assert.Fail("Lane=Manual live-mount probe requires ACDREAM_PROBE_LIVE_MOUNT=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(
@ -159,7 +160,7 @@ public sealed class KeyboardConfigLiveMountProbeTests
public void ProbeKeyboardFontsAndKeyNameStrings()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_LIVE_MOUNT") != "1")
return;
Assert.Fail("Lane=Manual live-mount probe requires ACDREAM_PROBE_LIVE_MOUNT=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(

View file

@ -26,7 +26,8 @@ namespace AcDream.App.Tests.UI.Layout;
/// </para>
/// </summary>
[Trait("Purpose", "Diagnostic")]
[Trait("Lane", "InstalledDat")]
[Trait("Lane", "Manual")]
[Trait("ManualTask", "LiveMountProbe")]
public sealed class MapHousePanelSlotProbeTests
{
private const uint HostLayoutId = 0x2100006Eu;
@ -48,7 +49,7 @@ public sealed class MapHousePanelSlotProbeTests
public void ProbeMapHousePanelSlot()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_LIVE_MOUNT") != "1")
return;
Assert.Fail("Lane=Manual live-mount probe requires ACDREAM_PROBE_LIVE_MOUNT=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(

View file

@ -16,7 +16,8 @@ namespace AcDream.App.Tests.UI.Layout;
/// page controller actually resolves. Env-gated like the fixture
/// generator so CI/dat-less runs skip it.
/// </summary>
[Trait("Lane", "InstalledDat")]
[Trait("Lane", "Manual")]
[Trait("ManualTask", "LiveMountProbe")]
public sealed class OptionsPanelLiveMountProbeTests
{
[Fact]
@ -24,7 +25,7 @@ public sealed class OptionsPanelLiveMountProbeTests
public void ProbeLiveMountShapes()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_LIVE_MOUNT") != "1")
return;
Assert.Fail("Lane=Manual live-mount probe requires ACDREAM_PROBE_LIVE_MOUNT=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(
@ -99,7 +100,7 @@ public sealed class OptionsPanelLiveMountProbeTests
public void ProbeConfigMenuChrome()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_LIVE_MOUNT") != "1")
return;
Assert.Fail("Lane=Manual live-mount probe requires ACDREAM_PROBE_LIVE_MOUNT=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(
@ -176,7 +177,7 @@ public sealed class OptionsPanelLiveMountProbeTests
public void ProbeConfigMenuPopupChrome()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_LIVE_MOUNT") != "1")
return;
Assert.Fail("Lane=Manual live-mount probe requires ACDREAM_PROBE_LIVE_MOUNT=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(
@ -320,7 +321,7 @@ public sealed class OptionsPanelLiveMountProbeTests
public void ProbeMenuPopupSizingAndTextStyle()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_LIVE_MOUNT") != "1")
return;
Assert.Fail("Lane=Manual live-mount probe requires ACDREAM_PROBE_LIVE_MOUNT=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(
@ -452,7 +453,7 @@ public sealed class OptionsPanelLiveMountProbeTests
public void ProbeChatOpacityCaptions()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_LIVE_MOUNT") != "1")
return;
Assert.Fail("Lane=Manual live-mount probe requires ACDREAM_PROBE_LIVE_MOUNT=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(
@ -486,7 +487,7 @@ public sealed class OptionsPanelLiveMountProbeTests
public void ProbeFilterLabelHome()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_LIVE_MOUNT") != "1")
return;
Assert.Fail("Lane=Manual live-mount probe requires ACDREAM_PROBE_LIVE_MOUNT=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(

View file

@ -53,7 +53,7 @@ public sealed class PaperdollClickMapTests
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
"Documents",
"Asheron's Call");
if (!Directory.Exists(datDir)) return;
if (!Directory.Exists(datDir)) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
PaperdollClickMap map = Assert.IsType<PaperdollClickMap>(PaperdollClickMap.Load(dats));

View file

@ -53,7 +53,7 @@ public class PaperdollSlotBackgroundTests
string datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
"Documents", "Asheron's Call");
if (!Directory.Exists(datDir)) return;
if (!Directory.Exists(datDir)) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
IReadOnlyDictionary<uint, uint> actual = PaperdollSlotBackgrounds.ResolveEmptySprites(dats);

View file

@ -15,7 +15,8 @@ namespace AcDream.App.Tests.UI.Layout;
/// INSTALLED DAT, so the "Height"/"Power"/"Accuracy" fix binds exactly what
/// retail authors instead of guessing.
/// </summary>
[Trait("Lane", "InstalledDat")]
[Trait("Lane", "Manual")]
[Trait("ManualTask", "PowerbarProbe")]
public sealed class PowerbarLayoutProbeTests
{
[Fact]
@ -23,7 +24,7 @@ public sealed class PowerbarLayoutProbeTests
public void ProbePowerbarAuthoredStrings()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_POWERBAR") != "1")
return;
Assert.Fail("Lane=Manual powerbar probe requires ACDREAM_PROBE_POWERBAR=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(
@ -44,7 +45,7 @@ public sealed class PowerbarLayoutProbeTests
public void ProbeFriendsRowTemplate()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_POWERBAR") != "1")
return;
Assert.Fail("Lane=Manual powerbar probe requires ACDREAM_PROBE_POWERBAR=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(
@ -81,7 +82,7 @@ public sealed class PowerbarLayoutProbeTests
public void ProbeSecureTradeLayout()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_POWERBAR") != "1")
return;
Assert.Fail("Lane=Manual powerbar probe requires ACDREAM_PROBE_POWERBAR=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(
@ -114,7 +115,7 @@ public sealed class PowerbarLayoutProbeTests
public void ProbeTotalItemsTemplate()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_POWERBAR") != "1")
return;
Assert.Fail("Lane=Manual powerbar probe requires ACDREAM_PROBE_POWERBAR=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(
@ -153,7 +154,7 @@ public sealed class PowerbarLayoutProbeTests
public void ProbeUiItemCatalog()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_POWERBAR") != "1")
return;
Assert.Fail("Lane=Manual powerbar probe requires ACDREAM_PROBE_POWERBAR=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(
@ -176,7 +177,7 @@ public sealed class PowerbarLayoutProbeTests
public void ProbeCharacterSelectRowTemplate()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_POWERBAR") != "1")
return;
Assert.Fail("Lane=Manual powerbar probe requires ACDREAM_PROBE_POWERBAR=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(

View file

@ -13,6 +13,7 @@ namespace AcDream.App.Tests.UI.Layout;
/// normal test runs deterministic and dat-independent.
/// </summary>
[Trait("Lane", "Manual")]
[Trait("ManualTask", "FixtureGeneration")]
public sealed class RetailLayoutFixtureGenerator
{
private static readonly (uint Id, string FileName)[] Layouts =

View file

@ -18,14 +18,15 @@ 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.
/// </summary>
[Trait("Lane", "InstalledDat")]
[Trait("Lane", "Manual")]
[Trait("ManualTask", "LiveMountProbe")]
public sealed class SocialPanelLiveMountProbeTests
{
[Fact]
public void ProbeLiveMountShapes()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_LIVE_MOUNT") != "1")
return;
Assert.Fail("Lane=Manual live-mount probe requires ACDREAM_PROBE_LIVE_MOUNT=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(
@ -488,7 +489,7 @@ public sealed class SocialPanelLiveMountProbeTests
public void ProbeSocialClickRouting()
{
if (Environment.GetEnvironmentVariable("ACDREAM_PROBE_LIVE_MOUNT") != "1")
return;
Assert.Fail("Lane=Manual live-mount probe requires ACDREAM_PROBE_LIVE_MOUNT=1.");
var datDir = Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(

View file

@ -13,7 +13,7 @@ public sealed class SpellbookRowStyleTests
string datDir = System.Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile),
"Documents", "Asheron's Call");
if (!Directory.Exists(datDir)) return;
if (!Directory.Exists(datDir)) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
SpellbookRowStyle style = Assert.IsType<SpellbookRowStyle>(
@ -37,7 +37,7 @@ public sealed class SpellbookRowStyleTests
string datDir = System.Environment.GetEnvironmentVariable("ACDREAM_DAT_DIR")
?? Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile),
"Documents", "Asheron's Call");
if (!Directory.Exists(datDir)) return;
if (!Directory.Exists(datDir)) Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
ElementInfo root = Assert.IsType<ElementInfo>(LayoutImporter.ImportInfos(

View file

@ -29,7 +29,7 @@ public sealed class RetailCursorCatalogTests
{
string? datDir = ResolveDatDir();
if (datDir is null)
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
CursorFeedbackKind[] kinds =
@ -88,7 +88,7 @@ public sealed class RetailCursorCatalogTests
{
string? datDir = ResolveDatDir();
if (datDir is null)
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
var resolver = new RetailCursorResolver(dats, new object());

View file

@ -106,7 +106,7 @@ public sealed class SpewBoxLayoutDumpDiagnostic
if (datDir is null)
{
_out.WriteLine("SKIP: installed retail DAT directory is unavailable.");
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
}
using var dats = new DatCollection(datDir, DatAccessType.Read);

View file

@ -40,7 +40,7 @@ public sealed class UiDatFontBorderPixelTests
{
string? datDir = ResolveDatDir();
if (datDir is null)
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
Assert.True(dats.TryGet<Font>(fontId, out Font? font), $"Font 0x{fontId:X8} not found");
@ -60,7 +60,7 @@ public sealed class UiDatFontBorderPixelTests
// correlation. Sweep the documented populated range (0x40000000-0x40000032).
string? datDir = ResolveDatDir();
if (datDir is null)
return;
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
int checkedCount = 0;

View file

@ -5,7 +5,6 @@ using AcDream.App.Rendering.Gpu;
using AcDream.App.Tests.Rendering.Gpu;
using AcDream.App.UI;
using DatReaderWriter.Types;
using Xunit.Sdk;
namespace AcDream.App.Tests.UI;
@ -96,7 +95,8 @@ public sealed class UiRenderContextAlphaTests
{
byte[]? ttf = BitmapFont.TryLoadSystemMonospaceFont();
if (ttf is null)
throw SkipException.ForSkip("No system TTF font found for BitmapFont construction.");
throw new InvalidOperationException(
"Lane=SystemFont requires a host system TTF font; see docs/release-gate.md.");
return new BitmapFont(device, ttf, pixelHeight: 16f);
}

View file

@ -10,7 +10,6 @@ using AcDream.Runtime.Entities;
using DatReaderWriter;
using DatReaderWriter.DBObjs;
using DatReaderWriter.Options;
using Xunit.Sdk;
namespace AcDream.App.Tests.World;
@ -155,7 +154,8 @@ public sealed class LiveEntityPresentationControllerTests
const uint magicPortal = 0x40000038u;
string datDir = @"C:\Turbine\Asheron's Call";
if (!File.Exists(Path.Combine(datDir, "client_portal.dat")))
throw SkipException.ForSkip("Installed retail DATs are required.");
throw new InvalidOperationException(
"Lane=InstalledDat requires installed retail DATs; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
Setup setup = Assert.IsType<Setup>(dats.Get<Setup>(humanSetup));

View file

@ -12,7 +12,6 @@ using DatReaderWriter;
using DatReaderWriter.DBObjs;
using DatReaderWriter.Options;
using DatReaderWriter.Types;
using Xunit.Sdk;
namespace AcDream.App.Tests.World;
@ -190,7 +189,8 @@ public sealed class RecallTeleportAnimationTests
{
string datDir = @"C:\Turbine\Asheron's Call";
if (!File.Exists(Path.Combine(datDir, "client_portal.dat")))
throw SkipException.ForSkip("Installed retail DATs are required.");
throw new InvalidOperationException(
"Lane=InstalledDat requires installed retail DATs; see docs/release-gate.md.");
using var dats = new DatCollection(datDir, DatAccessType.Read);
Setup setup = Assert.IsType<Setup>(dats.Get<Setup>(HumanSetup));