test(streaming): expose world reveal lifecycle

This commit is contained in:
Erik 2026-07-20 22:32:23 +02:00
parent b60cb67009
commit db45b81f75
6 changed files with 532 additions and 11 deletions

View file

@ -0,0 +1,105 @@
using AcDream.App.Streaming;
namespace AcDream.App.Tests.Streaming;
public sealed class WorldRevealLifecycleTelemetryTests
{
private static WorldRevealReadinessSnapshot Ready(uint cell = 0x11340021u) => new(
cell,
IsIndoor: false,
IsUnhydratable: false,
RequiredRenderRadius: 1,
IsRenderNeighborhoodReady: true,
AreCompositeTexturesReady: true,
IsCollisionReady: true);
[Fact]
public void Login_RecordsReadyThenFirstVisibleFrameExactlyOnce()
{
var logs = new List<string>();
var telemetry = new WorldRevealLifecycleTelemetry(logs.Add);
long generation = telemetry.Begin(WorldRevealKind.Login);
telemetry.ObserveReadiness(Ready());
telemetry.ObserveWorldViewportVisible();
telemetry.ObserveWorldViewportVisible();
telemetry.Complete();
Assert.Equal(generation, telemetry.Snapshot.Generation);
Assert.True(telemetry.Snapshot.IsReady);
Assert.True(telemetry.Snapshot.WorldViewportObserved);
Assert.True(telemetry.Snapshot.Completed);
Assert.Equal(0, telemetry.Snapshot.InvariantFailureCount);
Assert.Single(logs, line => line.Contains("event=world-visible", StringComparison.Ordinal));
}
[Fact]
public void EarlyWorldViewport_IsARecordedHardInvariantFailure()
{
var logs = new List<string>();
var telemetry = new WorldRevealLifecycleTelemetry(logs.Add);
telemetry.Begin(WorldRevealKind.Login);
telemetry.ObserveReadiness(Ready() with { AreCompositeTexturesReady = false });
telemetry.ObserveWorldViewportVisible();
Assert.Equal(1, telemetry.Snapshot.InvariantFailureCount);
Assert.Contains(logs, line => line.Contains("reason=viewport-before-ready", StringComparison.Ordinal));
}
[Fact]
public void NewGeneration_SupersedesOldStateAndRejectsDestinationMutation()
{
var logs = new List<string>();
var telemetry = new WorldRevealLifecycleTelemetry(logs.Add);
long first = telemetry.Begin(WorldRevealKind.Login);
telemetry.ObserveReadiness(Ready(0x11340021u));
long second = telemetry.Begin(WorldRevealKind.Portal);
telemetry.ObserveReadiness(Ready(0x3032001Cu));
telemetry.ObserveReadiness(Ready(0xC95B0001u));
Assert.True(second > first);
Assert.Equal(WorldRevealKind.Portal, telemetry.Snapshot.Kind);
Assert.Equal(0xC95B0001u, telemetry.Snapshot.Readiness.DestinationCell);
Assert.Equal(1, telemetry.Snapshot.InvariantFailureCount);
Assert.Contains(logs, line => line.Contains("event=superseded", StringComparison.Ordinal));
Assert.Contains(logs, line => line.Contains("reason=destination-changed", StringComparison.Ordinal));
}
[Fact]
public void PortalMaterialization_IsCountedOncePerGeneration()
{
var telemetry = new WorldRevealLifecycleTelemetry();
telemetry.Begin(WorldRevealKind.Portal);
telemetry.ObserveReadiness(Ready());
telemetry.ObserveMaterialized();
telemetry.ObserveMaterialized();
telemetry.Begin(WorldRevealKind.Portal);
telemetry.ObserveReadiness(Ready(0x3032001Cu));
telemetry.ObserveMaterialized();
Assert.Equal(2, telemetry.PortalMaterializationCount);
}
[Fact]
public void CancelledGeneration_IgnoresLateAsyncObservations()
{
var telemetry = new WorldRevealLifecycleTelemetry();
telemetry.Begin(WorldRevealKind.Portal);
telemetry.Cancel();
telemetry.ObserveReadiness(Ready());
telemetry.ObserveMaterialized();
telemetry.ObserveWorldViewportVisible();
telemetry.Complete();
Assert.True(telemetry.Snapshot.Cancelled);
Assert.False(telemetry.Snapshot.IsReady);
Assert.False(telemetry.Snapshot.Materialized);
Assert.False(telemetry.Snapshot.WorldViewportObserved);
Assert.False(telemetry.Snapshot.Completed);
Assert.Equal(0, telemetry.PortalMaterializationCount);
}
}

View file

@ -121,4 +121,46 @@ public sealed class WorldRevealReadinessBarrierTests
Assert.Equal(0, state.Preparations);
Assert.Equal(-1, state.RenderRadius);
}
[Fact]
public void Evaluate_ExposesTheCanonicalOutdoorDecisionWithoutRepeatingDomains()
{
const uint outdoorCell = 0x11340021u;
var state = new State
{
RenderReady = true,
CompositeReady = true,
TerrainReady = true,
};
WorldRevealReadinessSnapshot snapshot = state.Build().Evaluate(outdoorCell);
Assert.Equal(outdoorCell, snapshot.DestinationCell);
Assert.False(snapshot.IsIndoor);
Assert.Equal(WorldRevealReadinessBarrier.OutdoorNeighborhoodRadius, snapshot.RequiredRenderRadius);
Assert.True(snapshot.IsRenderNeighborhoodReady);
Assert.True(snapshot.AreCompositeTexturesReady);
Assert.True(snapshot.IsCollisionReady);
Assert.True(snapshot.IsReady);
Assert.Equal(-1, state.PreparedRadius);
}
[Fact]
public void Evaluate_ShortCircuitsDownstreamDomainsUntilRenderPublication()
{
var state = new State
{
CompositeReady = true,
TerrainReady = true,
SpawnCellReady = true,
};
WorldRevealReadinessSnapshot snapshot = state.Build().Evaluate(0x11340100u);
Assert.False(snapshot.IsRenderNeighborhoodReady);
Assert.False(snapshot.AreCompositeTexturesReady);
Assert.False(snapshot.IsCollisionReady);
Assert.False(snapshot.IsReady);
Assert.Equal(-1, state.TerrainRadius);
}
}