105 lines
4 KiB
C#
105 lines
4 KiB
C#
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);
|
|
}
|
|
}
|