Moving structure as preparation for docs

This commit is contained in:
2025-08-06 21:05:47 +02:00
parent 885079ae70
commit 799a014b15
117 changed files with 629 additions and 664 deletions

View File

@@ -0,0 +1,775 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Protocols.Modbus.Common.Contracts;
namespace AMWD.Protocols.Modbus.Tests.Common.Contracts
{
[TestClass]
public class ModbusClientBaseTest
{
// Consts
private const byte UNIT_ID = 42;
private const ushort START_ADDRESS = 123;
private const ushort READ_COUNT = 12;
// Mocks
private Mock<IModbusConnection> _connection;
private Mock<IModbusProtocol> _protocol;
// Responses
private List<Coil> _readCoilsResponse;
private List<DiscreteInput> _readDiscreteInputsResponse;
private List<HoldingRegister> _readHoldingRegistersResponse;
private List<InputRegister> _readInputRegistersResponse;
private DeviceIdentificationRaw _firstDeviceIdentificationResponse;
private Queue<DeviceIdentificationRaw> _deviceIdentificationResponseQueue;
private Coil _writeSingleCoilResponse;
private HoldingRegister _writeSingleHoldingRegisterResponse;
private (ushort startAddress, ushort count) _writeMultipleCoilsResponse;
private (ushort startAddress, ushort count) _writeMultipleHoldingRegistersResponse;
[TestInitialize]
public void Initialize()
{
_readCoilsResponse = [];
_readDiscreteInputsResponse = [];
_readHoldingRegistersResponse = [];
_readInputRegistersResponse = [];
for (int i = 0; i < READ_COUNT; i++)
{
_readCoilsResponse.Add(new Coil
{
Address = (ushort)i,
HighByte = (byte)((i % 2 == 0) ? 0xFF : 0x00)
});
_readDiscreteInputsResponse.Add(new DiscreteInput
{
Address = (ushort)i,
HighByte = (byte)((i % 2 == 1) ? 0xFF : 0x00)
});
_readHoldingRegistersResponse.Add(new HoldingRegister
{
Address = (ushort)i,
HighByte = 0x00,
LowByte = (byte)(i + 10)
});
_readInputRegistersResponse.Add(new InputRegister
{
Address = (ushort)i,
HighByte = 0x00,
LowByte = (byte)(i + 15)
});
}
_firstDeviceIdentificationResponse = new DeviceIdentificationRaw
{
AllowsIndividualAccess = true,
MoreRequestsNeeded = false,
NextObjectIdToRequest = 0x00,
};
_firstDeviceIdentificationResponse.Objects.Add(0x00, Encoding.UTF8.GetBytes("AM.WD"));
_firstDeviceIdentificationResponse.Objects.Add(0x01, Encoding.UTF8.GetBytes("AMWD-MB"));
_firstDeviceIdentificationResponse.Objects.Add(0x02, Encoding.UTF8.GetBytes("1.2.3"));
_firstDeviceIdentificationResponse.Objects.Add(0x03, Encoding.UTF8.GetBytes("https://github.com/AM-WD/AMWD.Protocols.Modbus"));
_firstDeviceIdentificationResponse.Objects.Add(0x04, Encoding.UTF8.GetBytes("AM.WD Modbus Library"));
_firstDeviceIdentificationResponse.Objects.Add(0x05, Encoding.UTF8.GetBytes("UnitTests"));
_firstDeviceIdentificationResponse.Objects.Add(0x06, Encoding.UTF8.GetBytes("Modbus Client Base Unit Test"));
_deviceIdentificationResponseQueue = new Queue<DeviceIdentificationRaw>();
_deviceIdentificationResponseQueue.Enqueue(_firstDeviceIdentificationResponse);
_writeSingleCoilResponse = new Coil { Address = START_ADDRESS };
_writeSingleHoldingRegisterResponse = new HoldingRegister { Address = START_ADDRESS, Value = 0x1234 };
_writeMultipleCoilsResponse = (START_ADDRESS, READ_COUNT);
_writeMultipleHoldingRegistersResponse = (START_ADDRESS, READ_COUNT);
}
#region Common/Connection/Assertions
[TestMethod]
public void ShouldPrettyPrint()
{
// Arrange
var client = GetClient();
// Act
string str = client.ToString();
// Assert
Assert.AreEqual("Modbus client using Moq protocol to connect via Mock", str);
}
[TestMethod]
public void ShouldThrowExceptionOnNullConnection()
{
// Arrange
IModbusConnection connection = null;
// Act + Assert
Assert.ThrowsExactly<ArgumentNullException>(() => new ModbusClientBaseWrapper(connection));
}
[TestMethod]
[DataRow(true)]
[DataRow(false)]
public void ShouldAlsoDisposeConnection(bool disposeConnection)
{
// Arrange
var client = GetClient(disposeConnection);
// Act
client.Dispose();
// Assert
if (disposeConnection)
_connection.Verify(c => c.Dispose(), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public void ShouldAllowDisposeMultipleTimes()
{
// Arrange
var client = GetClient();
// Act
client.Dispose();
client.Dispose();
// Assert
_connection.Verify(c => c.Dispose(), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldAssertDisposed()
{
// Arrange
var client = GetClient();
client.Dispose();
// Act + Assert
await Assert.ThrowsExactlyAsync<ObjectDisposedException>(() => client.ReadCoilsAsync(UNIT_ID, START_ADDRESS, READ_COUNT));
}
[TestMethod]
public async Task ShouldAssertProtocolSet()
{
// Arrange
var client = GetClient();
client.Protocol = null;
// Act + Assert
await Assert.ThrowsExactlyAsync<ArgumentNullException>(() => client.ReadCoilsAsync(UNIT_ID, START_ADDRESS, READ_COUNT));
}
#endregion Common/Connection/Assertions
#region Read
[TestMethod]
public async Task ShouldReadCoils()
{
// Arrange
_readCoilsResponse.Add(new Coil());
var client = GetClient();
// Act
var result = await client.ReadCoilsAsync(UNIT_ID, START_ADDRESS, READ_COUNT);
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(READ_COUNT, result.Count);
for (int i = 0; i < READ_COUNT; i++)
{
Assert.AreEqual(START_ADDRESS + i, result[i].Address);
Assert.AreEqual(i % 2 == 0, result[i].Value);
}
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeReadCoils(UNIT_ID, START_ADDRESS, READ_COUNT), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeReadCoils(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldReadDiscreteInputs()
{
// Arrange
_readDiscreteInputsResponse.Add(new DiscreteInput());
var client = GetClient();
// Act
var result = await client.ReadDiscreteInputsAsync(UNIT_ID, START_ADDRESS, READ_COUNT);
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(READ_COUNT, result.Count);
for (int i = 0; i < READ_COUNT; i++)
{
Assert.AreEqual(START_ADDRESS + i, result[i].Address);
Assert.AreEqual(i % 2 == 1, result[i].Value);
}
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeReadDiscreteInputs(UNIT_ID, START_ADDRESS, READ_COUNT), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeReadDiscreteInputs(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldReadHoldingRegisters()
{
// Arrange
var client = GetClient();
// Act
var result = await client.ReadHoldingRegistersAsync(UNIT_ID, START_ADDRESS, READ_COUNT);
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(READ_COUNT, result.Count);
for (int i = 0; i < READ_COUNT; i++)
{
Assert.AreEqual(START_ADDRESS + i, result[i].Address);
Assert.AreEqual(i + 10, result[i].Value);
}
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeReadHoldingRegisters(UNIT_ID, START_ADDRESS, READ_COUNT), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeReadHoldingRegisters(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldReadInputRegisters()
{
// Arrange
var client = GetClient();
// Act
var result = await client.ReadInputRegistersAsync(UNIT_ID, START_ADDRESS, READ_COUNT);
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(READ_COUNT, result.Count);
for (int i = 0; i < READ_COUNT; i++)
{
Assert.AreEqual(START_ADDRESS + i, result[i].Address);
Assert.AreEqual(i + 15, result[i].Value);
}
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeReadInputRegisters(UNIT_ID, START_ADDRESS, READ_COUNT), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeReadInputRegisters(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldReadDeviceIdentification()
{
// Arrange
var client = GetClient();
// Act
var result = await client.ReadDeviceIdentificationAsync(UNIT_ID, ModbusDeviceIdentificationCategory.Basic, ModbusDeviceIdentificationObject.VendorName);
// Assert
Assert.IsNotNull(result);
Assert.IsTrue(result.IsIndividualAccessAllowed);
Assert.AreEqual("AM.WD", result.VendorName);
Assert.AreEqual("AMWD-MB", result.ProductCode);
Assert.AreEqual("1.2.3", result.MajorMinorRevision);
Assert.AreEqual("https://github.com/AM-WD/AMWD.Protocols.Modbus", result.VendorUrl);
Assert.AreEqual("AM.WD Modbus Library", result.ProductName);
Assert.AreEqual("UnitTests", result.ModelName);
Assert.AreEqual("Modbus Client Base Unit Test", result.UserApplicationName);
Assert.AreEqual(0, result.ExtendedObjects.Count);
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeReadDeviceIdentification(UNIT_ID, ModbusDeviceIdentificationCategory.Basic, ModbusDeviceIdentificationObject.VendorName), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeReadDeviceIdentification(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldReadDeviceIdentificationMultipleCycles()
{
// Arrange
_firstDeviceIdentificationResponse.MoreRequestsNeeded = true;
_firstDeviceIdentificationResponse.NextObjectIdToRequest = 0x07;
_deviceIdentificationResponseQueue.Enqueue(new DeviceIdentificationRaw
{
AllowsIndividualAccess = true,
MoreRequestsNeeded = false,
NextObjectIdToRequest = 0x00,
Objects = new Dictionary<byte, byte[]>
{
{ 0x07, new byte[] { 0x01, 0x02, 0x03 } },
}
});
var client = GetClient();
// Act
var result = await client.ReadDeviceIdentificationAsync(UNIT_ID, ModbusDeviceIdentificationCategory.Extended, ModbusDeviceIdentificationObject.VendorName);
// Assert
Assert.IsNotNull(result);
Assert.IsTrue(result.IsIndividualAccessAllowed);
Assert.AreEqual("AM.WD", result.VendorName);
Assert.AreEqual("AMWD-MB", result.ProductCode);
Assert.AreEqual("1.2.3", result.MajorMinorRevision);
Assert.AreEqual("https://github.com/AM-WD/AMWD.Protocols.Modbus", result.VendorUrl);
Assert.AreEqual("AM.WD Modbus Library", result.ProductName);
Assert.AreEqual("UnitTests", result.ModelName);
Assert.AreEqual("Modbus Client Base Unit Test", result.UserApplicationName);
Assert.AreEqual(1, result.ExtendedObjects.Count);
Assert.AreEqual(0x07, result.ExtendedObjects.First().Key);
CollectionAssert.AreEqual(new byte[] { 0x01, 0x02, 0x03 }, result.ExtendedObjects.First().Value);
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Exactly(2));
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeReadDeviceIdentification(UNIT_ID, ModbusDeviceIdentificationCategory.Extended, ModbusDeviceIdentificationObject.VendorName), Times.Once);
_protocol.Verify(p => p.SerializeReadDeviceIdentification(UNIT_ID, ModbusDeviceIdentificationCategory.Extended, (ModbusDeviceIdentificationObject)0x07), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Exactly(2));
_protocol.Verify(p => p.DeserializeReadDeviceIdentification(It.IsAny<IReadOnlyList<byte>>()), Times.Exactly(2));
_protocol.VerifyNoOtherCalls();
}
#endregion Read
#region Write
[TestMethod]
public async Task ShouldWriteSingleCoil()
{
// Arrange
var coil = new Coil
{
Address = START_ADDRESS,
Value = false
};
var client = GetClient();
// Act
bool result = await client.WriteSingleCoilAsync(UNIT_ID, coil);
// Assert
Assert.IsTrue(result);
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeWriteSingleCoil(UNIT_ID, coil), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeWriteSingleCoil(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldFailWriteSingleCoilOnAddress()
{
// Arrange
var coil = new Coil
{
Address = START_ADDRESS + 1,
Value = false
};
var client = GetClient();
// Act
bool result = await client.WriteSingleCoilAsync(UNIT_ID, coil);
// Assert
Assert.IsFalse(result);
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeWriteSingleCoil(UNIT_ID, coil), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeWriteSingleCoil(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldFailWriteSingleCoilOnValue()
{
// Arrange
var coil = new Coil
{
Address = START_ADDRESS,
Value = true
};
var client = GetClient();
// Act
bool result = await client.WriteSingleCoilAsync(UNIT_ID, coil);
// Assert
Assert.IsFalse(result);
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeWriteSingleCoil(UNIT_ID, coil), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeWriteSingleCoil(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldWriteSingleHoldingRegister()
{
// Arrange
var register = new HoldingRegister
{
Address = START_ADDRESS,
Value = 0x1234
};
var client = GetClient();
// Act
bool result = await client.WriteSingleHoldingRegisterAsync(UNIT_ID, register);
// Assert
Assert.IsTrue(result);
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeWriteSingleHoldingRegister(UNIT_ID, register), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeWriteSingleHoldingRegister(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldFailWriteSingleHoldingRegisterOnAddress()
{
// Arrange
var register = new HoldingRegister
{
Address = START_ADDRESS + 1,
Value = 0x1234
};
var client = GetClient();
// Act
bool result = await client.WriteSingleHoldingRegisterAsync(UNIT_ID, register);
// Assert
Assert.IsFalse(result);
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeWriteSingleHoldingRegister(UNIT_ID, register), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeWriteSingleHoldingRegister(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldFailWriteSingleHoldingRegisterOnValue()
{
// Arrange
var register = new HoldingRegister
{
Address = START_ADDRESS,
Value = 0x1233
};
var client = GetClient();
// Act
bool result = await client.WriteSingleHoldingRegisterAsync(UNIT_ID, register);
// Assert
Assert.IsFalse(result);
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeWriteSingleHoldingRegister(UNIT_ID, register), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeWriteSingleHoldingRegister(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldWriteMultipleCoils()
{
// Arrange
var coils = new List<Coil>();
for (int i = 0; i < READ_COUNT; i++)
{
coils.Add(new Coil
{
Address = (ushort)(START_ADDRESS + i),
Value = i % 2 == 0
});
}
var client = GetClient();
// Act
bool result = await client.WriteMultipleCoilsAsync(UNIT_ID, coils);
// Assert
Assert.IsTrue(result);
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeWriteMultipleCoils(UNIT_ID, coils), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeWriteMultipleCoils(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldFailWriteMultipleCoilsOnAddress()
{
// Arrange
_writeMultipleCoilsResponse.startAddress = START_ADDRESS + 1;
var coils = new List<Coil>();
for (int i = 0; i < READ_COUNT; i++)
{
coils.Add(new Coil
{
Address = (ushort)(START_ADDRESS + i),
Value = i % 2 == 0
});
}
var client = GetClient();
// Act
bool result = await client.WriteMultipleCoilsAsync(UNIT_ID, coils);
// Assert
Assert.IsFalse(result);
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeWriteMultipleCoils(UNIT_ID, coils), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeWriteMultipleCoils(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldFailWriteMultipleCoilsOnCount()
{
// Arrange
_writeMultipleCoilsResponse.count = READ_COUNT + 1;
var coils = new List<Coil>();
for (int i = 0; i < READ_COUNT; i++)
{
coils.Add(new Coil
{
Address = (ushort)(START_ADDRESS + i),
Value = i % 2 == 0
});
}
var client = GetClient();
// Act
bool result = await client.WriteMultipleCoilsAsync(UNIT_ID, coils);
// Assert
Assert.IsFalse(result);
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeWriteMultipleCoils(UNIT_ID, coils), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeWriteMultipleCoils(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldWriteMultipleRegisters()
{
// Arrange
var registers = new List<HoldingRegister>();
for (int i = 0; i < READ_COUNT; i++)
{
registers.Add(new HoldingRegister
{
Address = (ushort)(START_ADDRESS + i),
Value = (ushort)i
});
}
var client = GetClient();
// Act
bool result = await client.WriteMultipleHoldingRegistersAsync(UNIT_ID, registers);
// Assert
Assert.IsTrue(result);
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeWriteMultipleHoldingRegisters(UNIT_ID, registers), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeWriteMultipleHoldingRegisters(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldFailWriteMultiplRegistersOnAddress()
{
// Arrange
_writeMultipleHoldingRegistersResponse.startAddress = START_ADDRESS + 1;
var registers = new List<HoldingRegister>();
for (int i = 0; i < READ_COUNT; i++)
{
registers.Add(new HoldingRegister
{
Address = (ushort)(START_ADDRESS + i),
Value = (ushort)i
});
}
var client = GetClient();
// Act
bool result = await client.WriteMultipleHoldingRegistersAsync(UNIT_ID, registers);
// Assert
Assert.IsFalse(result);
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeWriteMultipleHoldingRegisters(UNIT_ID, registers), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeWriteMultipleHoldingRegisters(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
[TestMethod]
public async Task ShouldFailWriteMultipleRegistersOnCount()
{
// Arrange
_writeMultipleHoldingRegistersResponse.count = READ_COUNT + 1;
var registers = new List<HoldingRegister>();
for (int i = 0; i < READ_COUNT; i++)
{
registers.Add(new HoldingRegister
{
Address = (ushort)(START_ADDRESS + i),
Value = (ushort)i
});
}
var client = GetClient();
// Act
bool result = await client.WriteMultipleHoldingRegistersAsync(UNIT_ID, registers);
// Assert
Assert.IsFalse(result);
_connection.Verify(c => c.InvokeAsync(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<Func<IReadOnlyList<byte>, bool>>(), It.IsAny<CancellationToken>()), Times.Once);
_connection.VerifyNoOtherCalls();
_protocol.Verify(p => p.SerializeWriteMultipleHoldingRegisters(UNIT_ID, registers), Times.Once);
_protocol.Verify(p => p.ValidateResponse(It.IsAny<IReadOnlyList<byte>>(), It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.Verify(p => p.DeserializeWriteMultipleHoldingRegisters(It.IsAny<IReadOnlyList<byte>>()), Times.Once);
_protocol.VerifyNoOtherCalls();
}
#endregion Write
private ModbusClientBase GetClient(bool disposeConnection = true)
{
_connection = new Mock<IModbusConnection>();
_connection
.SetupGet(c => c.Name)
.Returns("Mock");
_protocol = new Mock<IModbusProtocol>();
_protocol
.SetupGet(p => p.Name)
.Returns("Moq");
_protocol
.Setup(p => p.DeserializeReadCoils(It.IsAny<IReadOnlyList<byte>>()))
.Returns(() => _readCoilsResponse);
_protocol
.Setup(p => p.DeserializeReadDiscreteInputs(It.IsAny<IReadOnlyList<byte>>()))
.Returns(() => _readDiscreteInputsResponse);
_protocol
.Setup(p => p.DeserializeReadHoldingRegisters(It.IsAny<IReadOnlyList<byte>>()))
.Returns(() => _readHoldingRegistersResponse);
_protocol
.Setup(p => p.DeserializeReadInputRegisters(It.IsAny<IReadOnlyList<byte>>()))
.Returns(() => _readInputRegistersResponse);
_protocol
.Setup(p => p.DeserializeReadDeviceIdentification(It.IsAny<IReadOnlyList<byte>>()))
.Returns(() => _deviceIdentificationResponseQueue.Dequeue());
_protocol
.Setup(p => p.DeserializeWriteSingleCoil(It.IsAny<IReadOnlyList<byte>>()))
.Returns(() => _writeSingleCoilResponse);
_protocol
.Setup(p => p.DeserializeWriteSingleHoldingRegister(It.IsAny<IReadOnlyList<byte>>()))
.Returns(() => _writeSingleHoldingRegisterResponse);
_protocol
.Setup(p => p.DeserializeWriteMultipleCoils(It.IsAny<IReadOnlyList<byte>>()))
.Returns(() => _writeMultipleCoilsResponse);
_protocol
.Setup(p => p.DeserializeWriteMultipleHoldingRegisters(It.IsAny<IReadOnlyList<byte>>()))
.Returns(() => _writeMultipleHoldingRegistersResponse);
return new ModbusClientBaseWrapper(_connection.Object, disposeConnection)
{
Protocol = _protocol.Object,
};
}
internal class ModbusClientBaseWrapper : ModbusClientBase
{
public ModbusClientBaseWrapper(IModbusConnection connection)
: base(connection)
{ }
public ModbusClientBaseWrapper(IModbusConnection connection, bool disposeConnection)
: base(connection, disposeConnection)
{ }
public override IModbusProtocol Protocol { get; set; }
}
}
}

View File

@@ -0,0 +1,304 @@
namespace AMWD.Protocols.Modbus.Tests.Common.Extensions
{
[TestClass]
public class ModbusDecimalExtensionsTest
{
#region Modbus to value
[TestMethod]
public void ShouldGetSingle()
{
// Arrange
var registers = new HoldingRegister[]
{
new(),
new() { Address = 100, HighByte = 0x41, LowByte = 0x45 },
new() { Address = 101, HighByte = 0x70, LowByte = 0xA4 }
};
// Act
float f = registers.GetSingle(1);
// Assert
Assert.AreEqual(12.34f, f);
}
[TestMethod]
public void ShouldGetSingleReversedRegisters()
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 101, HighByte = 0x41, LowByte = 0x45 },
new() { Address = 100, HighByte = 0x70, LowByte = 0xA4 }
};
// Act
float f = registers.GetSingle(0, reverseRegisterOrder: true);
// Assert
Assert.AreEqual(12.34f, f);
}
[TestMethod]
public void ShouldThrowNullOnGetSingle()
{
// Arrange
HoldingRegister[] registers = null;
// Act + Assert
Assert.ThrowsExactly<ArgumentNullException>(() => registers.GetSingle(0));
}
[TestMethod]
public void ShouldThrowArgumentOnGetSingleForLength()
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 101, HighByte = 0x01, LowByte = 0x02 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => registers.GetSingle(0));
}
[TestMethod]
[DataRow(1)]
[DataRow(-1)]
public void ShouldThrowArgumentOutOfRangeOnGetSingle(int startIndex)
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 101, HighByte = 0x01, LowByte = 0x02 },
new() { Address = 100, HighByte = 0x03, LowByte = 0x04 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentOutOfRangeException>(() => registers.GetSingle(startIndex));
}
[TestMethod]
public void ShouldThrowArgumentOnGetSingleForType()
{
// Arrange
var registers = new ModbusObject[]
{
new HoldingRegister { Address = 100, HighByte = 0x01, LowByte = 0x02 },
new InputRegister { Address = 101, HighByte = 0x03, LowByte = 0x04 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => registers.GetSingle(0));
}
[TestMethod]
public void ShouldGetDouble()
{
// Arrange
var registers = new HoldingRegister[]
{
new(),
new() { Address = 100, HighByte = 0x40, LowByte = 0x28 },
new() { Address = 101, HighByte = 0xAE, LowByte = 0x14 },
new() { Address = 102, HighByte = 0x7A, LowByte = 0xE1 },
new() { Address = 103, HighByte = 0x47, LowByte = 0xAE }
};
// Act
double d = registers.GetDouble(1);
// Assert
Assert.AreEqual(12.34, d);
}
[TestMethod]
public void ShouldGetDoubleReversedRegisters()
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 103, HighByte = 0x40, LowByte = 0x28 },
new() { Address = 102, HighByte = 0xAE, LowByte = 0x14 },
new() { Address = 101, HighByte = 0x7A, LowByte = 0xE1 },
new() { Address = 100, HighByte = 0x47, LowByte = 0xAE }
};
// Act
double d = registers.GetDouble(0, reverseRegisterOrder: true);
// Assert
Assert.AreEqual(12.34, d);
}
[TestMethod]
public void ShouldThrowNullOnGetDouble()
{
// Arrange
HoldingRegister[] registers = null;
// Act + Assert
Assert.ThrowsExactly<ArgumentNullException>(() => registers.GetDouble(0));
}
[TestMethod]
public void ShouldThrowArgumentOnGetDoubleForLength()
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 100, HighByte = 0x40, LowByte = 0x28 },
new() { Address = 101, HighByte = 0xAE, LowByte = 0x14 },
new() { Address = 102, HighByte = 0x7A, LowByte = 0xE1 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => registers.GetDouble(0));
}
[TestMethod]
[DataRow(1)]
[DataRow(-1)]
public void ShouldThrowArgumentOutOfRangeOnGetDouble(int startIndex)
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 100, HighByte = 0x40, LowByte = 0x28 },
new() { Address = 101, HighByte = 0xAE, LowByte = 0x14 },
new() { Address = 102, HighByte = 0x7A, LowByte = 0xE1 },
new() { Address = 103, HighByte = 0x47, LowByte = 0xAE }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentOutOfRangeException>(() => registers.GetDouble(startIndex));
}
[TestMethod]
public void ShouldThrowArgumentOnGetDoubleForType()
{
// Arrange
var registers = new ModbusObject[]
{
new HoldingRegister { Address = 100, HighByte = 0x40, LowByte = 0x28 },
new InputRegister { Address = 101, HighByte = 0xAE, LowByte = 0x14 },
new HoldingRegister { Address = 102, HighByte = 0x7A, LowByte = 0xE1 },
new InputRegister { Address = 103, HighByte = 0x47, LowByte = 0xAE }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => registers.GetDouble(0));
}
#endregion Modbus to value
#region Value to Modbus
[TestMethod]
public void ShouldConvertSingle()
{
// Arrange
float f = 12.34f;
// Act
var registers = f.ToRegister(5).ToList();
// Assert
Assert.IsNotNull(registers);
Assert.AreEqual(2, registers.Count);
Assert.AreEqual(5, registers[0].Address);
Assert.AreEqual(0x41, registers[0].HighByte);
Assert.AreEqual(0x45, registers[0].LowByte);
Assert.AreEqual(6, registers[1].Address);
Assert.AreEqual(0x70, registers[1].HighByte);
Assert.AreEqual(0xA4, registers[1].LowByte);
}
[TestMethod]
public void ShouldConvertSingleReversed()
{
// Arrange
float f = 12.34f;
// Act
var registers = f.ToRegister(5, reverseRegisterOrder: true).ToList();
// Assert
Assert.IsNotNull(registers);
Assert.AreEqual(2, registers.Count);
Assert.AreEqual(6, registers[0].Address);
Assert.AreEqual(0x41, registers[0].HighByte);
Assert.AreEqual(0x45, registers[0].LowByte);
Assert.AreEqual(5, registers[1].Address);
Assert.AreEqual(0x70, registers[1].HighByte);
Assert.AreEqual(0xA4, registers[1].LowByte);
}
[TestMethod]
public void ShouldConvertDouble()
{
// Arrange
double d = 12.34;
// Act
var registers = d.ToRegister(5).ToList();
// Assert
Assert.IsNotNull(registers);
Assert.AreEqual(4, registers.Count);
Assert.AreEqual(5, registers[0].Address);
Assert.AreEqual(0x40, registers[0].HighByte);
Assert.AreEqual(0x28, registers[0].LowByte);
Assert.AreEqual(6, registers[1].Address);
Assert.AreEqual(0xAE, registers[1].HighByte);
Assert.AreEqual(0x14, registers[1].LowByte);
Assert.AreEqual(7, registers[2].Address);
Assert.AreEqual(0x7A, registers[2].HighByte);
Assert.AreEqual(0xE1, registers[2].LowByte);
Assert.AreEqual(8, registers[3].Address);
Assert.AreEqual(0x47, registers[3].HighByte);
Assert.AreEqual(0xAE, registers[3].LowByte);
}
[TestMethod]
public void ShouldConvertDoubleReversed()
{
// Arrange
double d = 12.34;
// Act
var registers = d.ToRegister(5, reverseRegisterOrder: true).ToList();
// Assert
Assert.IsNotNull(registers);
Assert.AreEqual(4, registers.Count);
Assert.AreEqual(8, registers[0].Address);
Assert.AreEqual(0x40, registers[0].HighByte);
Assert.AreEqual(0x28, registers[0].LowByte);
Assert.AreEqual(7, registers[1].Address);
Assert.AreEqual(0xAE, registers[1].HighByte);
Assert.AreEqual(0x14, registers[1].LowByte);
Assert.AreEqual(6, registers[2].Address);
Assert.AreEqual(0x7A, registers[2].HighByte);
Assert.AreEqual(0xE1, registers[2].LowByte);
Assert.AreEqual(5, registers[3].Address);
Assert.AreEqual(0x47, registers[3].HighByte);
Assert.AreEqual(0xAE, registers[3].LowByte);
}
#endregion Value to Modbus
}
}

View File

@@ -0,0 +1,271 @@
using System.Text;
namespace AMWD.Protocols.Modbus.Tests.Common.Extensions
{
[TestClass]
public class ModbusExtensionsTest
{
#region Modbus to value
[TestMethod]
public void ShouldConvertToBoolean()
{
// Arrange
var coil = new Coil { HighByte = 0x00 };
var discreteInput = new DiscreteInput { HighByte = 0xFF };
var holdingRegister = new HoldingRegister { HighByte = 0x01 };
var inputRegister = new InputRegister { LowByte = 0x10 };
// Act
bool coilResult = coil.GetBoolean();
bool discreteInputResult = discreteInput.GetBoolean();
bool holdingRegisterResult = holdingRegister.GetBoolean();
bool inputRegisterResult = inputRegister.GetBoolean();
// Assert
Assert.IsFalse(coilResult);
Assert.IsTrue(discreteInputResult);
Assert.IsTrue(holdingRegisterResult);
Assert.IsTrue(inputRegisterResult);
}
[TestMethod]
public void ShouldThrowNullOnGetBoolean()
{
// Arrange
Coil coil = null;
// Act + Assert
Assert.ThrowsExactly<ArgumentNullException>(() => coil.GetBoolean());
}
[TestMethod]
public void ShouldConvertToString()
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 1, HighByte = 65, LowByte = 66 },
new() { Address = 2, HighByte = 67, LowByte = 0 },
new() { Address = 3, HighByte = 95, LowByte = 96 }
};
// Act
string text = registers.GetString(3);
// Assert
Assert.AreEqual("ABC", text);
}
[TestMethod]
public void ShouldConvertToStringReversedBytes()
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 1, HighByte = 66, LowByte = 65 },
new() { Address = 2, HighByte = 0, LowByte = 67 }
};
// Act
string text = registers.GetString(2, reverseByteOrderPerRegister: true);
// Assert
Assert.AreEqual("ABC", text);
}
[TestMethod]
public void ShouldConvertToStringReversedRegisters()
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 2, HighByte = 65, LowByte = 66 },
new() { Address = 1, HighByte = 67, LowByte = 0 },
};
// Act
string text = registers.GetString(2, reverseRegisterOrder: true);
// Assert
Assert.AreEqual("ABC", text);
}
[TestMethod]
public void ShouldThrowNullOnString()
{
// Arrange
HoldingRegister[] list = null;
// Act + Assert
Assert.ThrowsExactly<ArgumentNullException>(() => list.GetString(2));
}
[TestMethod]
public void ShouldThrowArgumentOnStringForEmptyList()
{
// Arrange
var registers = Array.Empty<HoldingRegister>();
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => registers.GetString(2));
}
[TestMethod]
[DataRow(1)]
[DataRow(-1)]
public void ShouldThrowArgumentOutOfRangeOnString(int startIndex)
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 1, HighByte = 65, LowByte = 66 },
new() { Address = 2, HighByte = 67, LowByte = 0 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentOutOfRangeException>(() => registers.GetString(2, startIndex));
}
[TestMethod]
public void ShouldThrowArgumentOnStringForMixedTypes()
{
// Arrange
var registers = new ModbusObject[]
{
new HoldingRegister { Address = 1, HighByte = 65, LowByte = 66 },
new InputRegister { Address = 2, HighByte = 67, LowByte = 0 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => registers.GetString(2));
}
#endregion Modbus to value
#region Value to Modbus
[TestMethod]
public void ShouldGetBooleanCoil()
{
// Arrange
bool value = false;
// Act
var coil = value.ToCoil(123);
// Assert
Assert.IsNotNull(coil);
Assert.AreEqual(123, coil.Address);
Assert.IsFalse(coil.Value);
}
[TestMethod]
public void ShouldGetBooleanRegisterTrue()
{
// Arrange
bool value = true;
// Act
var register = value.ToRegister(321);
// Assert
Assert.IsNotNull(register);
Assert.AreEqual(321, register.Address);
Assert.IsTrue(register.Value > 0);
}
[TestMethod]
public void ShouldGetBooleanRegisterFalse()
{
// Arrange
bool value = false;
// Act
var register = value.ToRegister(321);
// Assert
Assert.IsNotNull(register);
Assert.AreEqual(321, register.Address);
Assert.IsTrue(register.Value == 0);
}
[TestMethod]
public void ShouldGetString()
{
// Arrange
string str = "abc";
// Act
var registers = str.ToRegisters(100).ToList();
// Assert
Assert.IsNotNull(registers);
Assert.AreEqual(2, registers.Count);
Assert.AreEqual(100, registers[0].Address);
Assert.AreEqual(97, registers[0].HighByte);
Assert.AreEqual(98, registers[0].LowByte);
Assert.AreEqual(101, registers[1].Address);
Assert.AreEqual(99, registers[1].HighByte);
Assert.AreEqual(0, registers[1].LowByte);
}
[TestMethod]
public void ShouldGetStringReversedRegisters()
{
// Arrange
string str = "abc";
// Act
var registers = str.ToRegisters(100, reverseRegisterOrder: true).ToList();
// Assert
Assert.IsNotNull(registers);
Assert.AreEqual(2, registers.Count);
Assert.AreEqual(101, registers[0].Address);
Assert.AreEqual(97, registers[0].HighByte);
Assert.AreEqual(98, registers[0].LowByte);
Assert.AreEqual(100, registers[1].Address);
Assert.AreEqual(99, registers[1].HighByte);
Assert.AreEqual(0, registers[1].LowByte);
}
[TestMethod]
public void ShouldGetStringReversedBytes()
{
// Arrange
string str = "abc";
// Act
var registers = str.ToRegisters(100, reverseByteOrderPerRegister: true).ToList();
// Assert
Assert.IsNotNull(registers);
Assert.AreEqual(2, registers.Count);
Assert.AreEqual(100, registers[0].Address);
Assert.AreEqual(97, registers[0].LowByte);
Assert.AreEqual(98, registers[0].HighByte);
Assert.AreEqual(101, registers[1].Address);
Assert.AreEqual(99, registers[1].LowByte);
Assert.AreEqual(0, registers[1].HighByte);
}
[TestMethod]
public void ShouldThrowNullOnGetString()
{
// Arrange
string str = null;
// Act + Assert
Assert.ThrowsExactly<ArgumentNullException>(() => str.ToRegisters(100).ToArray());
}
#endregion Value to Modbus
}
}

View File

@@ -0,0 +1,428 @@
namespace AMWD.Protocols.Modbus.Tests.Common.Extensions
{
[TestClass]
public class ModbusSignedExtensionsTest
{
#region Modbus to value
[TestMethod]
public void ShouldGetSByteOnHoldingRegister()
{
// Arrange
var register = new HoldingRegister { Address = 1, HighByte = 0x02, LowByte = 0xFE };
// Act
sbyte sb = register.GetSByte();
// Assert
Assert.AreEqual(-2, sb);
}
[TestMethod]
public void ShouldGetSByteOnInputRegister()
{
// Arrange
var register = new InputRegister { Address = 1, HighByte = 0x02, LowByte = 0xFE };
// Act
sbyte sb = register.GetSByte();
// Assert
Assert.AreEqual(-2, sb);
}
[TestMethod]
public void ShouldThrowNullForGetSByte()
{
// Arrange
HoldingRegister register = null;
// Act + Assert
Assert.ThrowsExactly<ArgumentNullException>(() => register.GetSByte());
}
[TestMethod]
public void ShouldThrowArgumentForGetSByte()
{
// Arrange
var obj = new Coil();
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => obj.GetSByte());
}
[TestMethod]
public void ShouldGetInt16OnHoldingRegister()
{
// Arrange
var register = new HoldingRegister { Address = 1, HighByte = 0x02, LowByte = 0x10 };
// Act
short s = register.GetInt16();
// Assert
Assert.AreEqual(528, s);
}
[TestMethod]
public void ShouldGetInt16OnInputRegister()
{
// Arrange
var register = new InputRegister { Address = 1, HighByte = 0x02, LowByte = 0x10 };
// Act
short s = register.GetInt16();
// Assert
Assert.AreEqual(528, s);
}
[TestMethod]
public void ShouldThrowNullForGetInt16()
{
// Arrange
HoldingRegister register = null;
// Act + Assert
Assert.ThrowsExactly<ArgumentNullException>(() => register.GetInt16());
}
[TestMethod]
public void ShouldThrowArgumentForGetInt16()
{
// Arrange
var obj = new Coil();
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => obj.GetInt16());
}
[TestMethod]
public void ShouldGetInt32()
{
// Arrange
var registers = new HoldingRegister[]
{
new HoldingRegister(),
new HoldingRegister { Address = 100, HighByte = 0x01, LowByte = 0x02 },
new HoldingRegister { Address = 101, HighByte = 0x03, LowByte = 0x04 }
};
// Act
int i = registers.GetInt32(1);
// Assert
Assert.AreEqual(16909060, i);
}
[TestMethod]
public void ShouldGetInt32ReversedRegisters()
{
// Arrange
var registers = new HoldingRegister[]
{
new HoldingRegister { Address = 101, HighByte = 0x01, LowByte = 0x02 },
new HoldingRegister { Address = 100, HighByte = 0x03, LowByte = 0x04 }
};
// Act
int i = registers.GetInt32(0, reverseRegisterOrder: true);
// Assert
Assert.AreEqual(16909060, i);
}
[TestMethod]
public void ShouldThrowNullOnGetInt32()
{
// Arrange
HoldingRegister[] registers = null;
// Act + Assert
Assert.ThrowsExactly<ArgumentNullException>(() => registers.GetInt32(0));
}
[TestMethod]
public void ShouldThrowArgumentOnGetInt32ForLength()
{
// Arrange
var registers = new HoldingRegister[]
{
new HoldingRegister { Address = 101, HighByte = 0x01, LowByte = 0x02 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => registers.GetInt32(0));
}
[TestMethod]
[DataRow(1)]
[DataRow(-1)]
public void ShouldThrowArgumentOutOfRangeOnGetInt32(int startIndex)
{
// Arrange
var registers = new HoldingRegister[]
{
new HoldingRegister { Address = 101, HighByte = 0x01, LowByte = 0x02 },
new HoldingRegister { Address = 100, HighByte = 0x03, LowByte = 0x04 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentOutOfRangeException>(() => registers.GetInt32(startIndex));
}
[TestMethod]
public void ShouldThrowArgumentOnGetInt32ForType()
{
// Arrange
var registers = new ModbusObject[]
{
new HoldingRegister { Address = 100, HighByte = 0x01, LowByte = 0x02 },
new InputRegister { Address = 101, HighByte = 0x03, LowByte = 0x04 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => registers.GetInt32(0));
}
[TestMethod]
public void ShouldGetInt64()
{
// Arrange
var registers = new HoldingRegister[]
{
new HoldingRegister(),
new HoldingRegister { Address = 100, HighByte = 0x00, LowByte = 0x00 },
new HoldingRegister { Address = 101, HighByte = 0x00, LowByte = 0x00 },
new HoldingRegister { Address = 102, HighByte = 0x01, LowByte = 0x02 },
new HoldingRegister { Address = 103, HighByte = 0x03, LowByte = 0x04 }
};
// Act
long l = registers.GetInt64(1);
// Assert
Assert.AreEqual(16909060L, l);
}
[TestMethod]
public void ShouldGetInt64ReversedRegisters()
{
// Arrange
var registers = new HoldingRegister[]
{
new HoldingRegister { Address = 103, HighByte = 0x00, LowByte = 0x00 },
new HoldingRegister { Address = 102, HighByte = 0x00, LowByte = 0x00 },
new HoldingRegister { Address = 101, HighByte = 0x01, LowByte = 0x02 },
new HoldingRegister { Address = 100, HighByte = 0x03, LowByte = 0x04 }
};
// Act
long l = registers.GetInt64(0, reverseRegisterOrder: true);
// Assert
Assert.AreEqual(16909060L, l);
}
[TestMethod]
public void ShouldThrowNullOnGetInt64()
{
// Arrange
HoldingRegister[] registers = null;
// Act + Assert
Assert.ThrowsExactly<ArgumentNullException>(() => registers.GetInt64(0));
}
[TestMethod]
public void ShouldThrowArgumentOnGetInt64ForLength()
{
// Arrange
var registers = new HoldingRegister[]
{
new HoldingRegister { Address = 101, HighByte = 0x00, LowByte = 0x00 },
new HoldingRegister { Address = 102, HighByte = 0x01, LowByte = 0x02 },
new HoldingRegister { Address = 103, HighByte = 0x03, LowByte = 0x04 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => registers.GetInt64(0));
}
[TestMethod]
[DataRow(1)]
[DataRow(-1)]
public void ShouldThrowArgumentOutOfRangeOnGetInt64(int startIndex)
{
// Arrange
var registers = new HoldingRegister[]
{
new HoldingRegister { Address = 100, HighByte = 0x00, LowByte = 0x00 },
new HoldingRegister { Address = 101, HighByte = 0x00, LowByte = 0x00 },
new HoldingRegister { Address = 102, HighByte = 0x01, LowByte = 0x02 },
new HoldingRegister { Address = 103, HighByte = 0x03, LowByte = 0x04 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentOutOfRangeException>(() => registers.GetInt64(startIndex));
}
[TestMethod]
public void ShouldThrowArgumentOnGetInt64ForType()
{
// Arrange
var registers = new ModbusObject[]
{
new HoldingRegister { Address = 100, HighByte = 0x00, LowByte = 0x00 },
new InputRegister { Address = 101, HighByte = 0x00, LowByte = 0x00 },
new HoldingRegister { Address = 102, HighByte = 0x01, LowByte = 0x02 },
new InputRegister { Address = 103, HighByte = 0x03, LowByte = 0x04 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => registers.GetInt64(0));
}
#endregion Modbus to value
#region Value to Modbus
[TestMethod]
public void ShouldConvertSByte()
{
// Arrange
sbyte sb = -2;
// Act
var register = sb.ToRegister(24);
// Assert
Assert.IsNotNull(register);
Assert.AreEqual(24, register.Address);
Assert.AreEqual(0x00, register.HighByte);
Assert.AreEqual(0xFE, register.LowByte);
}
[TestMethod]
public void ShouldConvertInt16()
{
// Arrange
short s = 1000;
// Act
var register = s.ToRegister(123);
// Assert
Assert.IsNotNull(register);
Assert.AreEqual(123, register.Address);
Assert.AreEqual(0x03, register.HighByte);
Assert.AreEqual(0xE8, register.LowByte);
}
[TestMethod]
public void ShouldConvertInt32()
{
// Arrange
int i = 75000;
// Act
var registers = i.ToRegister(5).ToList();
// Assert
Assert.IsNotNull(registers);
Assert.AreEqual(2, registers.Count);
Assert.AreEqual(5, registers[0].Address);
Assert.AreEqual(0x00, registers[0].HighByte);
Assert.AreEqual(0x01, registers[0].LowByte);
Assert.AreEqual(6, registers[1].Address);
Assert.AreEqual(0x24, registers[1].HighByte);
Assert.AreEqual(0xF8, registers[1].LowByte);
}
[TestMethod]
public void ShouldConvertInt32Reversed()
{
// Arrange
int i = 75000;
// Act
var registers = i.ToRegister(5, reverseRegisterOrder: true).ToList();
// Assert
Assert.IsNotNull(registers);
Assert.AreEqual(2, registers.Count);
Assert.AreEqual(6, registers[0].Address);
Assert.AreEqual(0x00, registers[0].HighByte);
Assert.AreEqual(0x01, registers[0].LowByte);
Assert.AreEqual(5, registers[1].Address);
Assert.AreEqual(0x24, registers[1].HighByte);
Assert.AreEqual(0xF8, registers[1].LowByte);
}
[TestMethod]
public void ShouldConvertInt64()
{
// Arrange
long l = 75000;
// Act
var registers = l.ToRegister(10).ToList();
// Assert
Assert.IsNotNull(registers);
Assert.AreEqual(4, registers.Count);
Assert.AreEqual(10, registers[0].Address);
Assert.AreEqual(0x00, registers[0].HighByte);
Assert.AreEqual(0x00, registers[0].LowByte);
Assert.AreEqual(11, registers[1].Address);
Assert.AreEqual(0x00, registers[1].HighByte);
Assert.AreEqual(0x00, registers[1].LowByte);
Assert.AreEqual(12, registers[2].Address);
Assert.AreEqual(0x00, registers[2].HighByte);
Assert.AreEqual(0x01, registers[2].LowByte);
Assert.AreEqual(13, registers[3].Address);
Assert.AreEqual(0x24, registers[3].HighByte);
Assert.AreEqual(0xF8, registers[3].LowByte);
}
[TestMethod]
public void ShouldConvertInt64Reversed()
{
// Arrange
long l = 75000;
// Act
var registers = l.ToRegister(10, reverseRegisterOrder: true).ToList();
// Assert
Assert.IsNotNull(registers);
Assert.AreEqual(4, registers.Count);
Assert.AreEqual(13, registers[0].Address);
Assert.AreEqual(0x00, registers[0].HighByte);
Assert.AreEqual(0x00, registers[0].LowByte);
Assert.AreEqual(12, registers[1].Address);
Assert.AreEqual(0x00, registers[1].HighByte);
Assert.AreEqual(0x00, registers[1].LowByte);
Assert.AreEqual(11, registers[2].Address);
Assert.AreEqual(0x00, registers[2].HighByte);
Assert.AreEqual(0x01, registers[2].LowByte);
Assert.AreEqual(10, registers[3].Address);
Assert.AreEqual(0x24, registers[3].HighByte);
Assert.AreEqual(0xF8, registers[3].LowByte);
}
#endregion Value to Modbus
}
}

View File

@@ -0,0 +1,428 @@
namespace AMWD.Protocols.Modbus.Tests.Common.Extensions
{
[TestClass]
public class ModbusUnsignedExtensionsTest
{
#region Modbus to value
[TestMethod]
public void ShouldGetByteOnHoldingRegister()
{
// Arrange
var register = new HoldingRegister { Address = 1, HighByte = 0x02, LowByte = 0x10 };
// Act
byte b = register.GetByte();
// Assert
Assert.AreEqual(16, b);
}
[TestMethod]
public void ShouldGetByteOnInputRegister()
{
// Arrange
var register = new InputRegister { Address = 1, HighByte = 0x02, LowByte = 0x10 };
// Act
byte b = register.GetByte();
// Assert
Assert.AreEqual(16, b);
}
[TestMethod]
public void ShouldThrowNullForGetByte()
{
// Arrange
HoldingRegister register = null;
// Act + Assert
Assert.ThrowsExactly<ArgumentNullException>(() => register.GetByte());
}
[TestMethod]
public void ShouldThrowArgumentForGetByte()
{
// Arrange
var obj = new Coil();
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => obj.GetByte());
}
[TestMethod]
public void ShouldGetUInt16OnHoldingRegister()
{
// Arrange
var register = new HoldingRegister { Address = 1, HighByte = 0x02, LowByte = 0x10 };
// Act
ushort us = register.GetUInt16();
// Assert
Assert.AreEqual(528, us);
}
[TestMethod]
public void ShouldGetUInt16OnInputRegister()
{
// Arrange
var register = new InputRegister { Address = 1, HighByte = 0x02, LowByte = 0x10 };
// Act
ushort us = register.GetUInt16();
// Assert
Assert.AreEqual(528, us);
}
[TestMethod]
public void ShouldThrowNullForGetUInt16()
{
// Arrange
HoldingRegister register = null;
// Act + Assert
Assert.ThrowsExactly<ArgumentNullException>(() => register.GetUInt16());
}
[TestMethod]
public void ShouldThrowArgumentForGetUInt16()
{
// Arrange
var obj = new Coil();
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => obj.GetUInt16());
}
[TestMethod]
public void ShouldGetUInt32()
{
// Arrange
var registers = new HoldingRegister[]
{
new(),
new() { Address = 100, HighByte = 0x01, LowByte = 0x02 },
new() { Address = 101, HighByte = 0x03, LowByte = 0x04 }
};
// Act
uint ui = registers.GetUInt32(1);
// Assert
Assert.AreEqual(16909060u, ui);
}
[TestMethod]
public void ShouldGetUInt32ReversedRegisters()
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 101, HighByte = 0x01, LowByte = 0x02 },
new() { Address = 100, HighByte = 0x03, LowByte = 0x04 }
};
// Act
uint ui = registers.GetUInt32(0, reverseRegisterOrder: true);
// Assert
Assert.AreEqual(16909060u, ui);
}
[TestMethod]
public void ShouldThrowNullOnGetUInt32()
{
// Arrange
HoldingRegister[] registers = null;
// Act + Assert
Assert.ThrowsExactly<ArgumentNullException>(() => registers.GetUInt32(0));
}
[TestMethod]
public void ShouldThrowArgumentOnGetUInt32ForLength()
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 101, HighByte = 0x01, LowByte = 0x02 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => registers.GetUInt32(1));
}
[TestMethod]
[DataRow(1)]
[DataRow(-1)]
public void ShouldThrowArgumentOutOfRangeOnGetUInt32(int startIndex)
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 101, HighByte = 0x01, LowByte = 0x02 },
new() { Address = 100, HighByte = 0x03, LowByte = 0x04 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentOutOfRangeException>(() => registers.GetUInt32(startIndex));
}
[TestMethod]
public void ShouldThrowArgumentOnGetUInt32ForType()
{
// Arrange
var registers = new ModbusObject[]
{
new HoldingRegister { Address = 100, HighByte = 0x01, LowByte = 0x02 },
new InputRegister { Address = 101, HighByte = 0x03, LowByte = 0x04 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => registers.GetUInt32(0));
}
[TestMethod]
public void ShouldGetUInt64()
{
// Arrange
var registers = new HoldingRegister[]
{
new(),
new() { Address = 100, HighByte = 0x00, LowByte = 0x00 },
new() { Address = 101, HighByte = 0x00, LowByte = 0x00 },
new() { Address = 102, HighByte = 0x01, LowByte = 0x02 },
new() { Address = 103, HighByte = 0x03, LowByte = 0x04 }
};
// Act
ulong ul = registers.GetUInt64(1);
// Assert
Assert.AreEqual(16909060ul, ul);
}
[TestMethod]
public void ShouldGetUInt64ReversedRegisters()
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 103, HighByte = 0x00, LowByte = 0x00 },
new() { Address = 102, HighByte = 0x00, LowByte = 0x00 },
new() { Address = 101, HighByte = 0x01, LowByte = 0x02 },
new() { Address = 100, HighByte = 0x03, LowByte = 0x04 }
};
// Act
ulong ul = registers.GetUInt64(0, reverseRegisterOrder: true);
// Assert
Assert.AreEqual(16909060ul, ul);
}
[TestMethod]
public void ShouldThrowNullOnGetUInt64()
{
// Arrange
HoldingRegister[] registers = null;
// Act + Assert
Assert.ThrowsExactly<ArgumentNullException>(() => registers.GetUInt64(0));
}
[TestMethod]
public void ShouldThrowArgumentOnGetUInt64ForLength()
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 101, HighByte = 0x00, LowByte = 0x00 },
new() { Address = 102, HighByte = 0x01, LowByte = 0x02 },
new() { Address = 103, HighByte = 0x03, LowByte = 0x04 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => registers.GetUInt64(0));
}
[TestMethod]
[DataRow(1)]
[DataRow(-1)]
public void ShouldThrowArgumentOutOfRangeOnGetUInt64(int startIndex)
{
// Arrange
var registers = new HoldingRegister[]
{
new() { Address = 100, HighByte = 0x00, LowByte = 0x00 },
new() { Address = 101, HighByte = 0x00, LowByte = 0x00 },
new() { Address = 102, HighByte = 0x01, LowByte = 0x02 },
new() { Address = 103, HighByte = 0x03, LowByte = 0x04 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentOutOfRangeException>(() => registers.GetUInt64(startIndex));
}
[TestMethod]
public void ShouldThrowArgumentOnGetUInt64ForType()
{
// Arrange
var registers = new ModbusObject[]
{
new HoldingRegister { Address = 100, HighByte = 0x00, LowByte = 0x00 },
new InputRegister { Address = 101, HighByte = 0x00, LowByte = 0x00 },
new HoldingRegister { Address = 102, HighByte = 0x01, LowByte = 0x02 },
new InputRegister { Address = 103, HighByte = 0x03, LowByte = 0x04 }
};
// Act + Assert
Assert.ThrowsExactly<ArgumentException>(() => registers.GetUInt64(0));
}
#endregion Modbus to value
#region Value to Modbus
[TestMethod]
public void ShouldConvertByte()
{
// Arrange
byte b = 123;
// Act
var register = b.ToRegister(321);
// Assert
Assert.IsNotNull(register);
Assert.AreEqual(321, register.Address);
Assert.AreEqual(0, register.HighByte);
Assert.AreEqual(123, register.LowByte);
}
[TestMethod]
public void ShouldConvertUInt16()
{
// Arrange
ushort us = 1000;
// Act
var register = us.ToRegister(123);
// Assert
Assert.IsNotNull(register);
Assert.AreEqual(123, register.Address);
Assert.AreEqual(0x03, register.HighByte);
Assert.AreEqual(0xE8, register.LowByte);
}
[TestMethod]
public void ShouldConvertUInt32()
{
// Arrange
uint ui = 75000;
// Act
var registers = ui.ToRegister(5).ToList();
// Assert
Assert.IsNotNull(registers);
Assert.AreEqual(2, registers.Count);
Assert.AreEqual(5, registers[0].Address);
Assert.AreEqual(0x00, registers[0].HighByte);
Assert.AreEqual(0x01, registers[0].LowByte);
Assert.AreEqual(6, registers[1].Address);
Assert.AreEqual(0x24, registers[1].HighByte);
Assert.AreEqual(0xF8, registers[1].LowByte);
}
[TestMethod]
public void ShouldConvertUInt32Reversed()
{
// Arrange
uint ui = 75000;
// Act
var registers = ui.ToRegister(5, reverseRegisterOrder: true).ToList();
// Assert
Assert.IsNotNull(registers);
Assert.AreEqual(2, registers.Count);
Assert.AreEqual(6, registers[0].Address);
Assert.AreEqual(0x00, registers[0].HighByte);
Assert.AreEqual(0x01, registers[0].LowByte);
Assert.AreEqual(5, registers[1].Address);
Assert.AreEqual(0x24, registers[1].HighByte);
Assert.AreEqual(0xF8, registers[1].LowByte);
}
[TestMethod]
public void ShouldConvertUInt64()
{
// Arrange
ulong ul = 75000;
// Act
var registers = ul.ToRegister(10).ToList();
// Assert
Assert.IsNotNull(registers);
Assert.AreEqual(4, registers.Count);
Assert.AreEqual(10, registers[0].Address);
Assert.AreEqual(0x00, registers[0].HighByte);
Assert.AreEqual(0x00, registers[0].LowByte);
Assert.AreEqual(11, registers[1].Address);
Assert.AreEqual(0x00, registers[1].HighByte);
Assert.AreEqual(0x00, registers[1].LowByte);
Assert.AreEqual(12, registers[2].Address);
Assert.AreEqual(0x00, registers[2].HighByte);
Assert.AreEqual(0x01, registers[2].LowByte);
Assert.AreEqual(13, registers[3].Address);
Assert.AreEqual(0x24, registers[3].HighByte);
Assert.AreEqual(0xF8, registers[3].LowByte);
}
[TestMethod]
public void ShouldConvertUInt64Reversed()
{
// Arrange
ulong ul = 75000;
// Act
var registers = ul.ToRegister(10, reverseRegisterOrder: true).ToList();
// Assert
Assert.IsNotNull(registers);
Assert.AreEqual(4, registers.Count);
Assert.AreEqual(13, registers[0].Address);
Assert.AreEqual(0x00, registers[0].HighByte);
Assert.AreEqual(0x00, registers[0].LowByte);
Assert.AreEqual(12, registers[1].Address);
Assert.AreEqual(0x00, registers[1].HighByte);
Assert.AreEqual(0x00, registers[1].LowByte);
Assert.AreEqual(11, registers[2].Address);
Assert.AreEqual(0x00, registers[2].HighByte);
Assert.AreEqual(0x01, registers[2].LowByte);
Assert.AreEqual(10, registers[3].Address);
Assert.AreEqual(0x24, registers[3].HighByte);
Assert.AreEqual(0xF8, registers[3].LowByte);
}
#endregion Value to Modbus
}
}

View File

@@ -0,0 +1,108 @@
namespace AMWD.Protocols.Modbus.Tests.Common.Models
{
[TestClass]
public class CoilTest
{
[TestMethod]
public void ShouldSuccessfulCompare()
{
// Arrange
var coil1 = new Coil { Address = 123, Value = true };
var coil2 = new Coil { Address = 123, Value = true };
// Act
bool success = coil1.Equals(coil2);
// Assert
Assert.IsTrue(success);
}
[TestMethod]
public void ShouldFailOnInstanceComparing()
{
// Arrange
var coil1 = new Coil { Address = 123, Value = true };
var coil2 = new { Address = 123, HighByte = 0xFF };
// Act
bool success = coil1.Equals(coil2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnTypeComparing()
{
// Arrange
var coil1 = new Coil { Address = 123, Value = true };
var coil2 = new DiscreteInput { Address = 123, HighByte = 0xFF };
// Act
bool success = coil1.Equals(coil2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnAddressComparing()
{
// Arrange
var coil1 = new Coil { Address = 123, Value = true };
var coil2 = new Coil { Address = 321, HighByte = 0xFF };
// Act
bool success = coil1.Equals(coil2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnHighByteComparing()
{
// Arrange
var coil1 = new Coil { Address = 123, Value = true };
var coil2 = new Coil { Address = 123, HighByte = 0x00 };
// Act
bool success = coil1.Equals(coil2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnLowByteComparing()
{
// Arrange
var coil1 = new Coil { Address = 123, Value = true };
var coil2 = new Coil { Address = 123, HighByte = 0xFF, LowByte = 0xFF };
// Act
bool success = coil1.Equals(coil2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
[DataRow(0xFF)]
[DataRow(0x00)]
public void ShouldPrintPrettyString(int highByte)
{
// Arrange
var coil = new Coil { Address = 123, HighByte = (byte)highByte, LowByte = 0x00 };
// Act
string str = coil.ToString();
// Assert
if (highByte > 0)
Assert.AreEqual("Coil #123 | ON", str);
else
Assert.AreEqual("Coil #123 | OFF", str);
}
}
}

View File

@@ -0,0 +1,108 @@
namespace AMWD.Protocols.Modbus.Tests.Common.Models
{
[TestClass]
public class DiscreteInputTest
{
[TestMethod]
public void ShouldSuccessfulCompare()
{
// Arrange
var input1 = new DiscreteInput { Address = 123, HighByte = 0xFF, LowByte = 0x00 };
var input2 = new DiscreteInput { Address = 123, HighByte = 0xFF, LowByte = 0x00 };
// Act
bool success = input1.Equals(input2);
// Assert
Assert.IsTrue(success);
}
[TestMethod]
public void ShouldFailOnInstanceComparing()
{
// Arrange
var coil1 = new Coil { Address = 123, Value = true };
var coil2 = new { Address = 123, HighByte = 0xFF };
// Act
bool success = coil1.Equals(coil2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnTypeComparing()
{
// Arrange
var input1 = new DiscreteInput { Address = 123, HighByte = 0xFF, LowByte = 0x00 };
var input2 = new Coil { Address = 123, HighByte = 0xFF, LowByte = 0x00 };
// Act
bool success = input1.Equals(input2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnAddressComparing()
{
// Arrange
var input1 = new DiscreteInput { Address = 123, HighByte = 0xFF, LowByte = 0x00 };
var input2 = new DiscreteInput { Address = 321, HighByte = 0xFF, LowByte = 0x00 };
// Act
bool success = input1.Equals(input2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnHighByteComparing()
{
// Arrange
var input1 = new DiscreteInput { Address = 123, HighByte = 0xFF, LowByte = 0x00 };
var input2 = new DiscreteInput { Address = 123, HighByte = 0x00, LowByte = 0x00 };
// Act
bool success = input1.Equals(input2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnLowByteComparing()
{
// Arrange
var input1 = new DiscreteInput { Address = 123, HighByte = 0xFF, LowByte = 0x00 };
var input2 = new DiscreteInput { Address = 123, HighByte = 0xFF, LowByte = 0xFF };
// Act
bool success = input1.Equals(input2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
[DataRow(0xFF)]
[DataRow(0x00)]
public void ShouldPrintPrettyString(int highByte)
{
// Arrange
var input = new DiscreteInput { Address = 123, HighByte = (byte)highByte, LowByte = 0x00 };
// Act
string str = input.ToString();
// Assert
if (highByte > 0)
Assert.AreEqual("Discrete Input #123 | ON", str);
else
Assert.AreEqual("Discrete Input #123 | OFF", str);
}
}
}

View File

@@ -0,0 +1,117 @@
namespace AMWD.Protocols.Modbus.Tests.Common.Models
{
[TestClass]
public class HoldingRegisterTests
{
[TestMethod]
public void ShouldSuccessfulCompare()
{
// Arrange
var register1 = new HoldingRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
var register2 = new HoldingRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
// Act
bool success = register1.Equals(register2);
// Assert
Assert.IsTrue(success);
}
[TestMethod]
public void ShouldFailOnInstanceComparing()
{
// Arrange
var register1 = new HoldingRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
var register2 = new { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
// Act
bool success = register1.Equals(register2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnTypeComparing()
{
// Arrange
var register1 = new HoldingRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
var register2 = new InputRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
// Act
bool success = register1.Equals(register2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnAddressComparing()
{
// Arrange
var register1 = new HoldingRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
var register2 = new HoldingRegister { Address = 321, HighByte = 0xBE, LowByte = 0xEF };
// Act
bool success = register1.Equals(register2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnHighByteComparing()
{
// Arrange
var register1 = new HoldingRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
var register2 = new HoldingRegister { Address = 123, HighByte = 0xBD, LowByte = 0xEF };
// Act
bool success = register1.Equals(register2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnLowByteComparing()
{
// Arrange
var register1 = new HoldingRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
var register2 = new HoldingRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEE };
// Act
bool success = register1.Equals(register2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldPrintPrettyString()
{
// Arrange
var register = new HoldingRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
// Act
string str = register.ToString();
// Assert
Assert.AreEqual("Holding Register #123 | 48879 | HI: BE, LO: EF", str);
}
[TestMethod]
public void ShouldSetByValue()
{
// Arrange
var register = new HoldingRegister { Address = 123 };
// Act
register.Value = 48879;
// Assert
Assert.AreEqual(0xBE, register.HighByte);
Assert.AreEqual(0xEF, register.LowByte);
}
}
}

View File

@@ -0,0 +1,103 @@
namespace AMWD.Protocols.Modbus.Tests.Common.Models
{
[TestClass]
public class InputRegisterTests
{
[TestMethod]
public void ShouldSuccessfulCompare()
{
// Arrange
var register1 = new InputRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
var register2 = new InputRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
// Act
bool success = register1.Equals(register2);
// Assert
Assert.IsTrue(success);
}
[TestMethod]
public void ShouldFailOnInstanceComparing()
{
// Arrange
var register1 = new InputRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
var register2 = new { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
// Act
bool success = register1.Equals(register2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnTypeComparing()
{
// Arrange
var register1 = new InputRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
var register2 = new HoldingRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
// Act
bool success = register1.Equals(register2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnAddressComparing()
{
// Arrange
var register1 = new InputRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
var register2 = new InputRegister { Address = 321, HighByte = 0xBE, LowByte = 0xEF };
// Act
bool success = register1.Equals(register2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnHighByteComparing()
{
// Arrange
var register1 = new InputRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
var register2 = new InputRegister { Address = 123, HighByte = 0xBD, LowByte = 0xEF };
// Act
bool success = register1.Equals(register2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldFailOnLowByteComparing()
{
// Arrange
var register1 = new InputRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
var register2 = new InputRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEE };
// Act
bool success = register1.Equals(register2);
// Assert
Assert.IsFalse(success);
}
[TestMethod]
public void ShouldPrintPrettyString()
{
// Arrange
var register = new InputRegister { Address = 123, HighByte = 0xBE, LowByte = 0xEF };
// Act
string str = register.ToString();
// Assert
Assert.AreEqual("Input Register #123 | 48879 | HI: BE, LO: EF", str);
}
}
}

View File

@@ -0,0 +1,287 @@
using AMWD.Protocols.Modbus.Common.Models;
using System.Reflection;
namespace AMWD.Protocols.Modbus.Tests.Common.Models
{
[TestClass]
public class ModbusDeviceTest
{
[TestMethod]
public void ShouldAllowMultipleDispose()
{
// Arrange
var device = new ModbusDevice(123);
// Act
device.Dispose();
device.Dispose();
// Assert - no exception
}
[TestMethod]
public void ShouldAssertDisposed()
{
// Arrange
var device = new ModbusDevice(123);
device.Dispose();
// Act
try
{
device.GetCoil(111);
Assert.Fail();
}
catch (ObjectDisposedException)
{ }
try
{
device.SetCoil(new Coil { Address = 222 });
Assert.Fail();
}
catch (ObjectDisposedException)
{ }
try
{
device.GetDiscreteInput(111);
Assert.Fail();
}
catch (ObjectDisposedException)
{ }
try
{
device.SetDiscreteInput(new DiscreteInput { Address = 222 });
Assert.Fail();
}
catch (ObjectDisposedException)
{ }
try
{
device.GetHoldingRegister(111);
Assert.Fail();
}
catch (ObjectDisposedException)
{ }
try
{
device.SetHoldingRegister(new HoldingRegister { Address = 222 });
Assert.Fail();
}
catch (ObjectDisposedException)
{ }
try
{
device.GetInputRegister(111);
Assert.Fail();
}
catch (ObjectDisposedException)
{ }
try
{
device.SetInputRegister(new InputRegister { Address = 222 });
Assert.Fail();
}
catch (ObjectDisposedException)
{ }
}
[TestMethod]
public void ShouldGetCoil()
{
// Arrange
var device = new ModbusDevice(123);
((HashSet<ushort>)device.GetType()
.GetField("_coils", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(device))
.Add(333);
// Act
var coilFalse = device.GetCoil(111);
var coilTrue = device.GetCoil(333);
// Assert
Assert.AreEqual(111, coilFalse.Address);
Assert.IsFalse(coilFalse.Value);
Assert.AreEqual(333, coilTrue.Address);
Assert.IsTrue(coilTrue.Value);
}
[TestMethod]
public void ShouldSetCoil()
{
// Arrange
var device = new ModbusDevice(123);
((HashSet<ushort>)device.GetType()
.GetField("_coils", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(device))
.Add(333);
// Act
device.SetCoil(new Coil { Address = 111, Value = true });
device.SetCoil(new Coil { Address = 333, Value = false });
// Assert
ushort[] coils = ((HashSet<ushort>)device.GetType()
.GetField("_coils", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(device)).ToArray();
Assert.AreEqual(1, coils.Length);
Assert.AreEqual(111, coils.First());
}
[TestMethod]
public void ShouldGetDiscreteInput()
{
// Arrange
var device = new ModbusDevice(123);
((HashSet<ushort>)device.GetType()
.GetField("_discreteInputs", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(device))
.Add(333);
// Act
var inputFalse = device.GetDiscreteInput(111);
var inputTrue = device.GetDiscreteInput(333);
// Assert
Assert.AreEqual(111, inputFalse.Address);
Assert.IsFalse(inputFalse.Value);
Assert.AreEqual(333, inputTrue.Address);
Assert.IsTrue(inputTrue.Value);
}
[TestMethod]
public void ShouldSetDiscreteInput()
{
// Arrange
var device = new ModbusDevice(123);
((HashSet<ushort>)device.GetType()
.GetField("_discreteInputs", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(device))
.Add(333);
// Act
device.SetDiscreteInput(new DiscreteInput { Address = 111, HighByte = 0xFF });
device.SetDiscreteInput(new DiscreteInput { Address = 333, HighByte = 0x00 });
// Assert
ushort[] discreteInputs = ((HashSet<ushort>)device.GetType()
.GetField("_discreteInputs", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(device)).ToArray();
Assert.AreEqual(1, discreteInputs.Length);
Assert.AreEqual(111, discreteInputs.First());
}
[TestMethod]
public void ShouldGetHoldingRegister()
{
// Arrange
var device = new ModbusDevice(123);
((Dictionary<ushort, ushort>)device.GetType()
.GetField("_holdingRegisters", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(device))
.Add(333, 42);
// Act
var zeroRegister = device.GetHoldingRegister(111);
var valueRegister = device.GetHoldingRegister(333);
// Assert
Assert.AreEqual(111, zeroRegister.Address);
Assert.AreEqual(0, zeroRegister.Value);
Assert.AreEqual(0x00, zeroRegister.HighByte);
Assert.AreEqual(0x00, zeroRegister.LowByte);
Assert.AreEqual(333, valueRegister.Address);
Assert.AreEqual(42, valueRegister.Value);
Assert.AreEqual(0x00, valueRegister.HighByte);
Assert.AreEqual(0x2A, valueRegister.LowByte);
}
[TestMethod]
public void ShouldSetHoldingRegister()
{
// Arrange
var device = new ModbusDevice(123);
((Dictionary<ushort, ushort>)device.GetType()
.GetField("_holdingRegisters", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(device))
.Add(333, 42);
// Act
device.SetHoldingRegister(new HoldingRegister { Address = 333, Value = 0 });
device.SetHoldingRegister(new HoldingRegister { Address = 111, Value = 42 });
// Assert
var registers = ((Dictionary<ushort, ushort>)device.GetType()
.GetField("_holdingRegisters", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(device))
.ToDictionary(x => x.Key, x => x.Value);
Assert.AreEqual(1, registers.Count);
Assert.AreEqual(111, registers.First().Key);
Assert.AreEqual(42, registers.First().Value);
}
[TestMethod]
public void ShouldGetInputRegister()
{
// Arrange
var device = new ModbusDevice(123);
((Dictionary<ushort, ushort>)device.GetType()
.GetField("_inputRegisters", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(device))
.Add(333, 42);
// Act
var zeroRegister = device.GetInputRegister(111);
var valueRegister = device.GetInputRegister(333);
// Assert
Assert.AreEqual(111, zeroRegister.Address);
Assert.AreEqual(0, zeroRegister.Value);
Assert.AreEqual(0x00, zeroRegister.HighByte);
Assert.AreEqual(0x00, zeroRegister.LowByte);
Assert.AreEqual(333, valueRegister.Address);
Assert.AreEqual(42, valueRegister.Value);
Assert.AreEqual(0x00, valueRegister.HighByte);
Assert.AreEqual(0x2A, valueRegister.LowByte);
}
[TestMethod]
public void ShouldSetInputRegister()
{
// Arrange
var device = new ModbusDevice(123);
((Dictionary<ushort, ushort>)device.GetType()
.GetField("_inputRegisters", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(device))
.Add(333, 42);
// Act
device.SetInputRegister(new InputRegister { Address = 333, LowByte = 0 });
device.SetInputRegister(new InputRegister { Address = 111, LowByte = 42 });
// Assert
var registers = ((Dictionary<ushort, ushort>)device.GetType()
.GetField("_inputRegisters", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(device))
.ToDictionary(x => x.Key, x => x.Value);
Assert.AreEqual(1, registers.Count);
Assert.AreEqual(111, registers.First().Key);
Assert.AreEqual(42, registers.First().Value);
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff