test: replace input and physics source freezes
This commit is contained in:
parent
0ad2ee1cdf
commit
caa5eb8b2b
6 changed files with 313 additions and 238 deletions
|
|
@ -1,10 +1,18 @@
|
|||
using System.Reflection;
|
||||
using AcDream.App.Input;
|
||||
using AcDream.App.Tests.Architecture;
|
||||
using AcDream.App.World;
|
||||
using AcDream.Core.Physics;
|
||||
using AcDream.Core.Physics.Motion;
|
||||
|
||||
namespace AcDream.App.Tests.Input;
|
||||
|
||||
/// <summary>
|
||||
/// C3c-F2 (2026-08-02): source pin for the production player-mode auto-entry
|
||||
/// precondition. <c>PlayerModeAutoEntry</c> is a ONE-SHOT that disarms before
|
||||
/// invoking its callback, and the production callback completes the world
|
||||
/// reveal, so an attempt made before the Runtime first-entry conductor has
|
||||
/// C3c-F2 (2026-08-02): compiled architecture check for the production
|
||||
/// player-mode auto-entry precondition. <c>PlayerModeAutoEntry</c> is a
|
||||
/// ONE-SHOT that disarms before invoking its callback, and the production
|
||||
/// callback completes the world reveal, so an attempt made before the Runtime
|
||||
/// first-entry conductor has
|
||||
/// committed permanently seals the reveal with the player never in world —
|
||||
/// the second link of the connected-gate login wedge
|
||||
/// (logs/connected-world-gate-20260802-130455: one "not committed yet" line,
|
||||
|
|
@ -14,45 +22,61 @@ namespace AcDream.App.Tests.Input;
|
|||
/// The guard's own one-shot/latch behavior is covered behaviorally by
|
||||
/// AcDream.Core.Tests.Input.AutoEnterPlayerModeTests; only the production
|
||||
/// context's dependency graph (a ~15-dependency PlayerModeController) has no
|
||||
/// focused harness, hence the source pin.
|
||||
/// focused harness, hence the metadata check.
|
||||
/// </summary>
|
||||
public sealed class C3cF2AutoEntryWiringTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProductionAutoEntryRequiresTheRuntimePublishedController()
|
||||
{
|
||||
string source = ReadSource("Input", "PlayerModeAutoEntry.cs");
|
||||
MethodInfo readiness = typeof(LivePlayerModeAutoEntryContext)
|
||||
.GetProperty(
|
||||
"IsPlayerControllerReady",
|
||||
BindingFlags.Instance | BindingFlags.Public)!
|
||||
.GetMethod!;
|
||||
IReadOnlyList<CompiledCall> calls = CompiledCallGraph.Read(readiness);
|
||||
|
||||
Assert.DoesNotContain(
|
||||
"public bool IsPlayerControllerReady => true;",
|
||||
source,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"IsRuntimePublished: true",
|
||||
source,
|
||||
StringComparison.Ordinal);
|
||||
calls,
|
||||
call => call.Target.DeclaringType == typeof(PlayerMovementController)
|
||||
&& call.Target.Name == "get_IsRuntimePublished");
|
||||
Assert.Contains(
|
||||
"record.PhysicsHost is EntityPhysicsHost",
|
||||
source,
|
||||
StringComparison.Ordinal);
|
||||
calls,
|
||||
call => call.Target.DeclaringType == typeof(LiveEntityRuntime)
|
||||
&& call.Target.Name == nameof(LiveEntityRuntime.TryGetRecord));
|
||||
Assert.Contains(
|
||||
calls,
|
||||
call => call.Target.DeclaringType == typeof(LiveEntityRecord)
|
||||
&& call.Target.Name == "get_PhysicsHost");
|
||||
Assert.Contains(
|
||||
typeof(EntityPhysicsHost),
|
||||
CompiledCallGraph.ReadTypeReferences(readiness));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PlayerPresentationAttach_DrainsMatchedAnimationsBeforeStartupMotionSuffix()
|
||||
{
|
||||
string source = ReadSource("Input", "PlayerModeController.cs");
|
||||
|
||||
int attach = source.IndexOf(
|
||||
"controller.Motion.DefaultSink =",
|
||||
StringComparison.Ordinal);
|
||||
int animationDrain = source.IndexOf(
|
||||
"sequencer.Manager.HandleEnterWorld();",
|
||||
attach,
|
||||
StringComparison.Ordinal);
|
||||
int unmatchedMotionDrain = source.IndexOf(
|
||||
"controller.Motion.HandleExitWorld();",
|
||||
animationDrain,
|
||||
StringComparison.Ordinal);
|
||||
MethodInfo enter = typeof(PlayerModeController).GetMethod(
|
||||
"BuildControllerAndCamera",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic)
|
||||
?? throw new MissingMethodException(
|
||||
typeof(PlayerModeController).FullName,
|
||||
"BuildControllerAndCamera");
|
||||
IReadOnlyList<CompiledCall> calls = CompiledCallGraph.Read(enter);
|
||||
int attach = CompiledCallGraph.IndexOf(
|
||||
calls,
|
||||
typeof(MotionInterpreter),
|
||||
"set_DefaultSink");
|
||||
int animationDrain = CompiledCallGraph.IndexOf(
|
||||
calls,
|
||||
typeof(MotionTableManager),
|
||||
nameof(MotionTableManager.HandleEnterWorld),
|
||||
attach + 1);
|
||||
int unmatchedMotionDrain = CompiledCallGraph.IndexOf(
|
||||
calls,
|
||||
typeof(MotionInterpreter),
|
||||
nameof(MotionInterpreter.HandleExitWorld),
|
||||
animationDrain + 1);
|
||||
|
||||
Assert.True(attach >= 0, "The player animation sink was not attached.");
|
||||
Assert.True(
|
||||
|
|
@ -62,24 +86,4 @@ public sealed class C3cF2AutoEntryWiringTests
|
|||
unmatchedMotionDrain > animationDrain,
|
||||
"Only the unmatched pre-attach interpreter suffix may drain last.");
|
||||
}
|
||||
|
||||
private static string ReadSource(params string[] relativePath)
|
||||
{
|
||||
DirectoryInfo? directory = new(AppContext.BaseDirectory);
|
||||
while (directory is not null)
|
||||
{
|
||||
if (File.Exists(Path.Combine(directory.FullName, "AcDream.slnx")))
|
||||
{
|
||||
return File.ReadAllText(Path.Combine(
|
||||
directory.FullName,
|
||||
"src",
|
||||
"AcDream.App",
|
||||
Path.Combine(relativePath)));
|
||||
}
|
||||
|
||||
directory = directory.Parent;
|
||||
}
|
||||
|
||||
throw new DirectoryNotFoundException("Could not find AcDream.slnx.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue