acdream/tests/AcDream.App.Tests/Composition/FrameRootCompositionTests.cs
Erik bca4148739 test(app): add canonical connected soak snapshots
Make scripted lifecycle checkpoints acknowledged post-diagnostics render barriers, capture the exact frame outcome beside canonical resource ownership, and harden the nine-stop route with ordered same-location cache and lifetime gates without weakening process residency thresholds.

Co-authored-by: Codex <codex@openai.com>
2026-07-22 20:01:06 +02:00

134 lines
4.7 KiB
C#

using System.Reflection;
using AcDream.App.Composition;
using AcDream.App.Rendering;
namespace AcDream.App.Tests.Composition;
public sealed class FrameRootCompositionTests
{
[Fact]
public void RuntimeBindingsReleaseInReverseAndRetryOnlyFailedEdges()
{
var calls = new List<string>();
var bindings = new FrameRootRuntimeBindings();
bindings.Adopt("first", new RetryBinding("first", calls, 0));
bindings.Adopt("second", new RetryBinding("second", calls, 1));
Assert.Throws<AggregateException>(bindings.Dispose);
Assert.Equal(["second", "first"], calls);
bindings.Dispose();
bindings.Dispose();
Assert.Equal(["second", "first", "second"], calls);
Assert.Throws<ObjectDisposedException>(() =>
bindings.Adopt("late", new RetryBinding("late", calls, 0)));
}
[Fact]
public void ProductionPhasePublishesOnlyAfterBothRootsExist()
{
string source = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Composition",
"FrameRootComposition.cs"));
AssertAppearsInOrder(
source,
"new RenderFrameResourceController(",
"new WorldSceneRenderer(",
"new WorldLifecycleAutomationController(",
"\"world lifecycle automation owner\"",
"\"world lifecycle automation binding\"",
"new RenderFrameOrchestrator(",
"(IRenderFramePostDiagnosticsPhase?)lifecycleAutomation",
"new RetailLiveFrameCoordinator(",
"new UpdateFrameOrchestrator(",
"d.FrameGraphs.PublishOwned(",
"_publication.PublishFrameRoots(result);",
"graphLease.Transfer();",
"bindingsLease.Transfer();");
}
[Fact]
public void GameWindowRetainsOnlyThePhaseBoundaryAndFrameHandoffs()
{
string source = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Rendering",
"GameWindow.cs"));
Assert.Contains("new FrameRootCompositionPhase(", source);
Assert.DoesNotContain("new AcDream.App.Rendering.WorldSceneRenderer(", source);
Assert.DoesNotContain("new AcDream.App.Update.UpdateFrameOrchestrator(", source);
Assert.DoesNotContain("CaptureWorldLifecycleResourceSnapshot", source);
Assert.DoesNotContain("_worldLifecycleAutomation", source);
Assert.DoesNotContain("_frameGraphs.Publish(", source);
}
[Fact]
public void FramePhaseAndSnapshotSourceRetainNoWindowOwner()
{
Assert.DoesNotContain(
typeof(FrameRootCompositionPhase).GetFields(
BindingFlags.Instance | BindingFlags.NonPublic),
field => field.FieldType == typeof(GameWindow));
string snapshots = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Diagnostics",
"WorldLifecycleResourceSnapshotSource.cs"));
Assert.DoesNotContain("GameWindow", snapshots, StringComparison.Ordinal);
Assert.Contains("_liveEntities.PendingTeardownCount", snapshots);
Assert.Contains("GpuMemoryTracker.AllocatedBytes", snapshots);
Assert.Contains("_frameProfiler.LastReport", snapshots);
Assert.Contains("Capture(RenderFrameOutcome outcome)", snapshots);
Assert.Contains("outcome.World.VisibleLandblocks", snapshots);
Assert.Contains("outcome.World.TotalLandblocks", snapshots);
}
private sealed class RetryBinding(
string name,
List<string> calls,
int failures) : IDisposable
{
private int _failures = failures;
public void Dispose()
{
calls.Add(name);
if (_failures-- > 0)
throw new InvalidOperationException("retry");
}
}
private static void AssertAppearsInOrder(string source, params string[] values)
{
int cursor = 0;
foreach (string value in values)
{
int found = source.IndexOf(value, cursor, StringComparison.Ordinal);
Assert.True(found >= 0, $"Missing expected source fragment: {value}");
cursor = found + value.Length;
}
}
private static string FindRepoRoot()
{
DirectoryInfo? directory = new(AppContext.BaseDirectory);
while (directory is not null)
{
if (File.Exists(Path.Combine(directory.FullName, "AcDream.slnx")))
return directory.FullName;
directory = directory.Parent;
}
throw new DirectoryNotFoundException("Could not find AcDream.slnx.");
}
}