using System.Text.Json; using GameCli; using Xunit; namespace GameCli.Tests; public class ProtocolTests { [Fact] public void StepInput_ParsesActionAndTarget() { var json = """{"action":2,"target":[0.35,0.60]}"""; var input = JsonSerializer.Deserialize(json, ProtocolJsonContext.Default.StepInput); Assert.NotNull(input); Assert.Equal(2, input!.Action); Assert.NotNull(input.Target); Assert.Equal(0.35f, input.Target![0]); Assert.Equal(0.60f, input.Target![1]); Assert.Null(input.Cmd); } [Fact] public void StepInput_ParsesResetCommand() { var json = """{"cmd":"reset","seed":12345}"""; var input = JsonSerializer.Deserialize(json, ProtocolJsonContext.Default.StepInput); Assert.NotNull(input); Assert.Equal("reset", input!.Cmd); Assert.Equal(12345, input.Seed); } [Fact] public void StepInput_ParsesResetCommandWithoutSeed() { var json = """{"cmd":"reset"}"""; var input = JsonSerializer.Deserialize(json, ProtocolJsonContext.Default.StepInput); Assert.NotNull(input); Assert.Equal("reset", input!.Cmd); Assert.Null(input.Seed); } [Fact] public void StepOutput_SerializesAllFields() { var output = new StepOutput { Obs = new[] { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f }, State = new ShipStateDto { X = 0.5f, Y = 0.6f, Angle = 0.1f, Engine = 2 }, Reward = -0.42f, Done = false, Step = 137, }; var json = JsonSerializer.Serialize(output, ProtocolJsonContext.Default.StepOutput); Assert.Contains("\"obs\":", json); Assert.Contains("\"state\":", json); Assert.Contains("\"reward\":", json); Assert.Contains("\"done\":false", json); Assert.Contains("\"step\":137", json); Assert.Contains("\"engine\":2", json); } [Fact] public void InitMessage_SerializesExpectedShape() { var init = new InitMessage { Init = new InitPayload { World = new[] { 1.0f, 1.0f }, Dt = 0.02f, ObsDim = 7, NActions = 4, }, }; var json = JsonSerializer.Serialize(init, ProtocolJsonContext.Default.InitMessage); Assert.Contains("\"world\":[1,1]", json); Assert.Contains("\"dt\":0.02", json); Assert.Contains("\"obs_dim\":7", json); Assert.Contains("\"n_actions\":4", json); } }