using System.Collections.Immutable; using SideScrollerGame.Sim.Definitions; using SideScrollerGame.Sim.Input; namespace SideScrollerGame.Sim.Tests; public sealed class SimulationStepTests { private sealed record UnsupportedAction : SimulationAction; [Fact] public void Step_AdvancesTickSnapshotsAndMovement() { Simulation simulation = new(SimulationTestFactory.CreateGameDefinition(), SimulationTestFactory.CreateConfig(), 7); var result = simulation.Step(SimulationTestFactory.CreateTick(1, new MoveAxisChanged(new(1), 2, -1), new AimAxisChanged(new(1), 30, 40), new ButtonChanged(new(1), InputButton.Jump, true), new WeaponSlotSelected(new(1), 3))); Assert.Equal(1, simulation.CurrentTick); Assert.Equal(0, simulation.PreviousSnapshot.Tick); Assert.Equal(0, result.PreviousSnapshot.Tick); Assert.Equal(1, result.CurrentSnapshot.Tick); Assert.Single(result.Events); var player = simulation.CurrentState.GetRequiredPlayer(new(1)); Assert.Equal(12, player.Position.m_X.ToIntRound()); Assert.Equal(19, player.Position.m_Y.ToIntRound()); Assert.Equal(30, player.AimAxisX); Assert.Equal(40, player.AimAxisY); Assert.Equal(3, player.SelectedWeaponSlot); Assert.NotEqual(0, player.ButtonMask); Assert.Equal(result.StateHash, simulation.CurrentSnapshot.StateHash); Assert.NotEqual(0UL, simulation.CurrentSnapshot.LastRandomValue); } [Fact] public void Step_RejectsUnexpectedTickNumbers() { Simulation simulation = new(SimulationTestFactory.CreateGameDefinition(), SimulationTestFactory.CreateConfig(), 7); var exception = Assert.Throws(() => simulation.Step(TickActionBatch.Empty(2))); Assert.Contains("Expected tick 1", exception.Message); } [Fact] public void Step_RejectsUnknownPlayers() { Simulation simulation = new(SimulationTestFactory.CreateGameDefinition(), SimulationTestFactory.CreateConfig(), 7); var exception = Assert.Throws(() => simulation.Step(SimulationTestFactory.CreateTick(1, new MoveAxisChanged(new(99), 1, 0)))); Assert.Contains("Unknown player id 99", exception.Message); } [Fact] public void Step_RejectsUnsupportedActions() { Simulation simulation = new(SimulationTestFactory.CreateGameDefinition(), SimulationTestFactory.CreateConfig(), 7); var exception = Assert.Throws(() => simulation.Step(SimulationTestFactory.CreateTick(1, new UnsupportedAction()))); Assert.Contains("Unsupported action type", exception.Message); } [Fact] public void Constructor_RejectsDuplicatePlayers() { GameDefinition definition = new(ImmutableArray.Create(new(new(1), new(0, 0)), new PlayerDefinition(new(1), new(2, 3)))); var exception = Assert.Throws(() => new Simulation(definition, SimulationTestFactory.CreateConfig(), 11)); Assert.Contains("Duplicate player id 1", exception.Message); } [Fact] public void Constructor_RejectsNullDefinition() { var exception = Assert.Throws(() => new Simulation(null!, SimulationTestFactory.CreateConfig(), 1)); Assert.Equal("gameDefinition", exception.ParamName); } [Fact] public void Constructor_RejectsNullConfig() { var exception = Assert.Throws(() => new Simulation(SimulationTestFactory.CreateGameDefinition(), null!, 1)); Assert.Equal("config", exception.ParamName); } [Fact] public void LoadState_RejectsNullDefinition() { var definition = SimulationTestFactory.CreateGameDefinition(); var config = SimulationTestFactory.CreateConfig(); Simulation simulation = new(definition, config, 2); var bytes = simulation.SaveState(); var exception = Assert.Throws(() => Simulation.LoadState(bytes, null!, config)); Assert.Equal("gameDefinition", exception.ParamName); } }