Skip to content

Commit

Permalink
Merge branch 'UpdateGrpcAPI' into Timeouts
Browse files Browse the repository at this point in the history
  • Loading branch information
Scretch9 committed Dec 15, 2023
2 parents b2d091f + be90049 commit b5a413c
Show file tree
Hide file tree
Showing 44 changed files with 7,915 additions and 2,927 deletions.
364 changes: 364 additions & 0 deletions .editorconfig

Large diffs are not rendered by default.

138 changes: 138 additions & 0 deletions src/FieldElementSubsystems.Test/Connection/Baseline4R1Test.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
using EulynxLive.FieldElementSubsystems.Connections.EulynxBaseline4R2;
using EulynxLive.FieldElementSubsystems.Interfaces;
using EulynxLive.Messages.Baseline4R2;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Moq;
using PointMovePointCommand = EulynxLive.Messages.Baseline4R2.PointMovePointCommand;

public class Baseline4R2Test{

private static readonly IDictionary<string, string?> TestSettings = new Dictionary<string, string?> {
{"PointSettings:LocalId", "99W1" },
{"PointSettings:LocalRastaId", "100" },
{"PointSettings:RemoteId", "INTERLOCKING" },
{"PointSettings:RemoteEndpoint", "http://localhost:50051" },
{"PointSettings:AllPointMachinesCrucial", "false" },
{"PointSettings:SimulateRandomTimeouts", "false" },
};

private readonly IConfiguration _configuration = new ConfigurationBuilder()
.AddInMemoryCollection(TestSettings)
.Build();

[Fact]
public void Test_Connect(){
// Arrange
var mockConnection = new Mock<IConnection>();
var connection = new PointToInterlockingConnection(Mock.Of<ILogger<PointToInterlockingConnection>>(), _configuration, CancellationToken.None);

// Act
connection.Connect(mockConnection.Object);

// Assert
Assert.Equal(connection.CurrentConnection, mockConnection.Object);
}

[Fact]
public async Task Test_Initialization(){
// Arrange
var mockConnection = new Mock<IConnection>();
mockConnection.SetupSequence(x => x.ReceiveAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(new PointPdiVersionCheckCommand("99W1","100", 0x01).ToByteArray())
.ReturnsAsync(new PointInitialisationRequestCommand("99W1","100").ToByteArray());
var args = new List<byte[]>();
mockConnection.Setup(x => x.SendAsync(Capture.In(args)))
.Returns(Task.FromResult(0));

var connection = new PointToInterlockingConnection(Mock.Of<ILogger<PointToInterlockingConnection>>(), _configuration, CancellationToken.None);

// Act
connection.Connect(mockConnection.Object);
await connection.InitializeConnection(new GenericPointState(){PointPosition = GenericPointPosition.Left, DegradedPointPosition = GenericDegradedPointPosition.NotDegraded}, CancellationToken.None);

// Assert
mockConnection.Verify(v => v.ReceiveAsync(It.IsAny<CancellationToken>()), Times.Exactly(2));
mockConnection.Verify(v => v.SendAsync(It.IsAny<byte[]>()), Times.Exactly(4));
Assert.Equal(new PointPdiVersionCheckMessage("99W1________________", "INTERLOCKING________", PointPdiVersionCheckMessageResultPdiVersionCheck.PDIVersionsFromReceiverAndSenderDoMatch, /* TODO */ 0, 0, new byte[] { }).ToByteArray(), args[0]);
Assert.Equal(new PointStartInitialisationMessage("99W1________________", "INTERLOCKING________").ToByteArray(), args[1]);
Assert.Equal(new PointPointPositionMessage("99W1________________", "INTERLOCKING________", PointPointPositionMessageReportedPointPosition.PointIsInALeftHandPositionDefinedEndPosition, PointPointPositionMessageReportedDegradedPointPosition.PointIsNotInADegradedPosition).ToByteArray(), args[2]);
Assert.Equal(new PointInitialisationCompletedMessage("99W1________________", "INTERLOCKING________").ToByteArray(), args[3]);
}

[Fact]
public async Task Test_Send_Position(){
// Arrange
var mockConnection = new Mock<IConnection>();
mockConnection.SetupSequence(x => x.ReceiveAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(new PointPdiVersionCheckCommand("99W1","100", 0x01).ToByteArray())
.ReturnsAsync(new PointInitialisationRequestCommand("99W1","100").ToByteArray());
var args = new List<byte[]>();
mockConnection.Setup(x => x.SendAsync(Capture.In(args)))
.Returns(Task.FromResult(0));

var connection = new PointToInterlockingConnection(Mock.Of<ILogger<PointToInterlockingConnection>>(), _configuration, CancellationToken.None);

// Act
connection.Connect(mockConnection.Object);
await connection.InitializeConnection(new GenericPointState(){PointPosition = GenericPointPosition.Left, DegradedPointPosition = GenericDegradedPointPosition.NotDegraded}, CancellationToken.None);
await connection.SendPointPosition(new GenericPointState(){PointPosition = GenericPointPosition.Right, DegradedPointPosition = GenericDegradedPointPosition.NotDegraded});
await connection.SendPointPosition(new GenericPointState(){PointPosition = GenericPointPosition.Left, DegradedPointPosition = GenericDegradedPointPosition.NotDegraded});
await connection.SendPointPosition(new GenericPointState(){PointPosition = GenericPointPosition.UnintendedPosition, DegradedPointPosition = GenericDegradedPointPosition.NotDegraded});
await connection.SendPointPosition(new GenericPointState(){PointPosition = GenericPointPosition.NoEndPosition, DegradedPointPosition = GenericDegradedPointPosition.NotDegraded});

// Assert
mockConnection.Verify(v => v.SendAsync(It.IsAny<byte[]>()), Times.Exactly(8));
Assert.Equal(new PointPointPositionMessage("99W1________________", "INTERLOCKING________", PointPointPositionMessageReportedPointPosition.PointIsInARightHandPositionDefinedEndPosition, PointPointPositionMessageReportedDegradedPointPosition.PointIsNotInADegradedPosition).ToByteArray(), args[4]);
Assert.Equal(new PointPointPositionMessage("99W1________________", "INTERLOCKING________", PointPointPositionMessageReportedPointPosition.PointIsInALeftHandPositionDefinedEndPosition, PointPointPositionMessageReportedDegradedPointPosition.PointIsNotInADegradedPosition).ToByteArray(), args[5]);
Assert.Equal(new PointPointPositionMessage("99W1________________", "INTERLOCKING________", PointPointPositionMessageReportedPointPosition.PointIsInUnintendedPosition, PointPointPositionMessageReportedDegradedPointPosition.PointIsNotInADegradedPosition).ToByteArray(), args[6]);
Assert.Equal(new PointPointPositionMessage("99W1________________", "INTERLOCKING________", PointPointPositionMessageReportedPointPosition.PointIsInNoEndPosition, PointPointPositionMessageReportedDegradedPointPosition.PointIsNotInADegradedPosition).ToByteArray(), args[7]);
}

[Fact]
public async Task Test_Receive_Position(){
// Arrange
var mockConnection = new Mock<IConnection>();
mockConnection.SetupSequence(x => x.ReceiveAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(new PointPdiVersionCheckCommand("99W1","100", 0x01).ToByteArray())
.ReturnsAsync(new PointInitialisationRequestCommand("99W1","100").ToByteArray())
.ReturnsAsync(new PointMovePointCommand("99W1", "100", PointMovePointCommandCommandedPointPosition.SubsystemElectronicInterlockingRequestsALeftHandPointMoving).ToByteArray())
.ReturnsAsync(new PointMovePointCommand("99W1", "100", PointMovePointCommandCommandedPointPosition.SubsystemElectronicInterlockingRequestsARightHandPointMoving).ToByteArray());

var connection = new PointToInterlockingConnection(Mock.Of<ILogger<PointToInterlockingConnection>>(), _configuration, CancellationToken.None);

// Act
connection.Connect(mockConnection.Object);
await connection.InitializeConnection(new GenericPointState(){PointPosition = GenericPointPosition.Left, DegradedPointPosition = GenericDegradedPointPosition.NotDegraded}, CancellationToken.None);
var position1 = await connection.ReceivePointPosition(CancellationToken.None);
var position2 = await connection.ReceivePointPosition(CancellationToken.None);

// Assert
mockConnection.Verify(v => v.ReceiveAsync(It.IsAny<CancellationToken>()), Times.Exactly(4));
Assert.Equal(GenericPointPosition.Left, position1);
Assert.Equal(GenericPointPosition.Right, position2);
}

[Fact]
public async Task Test_TimeoutMessage(){
// Arrange
var mockConnection = new Mock<IConnection>();
mockConnection.SetupSequence(x => x.ReceiveAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(new PointPdiVersionCheckCommand("99W1","100", 0x01).ToByteArray())
.ReturnsAsync(new PointInitialisationRequestCommand("99W1","100").ToByteArray());
var args = new List<byte[]>();
mockConnection.Setup(x => x.SendAsync(Capture.In(args)))
.Returns(Task.FromResult(0));

var connection = new PointToInterlockingConnection(Mock.Of<ILogger<PointToInterlockingConnection>>(), _configuration, CancellationToken.None);

// Act
connection.Connect(mockConnection.Object);
await connection.InitializeConnection(new GenericPointState(){PointPosition = GenericPointPosition.Left, DegradedPointPosition = GenericDegradedPointPosition.NotDegraded}, CancellationToken.None);
await connection.SendTimeoutMessage();

// Assert
mockConnection.Verify(v => v.SendAsync(It.IsAny<byte[]>()), Times.Exactly(5));
Assert.Equal(new PointMovementFailedMessage("99W1________________", "INTERLOCKING________").ToByteArray(), args[4]);
}
}
28 changes: 22 additions & 6 deletions src/FieldElementSubsystems.Test/Point/PointTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,16 @@ private EulynxLive.Point.Point CreateDefaultPoint(IPointToInterlockingConnection
return new EulynxLive.Point.Point(_logger, config, connection ?? Mock.Of<IPointToInterlockingConnection>(), async () => {});

Check warning on line 22 in src/FieldElementSubsystems.Test/Point/PointTest.cs

View workflow job for this annotation

GitHub Actions / build

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
}

private Mock<IPointToInterlockingConnection> CreateDefaultMockConnection() {
private static Mock<IPointToInterlockingConnection> CreateDefaultMockConnection() {
var mockConnection = new Mock<IPointToInterlockingConnection>();
mockConnection.Setup(x => x.Configuration).Returns(() => new PointConfiguration(
"99W1",
100,
"INTERLOCKING",
"http://localhost:50051",
true,
false
false,
ConnectionProtocol.EulynxBaseline4R1
));
mockConnection.Setup(x => x.TimeoutToken).Returns(() => CancellationToken.None);
mockConnection
Expand Down Expand Up @@ -151,22 +152,37 @@ public async Task Test_Send_Generic_Message()
Message = ByteString.CopyFrom (rawBytes)
};

var point = CreateDefaultPoint(mockConnection.Object);
mockConnection
.SetupSequence(m => m.SendGenericMessage(rawBytes))
.SetupSequence(m => m.ReceivePointPosition(It.IsAny<CancellationToken>()))
.Returns(Task.FromResult<GenericPointPosition?>(null))
.Returns(async () =>
{
await point.SendGenericMessage(genericMessage);
return null;
})
.Returns(() =>
{
cancel.Cancel();
return new TaskCompletionSource<GenericPointPosition?>().Task;
});

var args = new List<byte[]>();

mockConnection
.SetupSequence(m => m.SendGenericMessage(Capture.In(args)))
.Returns(() =>
{
cancel.Cancel();
return new TaskCompletionSource<GenericPointPosition?>().Task;
});

var point = CreateDefaultPoint(mockConnection.Object);

// Act
await point.StartAsync(cancel.Token);
await point.SendGenericMessage(genericMessage);

// Assert
mockConnection.Verify(v => v.SendGenericMessage(rawBytes), Times.Once());
Assert.Equal(rawBytes, args.ToArray()[0]);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace EulynxLive.FieldElementSubsystems.Configuration;

public enum ConnectionProtocol {
EulynxBaseline4R1,
EulynxBaseline4R2
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ public record PointConfiguration(
string RemoteId,
string RemoteEndpoint,
bool? AllPointMachinesCrucial = null,
bool? SimulateRandomTimeouts = null
bool? SimulateRandomTimeouts = null,
ConnectionProtocol? ConnectionProtocol = null
);
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

namespace EulynxLive.FieldElementSubsystems.Connections.EulynxBaseline4R1;

public record PointState(GenericPointState State)
public record PointState(GenericPointState State) : SpecificPointState<
PointPointPositionMessageReportedPointPosition,
PointPointPositionMessageReportedDegradedPointPosition
>(State)
{
public PointPointPositionMessageReportedPointPosition PointPosition => MapInterfacePointPositionToConcrete(State.PointPosition);
public PointPointPositionMessageReportedDegradedPointPosition DegradedPointPosition => MapInterfaceDegradedPointPositionToConcrete(State.DegradedPointPosition);

private static PointPointPositionMessageReportedPointPosition MapInterfacePointPositionToConcrete(GenericPointPosition value) => value switch
public override PointPointPositionMessageReportedPointPosition MapInterfacePointPositionToConcrete(GenericPointPosition value) => value switch
{
GenericPointPosition.Left => PointPointPositionMessageReportedPointPosition.PointIsInALeftHandPositionDefinedEndPosition,
GenericPointPosition.Right => PointPointPositionMessageReportedPointPosition.PointIsInARightHandPositionDefinedEndPosition,
Expand All @@ -18,7 +18,7 @@ public record PointState(GenericPointState State)
_ => throw new NotImplementedException(),
};

private static PointPointPositionMessageReportedDegradedPointPosition MapInterfaceDegradedPointPositionToConcrete(GenericDegradedPointPosition value) => value switch
public override PointPointPositionMessageReportedDegradedPointPosition MapInterfaceDegradedPointPositionToConcrete(GenericDegradedPointPosition value) => value switch
{
GenericDegradedPointPosition.DegradedLeft => PointPointPositionMessageReportedDegradedPointPosition.PointIsInADegradedLeftHandPosition,
GenericDegradedPointPosition.DegradedRight => PointPointPositionMessageReportedDegradedPointPosition.PointIsInADegradedRightHandPosition,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using EulynxLive.Messages.Baseline4R1;
using EulynxLive.FieldElementSubsystems.Interfaces;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using EulynxLive.FieldElementSubsystems.Configuration;
using Grpc.Core;
using EulynxLive.Messages.Baseline4R1;


namespace EulynxLive.FieldElementSubsystems.Connections.EulynxBaseline4R1;
Expand All @@ -13,7 +13,6 @@ public class PointToInterlockingConnection : IPointToInterlockingConnection
private readonly ILogger _logger;
private readonly string _localId;
private readonly string _remoteId;

public PointConfiguration Configuration { get; }
public CancellationToken TimeoutToken => _timeout.Token;

Expand Down Expand Up @@ -148,23 +147,4 @@ public async Task SendGenericMessage(byte[] message)
if (_currentConnection == null) throw new InvalidOperationException("Connection is null. Did you call Connect()?");
await SendMessage(message);
}

public async Task SendAbilityToMoveMessage(GenericAbiliyToMove abilityToMove)
{
if (_currentConnection == null) throw new InvalidOperationException("Connection is null. Did you call Connect()?");
if (abilityToMove == GenericAbiliyToMove.Unknown)
{
_logger.LogInformation("Ability to move cannot be unknown.");
return;
}

var abilityToMoveConverted = abilityToMove switch
{
GenericAbiliyToMove.CanMove => PointAbilityToMovePointMessageReportedAbilityToMovePointStatus.PointIsAbleToMove,
GenericAbiliyToMove.CannotMove => PointAbilityToMovePointMessageReportedAbilityToMovePointStatus.PointIsUnableToMove,
_ => throw new NotImplementedException(),
};
var response = new PointAbilityToMovePointMessage(_localId, _remoteId, abilityToMoveConverted);
await SendMessage(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

using EulynxLive.FieldElementSubsystems.Interfaces;
using EulynxLive.Messages.Baseline4R2;

namespace EulynxLive.FieldElementSubsystems.Connections.EulynxBaseline4R2;

public record PointState(GenericPointState State) : SpecificPointState<
PointPointPositionMessageReportedPointPosition,
PointPointPositionMessageReportedDegradedPointPosition
>(State)
{
public override PointPointPositionMessageReportedPointPosition MapInterfacePointPositionToConcrete(GenericPointPosition value) => value switch
{
GenericPointPosition.Left => PointPointPositionMessageReportedPointPosition.PointIsInALeftHandPositionDefinedEndPosition,
GenericPointPosition.Right => PointPointPositionMessageReportedPointPosition.PointIsInARightHandPositionDefinedEndPosition,
GenericPointPosition.UnintendedPosition => PointPointPositionMessageReportedPointPosition.PointIsInUnintendedPosition,
GenericPointPosition.NoEndPosition => PointPointPositionMessageReportedPointPosition.PointIsInNoEndPosition,
_ => throw new NotImplementedException(),
};

public override PointPointPositionMessageReportedDegradedPointPosition MapInterfaceDegradedPointPositionToConcrete(GenericDegradedPointPosition value) => value switch
{
GenericDegradedPointPosition.DegradedLeft => PointPointPositionMessageReportedDegradedPointPosition.PointIsInADegradedLeftHandPosition,
GenericDegradedPointPosition.DegradedRight => PointPointPositionMessageReportedDegradedPointPosition.PointIsInADegradedRightHandPosition,
GenericDegradedPointPosition.NotDegraded => PointPointPositionMessageReportedDegradedPointPosition.PointIsNotInADegradedPosition,
GenericDegradedPointPosition.NotApplicable => PointPointPositionMessageReportedDegradedPointPosition.DegradedPointPositionIsNotApplicable,
_ => throw new NotImplementedException(),
};
}
Loading

0 comments on commit b5a413c

Please sign in to comment.