refactor(app): compose atomic frame roots
Move the complete update/render construction graph into a typed Phase-8 owner, explicitly carry the content dependencies it consumes, and publish both roots through one exact lease. Extract lifecycle resource sampling and frame-owned late bindings so partial startup and shutdown withdraw the same generation without window callbacks. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
826f9ea9b5
commit
3628aeb520
21 changed files with 1052 additions and 374 deletions
126
tests/AcDream.App.Tests/Composition/FrameRootCompositionTests.cs
Normal file
126
tests/AcDream.App.Tests/Composition/FrameRootCompositionTests.cs
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
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 RenderFrameOrchestrator(",
|
||||
"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("_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);
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ public sealed class GameWindowCompositionPipelineTests
|
|||
IInteractionUiCompositionPhase<Token, Token, Token, Token, Token>,
|
||||
ILivePresentationCompositionPhase<Token, Token, Token, Token, Token>,
|
||||
ISessionPlayerCompositionPhase<Token, Token, Token, Token, Token, Token>,
|
||||
IFrameRootCompositionPhase<Token, Token, Token, Token, Token, Token, Token>,
|
||||
IFrameRootCompositionPhase<Token, Token, Token, Token, Token, Token, Token, Token>,
|
||||
ISessionStartCompositionPhase<Token>
|
||||
{
|
||||
public Token Platform { get; } = new(0);
|
||||
|
|
@ -155,8 +155,9 @@ public sealed class GameWindowCompositionPipelineTests
|
|||
return _session;
|
||||
}
|
||||
|
||||
Token IFrameRootCompositionPhase<Token, Token, Token, Token, Token, Token, Token>.Compose(
|
||||
Token IFrameRootCompositionPhase<Token, Token, Token, Token, Token, Token, Token, Token>.Compose(
|
||||
Token host,
|
||||
Token content,
|
||||
Token settings,
|
||||
Token world,
|
||||
Token interaction,
|
||||
|
|
@ -164,6 +165,7 @@ public sealed class GameWindowCompositionPipelineTests
|
|||
Token session)
|
||||
{
|
||||
Assert.Same(_host, host);
|
||||
Assert.Same(_content, content);
|
||||
Assert.Same(_settings, settings);
|
||||
Assert.Same(_world, world);
|
||||
Assert.Same(_interaction, interaction);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ public sealed class GameWindowRenderLeafCompositionTests
|
|||
"Composition",
|
||||
"SessionPlayerComposition.cs"));
|
||||
string source = GameWindowSource();
|
||||
string framePhase = FrameRootSource();
|
||||
|
||||
AssertAppearsInOrder(
|
||||
phase,
|
||||
|
|
@ -57,10 +58,13 @@ public sealed class GameWindowRenderLeafCompositionTests
|
|||
AssertAppearsInOrder(
|
||||
source,
|
||||
"new SessionPlayerCompositionPhase(",
|
||||
"new AcDream.App.Rendering.LocalPlayerTeleportRenderStateSource(",
|
||||
"new AcDream.App.Rendering.RenderFrameResourceController(",
|
||||
"new AcDream.App.Rendering.PrivatePresentationRenderer(",
|
||||
"new AcDream.App.Rendering.RenderFrameOrchestrator(");
|
||||
"new FrameRootCompositionPhase(");
|
||||
AssertAppearsInOrder(
|
||||
framePhase,
|
||||
"new LocalPlayerTeleportRenderStateSource(",
|
||||
"new RenderFrameResourceController(",
|
||||
"new PrivatePresentationRenderer(",
|
||||
"new RenderFrameOrchestrator(");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -111,10 +115,11 @@ public sealed class GameWindowRenderLeafCompositionTests
|
|||
"Composition",
|
||||
"SettingsDevToolsComposition.cs"));
|
||||
Assert.Contains("new DevToolsFramePresenter(", settingsComposition);
|
||||
Assert.Contains("new AcDream.App.Rendering.RenderFrameResourceController(", source);
|
||||
Assert.Contains("new AcDream.App.Rendering.RenderWeatherFrameController(", source);
|
||||
Assert.Contains("new AcDream.App.Rendering.PrivatePresentationRenderer(", source);
|
||||
Assert.Contains("new AcDream.App.Rendering.RenderFrameOrchestrator(", source);
|
||||
string framePhase = FrameRootSource();
|
||||
Assert.Contains("new RenderFrameResourceController(", framePhase);
|
||||
Assert.Contains("new RenderWeatherFrameController(", framePhase);
|
||||
Assert.Contains("new PrivatePresentationRenderer(", framePhase);
|
||||
Assert.Contains("new RenderFrameOrchestrator(", framePhase);
|
||||
Assert.Contains("new DisplayFramePacingController(", source);
|
||||
string pointerSource = File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
|
|
@ -142,7 +147,8 @@ public sealed class GameWindowRenderLeafCompositionTests
|
|||
AssertAppearsInOrder(
|
||||
source,
|
||||
"new ResourceShutdownStage(\"frame borrowers\"",
|
||||
"_frameGraphs.Withdraw();",
|
||||
"publication.Dispose();",
|
||||
"bindings.Dispose();",
|
||||
"new ResourceShutdownStage(\"session dependents\"");
|
||||
AssertAppearsInOrder(
|
||||
source,
|
||||
|
|
@ -150,7 +156,7 @@ public sealed class GameWindowRenderLeafCompositionTests
|
|||
"new(\"frame profiler\", _frameProfiler.Dispose)");
|
||||
AssertAppearsInOrder(
|
||||
source,
|
||||
"_frameGraphs.Withdraw();",
|
||||
"publication.Dispose();",
|
||||
"owner.DisposeFrontend()",
|
||||
"new ResourceShutdownStage(\"input\"",
|
||||
"_input?.Dispose();",
|
||||
|
|
@ -186,7 +192,7 @@ public sealed class GameWindowRenderLeafCompositionTests
|
|||
"private void OnRender(double deltaSeconds)",
|
||||
StringComparison.Ordinal);
|
||||
int end = source.IndexOf(
|
||||
"private AcDream.App.Diagnostics.WorldLifecycleResourceSnapshot",
|
||||
"private void OnFramebufferResize(",
|
||||
start,
|
||||
StringComparison.Ordinal);
|
||||
Assert.True(start >= 0 && end > start);
|
||||
|
|
@ -216,12 +222,12 @@ public sealed class GameWindowRenderLeafCompositionTests
|
|||
[Fact]
|
||||
public void TerrainAndFrameDiagnostics_AreComposedAsOneFocusedOwner()
|
||||
{
|
||||
string source = GameWindowSource();
|
||||
string source = FrameRootSource();
|
||||
|
||||
Assert.Contains(
|
||||
"new AcDream.App.Rendering.TerrainDrawDiagnosticsController(",
|
||||
"new TerrainDrawDiagnosticsController(",
|
||||
source);
|
||||
Assert.Contains("new AcDream.App.Rendering.WorldScenePassExecutor(", source);
|
||||
Assert.Contains("new WorldScenePassExecutor(", source);
|
||||
Assert.DoesNotContain("_terrainDrawDiagnostics!.Begin();", source);
|
||||
Assert.DoesNotContain("_terrainDrawDiagnostics.Complete();", source);
|
||||
}
|
||||
|
|
@ -240,6 +246,13 @@ public sealed class GameWindowRenderLeafCompositionTests
|
|||
"Composition",
|
||||
"LivePresentationComposition.cs"));
|
||||
|
||||
private static string FrameRootSource() => File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Composition",
|
||||
"FrameRootComposition.cs"));
|
||||
|
||||
private static string Source(string fileName) => File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
"src",
|
||||
|
|
|
|||
|
|
@ -65,10 +65,21 @@ public sealed class GameWindowSlice8BoundaryTests
|
|||
"new LivePresentationCompositionPhase(",
|
||||
"this).Compose(",
|
||||
"new SessionPlayerCompositionPhase(",
|
||||
"var renderFrameOrchestrator =",
|
||||
"var updateFrameOrchestrator = new AcDream.App.Update.UpdateFrameOrchestrator(",
|
||||
"_frameGraphs.Publish(updateFrameOrchestrator, renderFrameOrchestrator);",
|
||||
"sessionPlayer.SessionHost.Start(_options)");
|
||||
"FrameRootResult frameRoots = new FrameRootCompositionPhase(",
|
||||
"frameRoots.SessionHost.Start(_options)");
|
||||
|
||||
string framePhase = File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Composition",
|
||||
"FrameRootComposition.cs"));
|
||||
AssertAppearsInOrder(
|
||||
framePhase,
|
||||
"new RenderFrameOrchestrator(",
|
||||
"new UpdateFrameOrchestrator(",
|
||||
"d.FrameGraphs.PublishOwned(",
|
||||
"_publication.PublishFrameRoots(result);");
|
||||
|
||||
string sessionPhase = File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
|
|
@ -86,7 +97,7 @@ public sealed class GameWindowSlice8BoundaryTests
|
|||
"_publication.PublishSessionPlayer(result);");
|
||||
Assert.Equal(1, CountOccurrences(
|
||||
body,
|
||||
"sessionPlayer.SessionHost.Start(_options)"));
|
||||
"frameRoots.SessionHost.Start(_options)"));
|
||||
string phaseOne = Slice(
|
||||
File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
|
|
@ -107,7 +118,7 @@ public sealed class GameWindowSlice8BoundaryTests
|
|||
phaseOne,
|
||||
StringComparison.Ordinal);
|
||||
int start = body.IndexOf(
|
||||
"sessionPlayer.SessionHost.Start(_options)",
|
||||
"frameRoots.SessionHost.Start(_options)",
|
||||
StringComparison.Ordinal);
|
||||
string postStart = body[start..];
|
||||
Assert.Contains("switch (liveStart.Status)", postStart, StringComparison.Ordinal);
|
||||
|
|
@ -331,7 +342,8 @@ public sealed class GameWindowSlice8BoundaryTests
|
|||
"this).Compose(platform, hostInputCamera, contentEffectsAudio);",
|
||||
"new WorldRenderCompositionPhase(",
|
||||
"new SessionPlayerCompositionPhase(",
|
||||
"sessionPlayer.SessionHost.Start(_options)");
|
||||
"new FrameRootCompositionPhase(",
|
||||
"frameRoots.SessionHost.Start(_options)");
|
||||
string sessionPhase = File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
"src",
|
||||
|
|
@ -385,7 +397,7 @@ public sealed class GameWindowSlice8BoundaryTests
|
|||
string render = Slice(
|
||||
source,
|
||||
"private void OnRender(double deltaSeconds)",
|
||||
"private AcDream.App.Diagnostics.WorldLifecycleResourceSnapshot");
|
||||
"private void OnFramebufferResize(");
|
||||
string focus = Slice(
|
||||
source,
|
||||
"private void OnFocusChanged(bool focused)",
|
||||
|
|
@ -524,6 +536,12 @@ public sealed class GameWindowSlice8BoundaryTests
|
|||
"AcDream.App",
|
||||
"Composition",
|
||||
"SessionPlayerComposition.cs"));
|
||||
string framePhase = File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Composition",
|
||||
"FrameRootComposition.cs"));
|
||||
|
||||
AssertAppearsInOrder(
|
||||
livePhase,
|
||||
|
|
@ -536,7 +554,12 @@ public sealed class GameWindowSlice8BoundaryTests
|
|||
"new WorldRenderCompositionPhase(",
|
||||
"new LivePresentationCompositionPhase(",
|
||||
"new SessionPlayerCompositionPhase(",
|
||||
"_frameGraphs.Publish(updateFrameOrchestrator, renderFrameOrchestrator);");
|
||||
"new FrameRootCompositionPhase(");
|
||||
AssertAppearsInOrder(
|
||||
framePhase,
|
||||
"new RenderFrameOrchestrator(",
|
||||
"new UpdateFrameOrchestrator(",
|
||||
"d.FrameGraphs.PublishOwned(");
|
||||
AssertAppearsInOrder(
|
||||
sessionPhase,
|
||||
"d.PortalTunnelFallback.Transfer(",
|
||||
|
|
@ -550,7 +573,8 @@ public sealed class GameWindowSlice8BoundaryTests
|
|||
"TerrainModernRenderer terrain = AcquireAndPublish(");
|
||||
AssertAppearsInOrder(
|
||||
shutdown,
|
||||
"_frameGraphs.Withdraw();",
|
||||
"publication.Dispose();",
|
||||
"bindings.Dispose();",
|
||||
"_retailUiLease.Dispose();",
|
||||
"_localPlayerTeleport?.Dispose();",
|
||||
"_portalTunnelFallback.ReleaseFallback();",
|
||||
|
|
|
|||
|
|
@ -225,11 +225,11 @@ public sealed class RetailPViewPassExecutorTests
|
|||
FindRepoRoot(),
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Rendering",
|
||||
"GameWindow.cs"));
|
||||
"Composition",
|
||||
"FrameRootComposition.cs"));
|
||||
|
||||
Assert.Contains("new AcDream.App.Rendering.RetailPViewPassExecutor(", source);
|
||||
Assert.Contains("new AcDream.App.Rendering.WorldScenePViewRenderer(", source);
|
||||
Assert.Contains("new RetailPViewPassExecutor(", source);
|
||||
Assert.Contains("new WorldScenePViewRenderer(", source);
|
||||
Assert.DoesNotContain("new AcDream.App.Rendering.RetailPViewFrameInput", source);
|
||||
Assert.DoesNotContain("RetailPViewDrawContext", source);
|
||||
Assert.DoesNotContain("DrawLandscapeSlice =", source);
|
||||
|
|
|
|||
|
|
@ -152,6 +152,28 @@ public sealed class RuntimeResourceSlotTests
|
|||
Assert.Equal(["update:2"], calls);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OwnedFramePublicationWithdrawsOnlyItsExactPair()
|
||||
{
|
||||
var calls = new List<string>();
|
||||
var slot = new GameFrameGraphSlot();
|
||||
IDisposable stale = slot.PublishOwned(
|
||||
new RecordingUpdateRoot(calls),
|
||||
new RecordingRenderRoot(calls));
|
||||
|
||||
stale.Dispose();
|
||||
IDisposable current = slot.PublishOwned(
|
||||
new RecordingUpdateRoot(calls),
|
||||
new RecordingRenderRoot(calls));
|
||||
stale.Dispose();
|
||||
|
||||
Assert.True(slot.Tick(new UpdateFrameInput(3)));
|
||||
current.Dispose();
|
||||
current.Dispose();
|
||||
Assert.False(slot.Tick(new UpdateFrameInput(4)));
|
||||
Assert.Equal(["update:3"], calls);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OwnedSlotRejectsReentrantAcquireWithoutLosingOuterResource()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -328,6 +328,12 @@ public sealed class WorldRenderFrameBuilderTests
|
|||
public void World_scene_uses_the_typed_builder_and_orchestrator_owns_its_local_composition()
|
||||
{
|
||||
string gameWindow = GameWindowSource();
|
||||
string frameRoot = File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Composition",
|
||||
"FrameRootComposition.cs"));
|
||||
string worldScene = File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
"src",
|
||||
|
|
@ -357,11 +363,14 @@ public sealed class WorldRenderFrameBuilderTests
|
|||
"_passes.DrawFlatTerrain(",
|
||||
"NormalWorldDrawn: true");
|
||||
AssertAppearsInOrder(
|
||||
gameWindow,
|
||||
"var skyPesFrame = new AcDream.App.Rendering.SkyPesFrameController(",
|
||||
frameRoot,
|
||||
"var skyPesFrame = new SkyPesFrameController(",
|
||||
"var worldRenderFrameBuilder =",
|
||||
"new AcDream.App.Rendering.RenderFrameOrchestrator(",
|
||||
"_frameGraphs.Withdraw();",
|
||||
"new RenderFrameOrchestrator(",
|
||||
"d.FrameGraphs.PublishOwned(");
|
||||
AssertAppearsInOrder(
|
||||
gameWindow,
|
||||
"publication.Dispose();",
|
||||
"new(\"equipped children\"",
|
||||
"new(\"effect network state\"",
|
||||
"new(\"audio\"",
|
||||
|
|
|
|||
|
|
@ -279,11 +279,11 @@ public sealed class WorldSceneRendererTests
|
|||
FindRepoRoot(),
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Rendering",
|
||||
"GameWindow.cs"));
|
||||
"Composition",
|
||||
"FrameRootComposition.cs"));
|
||||
|
||||
Assert.Contains("new AcDream.App.Rendering.WorldSceneRenderer(", source);
|
||||
Assert.Contains("new AcDream.App.Rendering.RenderFrameOrchestrator(", source);
|
||||
Assert.Contains("new WorldSceneRenderer(", source);
|
||||
Assert.Contains("new RenderFrameOrchestrator(", source);
|
||||
Assert.DoesNotContain("_worldSceneRenderer", source);
|
||||
Assert.DoesNotContain("_retailPViewRenderer.DrawInside(", source);
|
||||
Assert.DoesNotContain("_retailAlphaQueue.BeginFrame();", source);
|
||||
|
|
|
|||
|
|
@ -276,10 +276,16 @@ public sealed class UpdateFrameOrchestratorTests
|
|||
"AcDream.App",
|
||||
"Update",
|
||||
"UpdateFrameRuntimeAdapters.cs"));
|
||||
string frameRoot = File.ReadAllText(Path.Combine(
|
||||
root,
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Composition",
|
||||
"FrameRootComposition.cs"));
|
||||
|
||||
Assert.Equal(0, CountOccurrences(source, "PublishTime("));
|
||||
Assert.Equal(1, CountOccurrences(adapters, "_runner.PublishTime("));
|
||||
Assert.Contains("new AcDream.App.Update.PhysicsScriptClockPublisher(", source,
|
||||
Assert.Contains("new PhysicsScriptClockPublisher(", frameRoot,
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
|
|
@ -349,10 +355,16 @@ public sealed class UpdateFrameOrchestratorTests
|
|||
"AcDream.App",
|
||||
"Composition",
|
||||
"SessionPlayerComposition.cs"));
|
||||
string frameRoot = File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Composition",
|
||||
"FrameRootComposition.cs"));
|
||||
|
||||
Assert.Contains("new LiveObjectFrameController(", sessionPlayer);
|
||||
Assert.Contains("new LiveSpatialPresentationReconciler(", sessionPlayer);
|
||||
Assert.Contains("new AcDream.App.World.RetailLiveFrameCoordinator(", source);
|
||||
Assert.Contains("new RetailLiveFrameCoordinator(", frameRoot);
|
||||
Assert.DoesNotContain("AdvanceLiveObjectRuntime", source, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("ReconcileLiveObjectSpatialPresentation", source,
|
||||
StringComparison.Ordinal);
|
||||
|
|
@ -375,7 +387,6 @@ public sealed class UpdateFrameOrchestratorTests
|
|||
"AcDream.App",
|
||||
"Composition",
|
||||
"SessionPlayerComposition.cs"));
|
||||
|
||||
Assert.Contains("new StreamingFrameController(", sessionPlayer);
|
||||
Assert.DoesNotContain("_streamingFrame", source, StringComparison.Ordinal);
|
||||
Assert.Equal(1, CountOccurrences(
|
||||
|
|
@ -492,6 +503,12 @@ public sealed class UpdateFrameOrchestratorTests
|
|||
"AcDream.App",
|
||||
"Composition",
|
||||
"SessionPlayerComposition.cs"));
|
||||
string frameRoot = File.ReadAllText(Path.Combine(
|
||||
root,
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Composition",
|
||||
"FrameRootComposition.cs"));
|
||||
|
||||
Assert.Contains(
|
||||
"new LocalPlayerTeleportController(",
|
||||
|
|
@ -513,10 +530,10 @@ public sealed class UpdateFrameOrchestratorTests
|
|||
Assert.Contains("ILocalPlayerTeleportNetworkSink", networkSource,
|
||||
StringComparison.Ordinal);
|
||||
AssertAppearsInOrder(
|
||||
source,
|
||||
"new AcDream.App.Update.LiveEntityLivenessFramePhase(",
|
||||
"sessionPlayer.LocalTeleport,",
|
||||
"new AcDream.App.Update.PlayerModeAutoEntryFramePhase(",
|
||||
frameRoot,
|
||||
"new LiveEntityLivenessFramePhase(",
|
||||
"session.LocalTeleport,",
|
||||
"new PlayerModeAutoEntryFramePhase(",
|
||||
"cameraFrame);");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue