acdream/tests/AcDream.App.Tests/Runtime/RuntimeMovementOwnershipTests.cs
Erik aa3f4a60f8 refactor(runtime): own local movement and outbound cadence
Move the canonical local movement controller, body/motion managers, object clock, movement wire data, and MTS/jump/AP sender into AcDream.Runtime. Replace process skill defaults with typed Runtime character options, make graphical and direct commands borrow one autorun owner, retain the construction-time PartArray seam, and include movement in terminal ownership convergence.

Preserve the accepted pre-inbound movement/jump and post-inbound autonomous-position order while moving the exact packet/cadence fixtures into Runtime tests. Add graphical/direct parity, two-instance isolation, teardown, allocation, architecture, and divergence-path coverage.

Co-authored-by: Codex <noreply@openai.com>
2026-07-26 12:33:53 +02:00

123 lines
4.2 KiB
C#

using System.Text.RegularExpressions;
namespace AcDream.App.Tests.Runtime;
public sealed class RuntimeMovementOwnershipTests
{
[Fact]
public void ProductionConstructsOneCanonicalRuntimeMovementOwner()
{
string root = FindRepositoryRoot();
string appRoot = Path.Combine(root, "src", "AcDream.App");
string runtimeRoot = Path.Combine(root, "src", "AcDream.Runtime");
string app = string.Join(
"\n",
Directory.EnumerateFiles(appRoot, "*.cs", SearchOption.AllDirectories)
.Select(File.ReadAllText));
string runtime = string.Join(
"\n",
Directory.EnumerateFiles(runtimeRoot, "*.cs", SearchOption.AllDirectories)
.Select(File.ReadAllText));
Assert.False(File.Exists(Path.Combine(
appRoot,
"Input",
"PlayerMovementController.cs")));
Assert.False(File.Exists(Path.Combine(
appRoot,
"Input",
"LocalPlayerOutboundController.cs")));
Assert.DoesNotContain(
"class PlayerMovementController",
app,
StringComparison.Ordinal);
Assert.DoesNotContain(
"class LocalPlayerOutboundController",
app,
StringComparison.Ordinal);
Assert.Empty(Regex.Matches(app, @"\bbool\s+_autoRunActive\b"));
Assert.Single(Regex.Matches(
app,
@"RuntimeLocalPlayerMovementState\s+\w+\s*=\s*new\s*\(")
.Cast<Match>());
Assert.DoesNotContain(
"ACDREAM_RUN_SKILL",
runtime,
StringComparison.Ordinal);
Assert.DoesNotContain(
"ACDREAM_JUMP_SKILL",
runtime,
StringComparison.Ordinal);
}
[Fact]
public void GraphicalInputRuntimeViewsAndShutdownBorrowTheExactOwner()
{
string root = FindRepositoryRoot();
string gameWindow = ReadAppSource(root, "Rendering", "GameWindow.cs");
string input = ReadAppSource(
root,
"Input",
"DispatcherMovementInputSource.cs");
string view = ReadAppSource(
root,
"Runtime",
"CurrentGameRuntimeViewAdapter.cs");
string commands = ReadAppSource(
root,
"Runtime",
"CurrentGameRuntimeCommandAdapter.cs");
string lifetime = ReadAppSource(
root,
"Rendering",
"GameWindowLifetime.cs");
Assert.Contains(
"RuntimeLocalPlayerMovementState _playerControllerSlot = new();",
gameWindow,
StringComparison.Ordinal);
Assert.Contains(
"new AcDream.App.Input.DispatcherMovementInputSource(",
gameWindow,
StringComparison.Ordinal);
Assert.Contains(
"_playerControllerSlot,",
gameWindow,
StringComparison.Ordinal);
Assert.Contains(
"RuntimeLocalPlayerMovementState movement,",
input,
StringComparison.Ordinal);
Assert.Contains("_movement.AutoRunActive", input, StringComparison.Ordinal);
Assert.Contains(
"movement ?? throw new ArgumentNullException(nameof(movement))).View",
view,
StringComparison.Ordinal);
Assert.Contains("_movement.Execute(command)", commands, StringComparison.Ordinal);
Assert.Contains(
"RuntimeLocalPlayerMovementState Movement",
lifetime,
StringComparison.Ordinal);
Assert.Contains(
"\"runtime local movement state\"",
lifetime,
StringComparison.Ordinal);
}
private static string ReadAppSource(string root, params string[] relative) =>
File.ReadAllText(Path.Combine(
[root, "src", "AcDream.App", .. relative]));
private static string FindRepositoryRoot()
{
var current = new DirectoryInfo(AppContext.BaseDirectory);
while (current is not null)
{
if (File.Exists(Path.Combine(current.FullName, "AcDream.slnx")))
return current.FullName;
current = current.Parent;
}
throw new DirectoryNotFoundException("AcDream.slnx was not found.");
}
}