diff --git a/tests/DeterministicSim.Engine.Tests.csproj b/tests/DeterministicSim.Engine.Tests.csproj index ca14eb3..10e4f42 100644 --- a/tests/DeterministicSim.Engine.Tests.csproj +++ b/tests/DeterministicSim.Engine.Tests.csproj @@ -34,6 +34,7 @@ + diff --git a/tests/unit/core/EntityAgnosticTests.cs b/tests/unit/core/EntityAgnosticTests.cs new file mode 100644 index 0000000..4ecf879 --- /dev/null +++ b/tests/unit/core/EntityAgnosticTests.cs @@ -0,0 +1,130 @@ +using DeterministicSim.Engine.Core; +using DeterministicSim.Engine.Net; +using Xunit; +using System.Runtime.CompilerServices; + +namespace DeterministicSim.Engine.Tests.Core; + +public class EntityAgnosticTests +{ + [Fact] + public void GameState_1Entity_InitializesCorrectly() + { + var state = new GameState(1); + Assert.Equal(1, state.EntityCount); + + state.SetPosX(0, 100); + state.SetPosY(0, 200); + + Assert.Equal(100, state.GetPosX(0)); + Assert.Equal(200, state.GetPosY(0)); + Assert.True(state.IsActive(0)); // Should be active by default + } + + [Fact] + public void GameState_100Entities_InitializesCorrectly() + { + var state = new GameState(100); + Assert.Equal(100, state.EntityCount); + + for (int i = 0; i < 100; i++) + { + state.SetPosX(i, i * 10); + state.SetPosY(i, i * 20); + state.SetVelX(i, i * 2); + state.SetVelY(i, i * 3); + state.SetActive(i, i % 2 == 0); + } + + for (int i = 0; i < 100; i++) + { + Assert.Equal(i * 10, state.GetPosX(i)); + Assert.Equal(i * 20, state.GetPosY(i)); + Assert.Equal(i * 2, state.GetVelX(i)); + Assert.Equal(i * 3, state.GetVelY(i)); + Assert.Equal(i % 2 == 0, state.IsActive(i)); + } + } + + [Fact] + public void GameState_CopyFrom_MismatchEntityCount_HandlesGracefully() + { + var src = new GameState(10); + for(int i = 0; i < 10; i++) + { + src.SetPosX(i, i * 100); + } + + var dst = new GameState(5); + dst.CopyFrom(src); + + // Should only copy up to Math.Min(src.EntityCount, dst.EntityCount) + for(int i = 0; i < 5; i++) + { + Assert.Equal(i * 100, dst.GetPosX(i)); + } + + var dst2 = new GameState(15); + dst2.CopyFrom(src); + for(int i = 0; i < 10; i++) + { + Assert.Equal(i * 100, dst2.GetPosX(i)); + } + for(int i = 10; i < 15; i++) + { + Assert.Equal(0, dst2.GetPosX(i)); + } + } + + [Fact] + public void RollbackController_1Player_WorksCorrectly() + { + var config = RollbackConfig.Default(); + config.PlayerCount = 1; + + var controller = new RollbackController(config); + + var inputFrame = new InputFrame(1, 1); + inputFrame.SetPlayerInputs(0, 42); + + controller.SaveInputs(1, inputFrame); + + var storedFrame = controller.GetInputs(1); + Assert.Equal(1, storedFrame.PlayerCount); + Assert.Equal(42, storedFrame.GetPlayerInputs(0)); + + controller.SaveState(1); + var state = controller.GetState(1); + Assert.NotNull(state); + Assert.Equal(1, state!.EntityCount); + } + + [Fact] + public void RollbackController_4Players_WorksCorrectly() + { + var config = RollbackConfig.Default(); + config.PlayerCount = 4; + + var controller = new RollbackController(config); + + var inputFrame = new InputFrame(1, 4); + inputFrame.SetPlayerInputs(0, 10); + inputFrame.SetPlayerInputs(1, 20); + inputFrame.SetPlayerInputs(2, 30); + inputFrame.SetPlayerInputs(3, 40); + + controller.SaveInputs(1, inputFrame); + + var storedFrame = controller.GetInputs(1); + Assert.Equal(4, storedFrame.PlayerCount); + Assert.Equal(10, storedFrame.GetPlayerInputs(0)); + Assert.Equal(20, storedFrame.GetPlayerInputs(1)); + Assert.Equal(30, storedFrame.GetPlayerInputs(2)); + Assert.Equal(40, storedFrame.GetPlayerInputs(3)); + + controller.SaveState(1); + var state = controller.GetState(1); + Assert.NotNull(state); + Assert.Equal(4, state!.EntityCount); + } +}