130 lines
6.0 KiB
C#
130 lines
6.0 KiB
C#
using Exchanger.Hardware.Abstractions;
|
||
using Exchanger.Hardware.PeripheryController;
|
||
using NUnit.Framework;
|
||
|
||
namespace Exchanger.HardwareTests;
|
||
|
||
[TestFixture]
|
||
[NonParallelizable]
|
||
[Category("HardwareSafe")]
|
||
public sealed class BoardSafeTests
|
||
{
|
||
[Test]
|
||
public void TransportAndHandshake_ReachReadyAndCloseCleanly()
|
||
{
|
||
BoardTestConfiguration configuration = BoardTestConfiguration.RequireSafeTests();
|
||
using var session = new BoardTestSession(configuration);
|
||
|
||
session.ConnectAndAuthorize();
|
||
|
||
using (Assert.EnterMultipleScope())
|
||
{
|
||
Assert.That(session.Port.IsConnected, Is.True);
|
||
Assert.That(session.Controller.AuthenticationState, Is.EqualTo(ControllerAuthenticationState.Ready));
|
||
Assert.That(session.Controller.ConnectionState, Is.EqualTo(MachineConnectionState.Ready));
|
||
Assert.That(session.ConnectionStates, Does.Contain(MachineConnectionState.Authenticating));
|
||
Assert.That(session.ConnectionStates, Does.Contain(MachineConnectionState.Ready));
|
||
}
|
||
|
||
session.DisconnectAndWait();
|
||
Assert.That(session.Port.IsConnected, Is.False);
|
||
}
|
||
|
||
[Test]
|
||
public void DigitalInputs_QueryReturnsDocumentedTypedFrame()
|
||
{
|
||
BoardTestConfiguration configuration = BoardTestConfiguration.RequireSafeTests();
|
||
using var session = new BoardTestSession(configuration);
|
||
session.ConnectAndAuthorize();
|
||
|
||
ObservedBoardMessage response = session.SendAndWaitForMessage(
|
||
PeripheryProtocolCommands.QueryDigitalInputs,
|
||
message => message.Kind == PeripheryMessageKind.DigitalInputs,
|
||
"На команду 91 не получен документированный кадр INPUT<0..67108863>.");
|
||
|
||
Assert.That(response.NumericValue, Is.InRange(0, 67_108_863));
|
||
}
|
||
|
||
[Test]
|
||
public void Hopper1StockInput_UsesConfiguredBinaryPolarity()
|
||
{
|
||
BoardTestConfiguration configuration = BoardTestConfiguration.RequireSafeTests();
|
||
if (configuration.StockSensorInputIndex < 0)
|
||
{
|
||
Assert.Ignore("Проверка IN1 отключена параметром StockInput=-1.");
|
||
}
|
||
|
||
using var session = new BoardTestSession(configuration);
|
||
session.ConnectAndAuthorize();
|
||
|
||
ObservedBoardMessage response = session.SendAndWaitForMessage(
|
||
PeripheryProtocolCommands.QueryDigitalInputs,
|
||
message => message.Kind == PeripheryMessageKind.DigitalInputs,
|
||
"На команду 91 не получен снимок входов для проверки IN1.");
|
||
session.PumpOnce();
|
||
|
||
bool inputHigh = (response.NumericValue & (1 << configuration.StockSensorInputIndex)) != 0;
|
||
MachineStockLevel expected = inputHigh == configuration.StockLowWhenInputHigh
|
||
? MachineStockLevel.Low
|
||
: MachineStockLevel.Enough;
|
||
|
||
Assert.That(session.Controller.StockLevel, Is.EqualTo(expected));
|
||
TestContext.Progress.WriteLine($"IN{configuration.StockSensorInputIndex}: состояние запаса {expected}.");
|
||
}
|
||
|
||
[TestCase(PeripheryProtocolCommands.QueryCoinAcceptorStatus, TestName = "Status_CoinAcceptor_ReturnsFrame")]
|
||
[TestCase(PeripheryProtocolCommands.QueryBillAcceptorStatus, TestName = "Status_BillAcceptor_ReturnsFrame")]
|
||
[TestCase(PeripheryProtocolCommands.QueryCashlessStatus, TestName = "Status_Cashless_ReturnsFrame")]
|
||
[TestCase(PeripheryProtocolCommands.QueryHopper1Credit, TestName = "Status_Hopper1Credit_ReturnsFrame")]
|
||
[TestCase(PeripheryProtocolCommands.QueryControllerStatus, TestName = "Status_Controller_ReturnsFrame")]
|
||
public void StatusQuery_ReturnsNonHandshakeFrame(string command)
|
||
{
|
||
BoardTestConfiguration configuration = BoardTestConfiguration.RequireSafeTests();
|
||
using var session = new BoardTestSession(configuration);
|
||
session.ConnectAndAuthorize();
|
||
|
||
ObservedBoardMessage response = session.SendAndWaitForMessage(
|
||
command,
|
||
message => message.Kind is PeripheryMessageKind.Unknown
|
||
or PeripheryMessageKind.Hopper1Credit
|
||
or PeripheryMessageKind.ControllerError
|
||
or PeripheryMessageKind.TransportError,
|
||
$"Контроллер не вернул кадр на безопасный status-запрос {command}.");
|
||
|
||
using (Assert.EnterMultipleScope())
|
||
{
|
||
Assert.That(response.FrameLength, Is.GreaterThan(0));
|
||
Assert.That(response.Kind, Is.Not.EqualTo(PeripheryMessageKind.ControllerError));
|
||
Assert.That(response.Kind, Is.Not.EqualTo(PeripheryMessageKind.TransportError));
|
||
}
|
||
TestContext.Progress.WriteLine($"Status-запрос {command}: получен кадр категории {response.Kind}, длина скрыта из отчёта протокола.");
|
||
}
|
||
|
||
[Test]
|
||
public void ReconnectCycles_ReauthorizeExactlyOncePerCycle()
|
||
{
|
||
BoardTestConfiguration configuration = BoardTestConfiguration.RequireSafeTests();
|
||
using var session = new BoardTestSession(configuration);
|
||
|
||
for (int cycle = 1; cycle <= configuration.ReconnectCycles; cycle++)
|
||
{
|
||
TestContext.Progress.WriteLine($"Цикл переподключения {cycle}/{configuration.ReconnectCycles}.");
|
||
session.ConnectAndAuthorize();
|
||
session.DisconnectAndWait();
|
||
}
|
||
|
||
using (Assert.EnterMultipleScope())
|
||
{
|
||
Assert.That(
|
||
session.ConnectionStates.Count(state => state == MachineConnectionState.Authenticating),
|
||
Is.EqualTo(configuration.ReconnectCycles));
|
||
Assert.That(
|
||
session.ConnectionStates.Count(state => state == MachineConnectionState.Ready),
|
||
Is.EqualTo(configuration.ReconnectCycles));
|
||
Assert.That(
|
||
session.ConnectionStates.Count(state => state == MachineConnectionState.Disconnected),
|
||
Is.EqualTo(configuration.ReconnectCycles));
|
||
}
|
||
}
|
||
}
|