feat(runtime): define borrowed views commands and ordered events
Establish the J1 presentation-independent contract with instance-scoped clocks and generations, immutable borrowed views, typed generation-gated commands, normalized ordered diagnostics, and teardown acknowledgements. Route graphical startup plus press-time selection, movement, and combat through focused App adapters over the exact existing owners without adding a queue or mirrored world. Validated by the Release solution build, 13 Runtime tests, 3,838 App tests with three existing skips, and the complete 8,424-test Release suite with five existing skips. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
afebbe3eca
commit
854d9e9cd1
21 changed files with 2594 additions and 44 deletions
125
tests/AcDream.Runtime.Tests/GameRuntimeContractTests.cs
Normal file
125
tests/AcDream.Runtime.Tests/GameRuntimeContractTests.cs
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
namespace AcDream.Runtime.Tests;
|
||||
|
||||
public sealed class GameRuntimeContractTests
|
||||
{
|
||||
[Fact]
|
||||
public void InstanceClock_NormalizesHostTimeAndCanFreezeSimulation()
|
||||
{
|
||||
var first = new GameRuntimeClock();
|
||||
var second = new GameRuntimeClock();
|
||||
|
||||
RuntimeFrameTime frame1 = first.Advance(0.25);
|
||||
RuntimeFrameTime frozen = first.Advance(0.5, advanceSimulationTime: false);
|
||||
RuntimeFrameTime invalid = first.Advance(double.NaN);
|
||||
|
||||
Assert.Equal(1UL, frame1.FrameNumber);
|
||||
Assert.Equal(0.25, frame1.DeltaSeconds);
|
||||
Assert.Equal(0.25, frame1.SimulationTimeSeconds);
|
||||
Assert.Equal(2UL, frozen.FrameNumber);
|
||||
Assert.Equal(0.5, frozen.DeltaSeconds);
|
||||
Assert.Equal(0.25, frozen.SimulationTimeSeconds);
|
||||
Assert.Equal(3UL, invalid.FrameNumber);
|
||||
Assert.Equal(0.0, invalid.DeltaSeconds);
|
||||
Assert.Equal(0.25, invalid.SimulationTimeSeconds);
|
||||
Assert.Equal(0UL, second.FrameNumber);
|
||||
Assert.Equal(0.0, second.SimulationTimeSeconds);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(double.NegativeInfinity)]
|
||||
[InlineData(double.PositiveInfinity)]
|
||||
[InlineData(double.NaN)]
|
||||
[InlineData(-1.0)]
|
||||
[InlineData(0.0)]
|
||||
public void InstanceClock_InvalidDeltaNormalizesToZero(double input)
|
||||
{
|
||||
Assert.Equal(0.0, GameRuntimeClock.NormalizeDeltaSeconds(input));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenerationAndTeardownAcknowledgementAreExact()
|
||||
{
|
||||
RuntimeGenerationToken first = RuntimeGenerationToken.Initial.Next();
|
||||
var complete = new RuntimeTeardownAcknowledgement(
|
||||
first,
|
||||
first.Next(),
|
||||
RuntimeCommandStatus.Accepted,
|
||||
RuntimeTeardownStage.Complete);
|
||||
var stale = complete with
|
||||
{
|
||||
Status = RuntimeCommandStatus.StaleGeneration,
|
||||
};
|
||||
var partial = complete with
|
||||
{
|
||||
CompletedStages =
|
||||
RuntimeTeardownStage.CommandsInert
|
||||
| RuntimeTeardownStage.InboundDetached,
|
||||
};
|
||||
|
||||
Assert.Equal(1UL, first.Value);
|
||||
Assert.True(complete.IsComplete);
|
||||
Assert.False(stale.IsComplete);
|
||||
Assert.False(partial.IsComplete);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EventSequencersAreMonotonicAndInstanceScoped()
|
||||
{
|
||||
var first = new RuntimeEventSequencer();
|
||||
var second = new RuntimeEventSequencer();
|
||||
var generation = new RuntimeGenerationToken(7);
|
||||
|
||||
RuntimeEventStamp one = first.Next(generation, frameNumber: 11);
|
||||
RuntimeEventStamp two = first.Next(generation, frameNumber: 12);
|
||||
RuntimeEventStamp independent = second.Next(generation, frameNumber: 99);
|
||||
|
||||
Assert.Equal(1UL, one.Sequence);
|
||||
Assert.Equal(2UL, two.Sequence);
|
||||
Assert.Equal(1UL, independent.Sequence);
|
||||
Assert.Equal(12UL, two.FrameNumber);
|
||||
Assert.Equal(99UL, independent.FrameNumber);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TraceRecorderNormalizesTypedDeltasWithoutRetainingOwners()
|
||||
{
|
||||
var recorder = new RuntimeTraceRecorder();
|
||||
var stamp = new RuntimeEventStamp(
|
||||
new RuntimeGenerationToken(3),
|
||||
Sequence: 1,
|
||||
FrameNumber: 8);
|
||||
var command = new RuntimeCommandDelta(
|
||||
stamp,
|
||||
RuntimeCommandDomain.Selection,
|
||||
(int)RuntimeSelectionCommand.SelectClosestHostile,
|
||||
RuntimeCommandStatus.Accepted,
|
||||
PrimaryObjectId: 0x50000001u);
|
||||
var chat = new RuntimeChatDelta(
|
||||
stamp with { Sequence = 2 },
|
||||
new RuntimeChatEntry(
|
||||
Revision: 4,
|
||||
SenderGuid: 0x50000002u,
|
||||
Kind: 2,
|
||||
Sender: "Grey",
|
||||
Text: "hello",
|
||||
ChannelName: "General"));
|
||||
|
||||
recorder.OnCommand(in command);
|
||||
recorder.OnChat(in chat);
|
||||
|
||||
Assert.Collection(
|
||||
recorder.Entries,
|
||||
entry =>
|
||||
{
|
||||
Assert.Equal(RuntimeTraceKind.Command, entry.Kind);
|
||||
Assert.Equal(0x50000001u, entry.PrimaryObjectId);
|
||||
Assert.Equal((long)RuntimeCommandStatus.Accepted, entry.Value);
|
||||
},
|
||||
entry =>
|
||||
{
|
||||
Assert.Equal(RuntimeTraceKind.Chat, entry.Kind);
|
||||
Assert.Equal(4L, entry.Value);
|
||||
Assert.Equal("General|Grey|hello", entry.Text);
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue