/nmodbus/NModbus/src/Modbus.UnitTests/IO/ModbusTransportFixture.cs
https://github.com/offlinehacker/Bastet-GUI · C# · 328 lines · 242 code · 69 blank · 17 comment · 0 complexity · d4bb31baf5d2c452a2f78b4534fb6f4f MD5 · raw file
- using System;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using MbUnit.Framework;
- using Modbus.Data;
- using Modbus.IO;
- using Modbus.Message;
- using Modbus.Utility;
- using Rhino.Mocks;
- using Unme.Common;
- using Unme.MbUnit.Framework.Extensions;
- namespace Modbus.UnitTests.IO
- {
- delegate ReadCoilsInputsResponse ThrowExceptionDelegate();
- [TestFixture]
- public class ModbusTransportFixture
- {
- [Test]
- public void UnicastMessage()
- {
- MockRepository mocks = new MockRepository();
- ModbusTransport transport = mocks.PartialMock<ModbusTransport>();
- transport.Write(null);
- LastCall.IgnoreArguments();
- // read 4 coils from slave id 2
- Expect.Call(transport.ReadResponse<ReadCoilsInputsResponse>())
- .Return(new ReadCoilsInputsResponse(Modbus.ReadCoils, 2, 1, new DiscreteCollection(true, false, true, false, false, false, false, false)));
- transport.OnValidateResponse(null, null);
- LastCall.IgnoreArguments();
- mocks.ReplayAll();
- ReadCoilsInputsRequest request = new ReadCoilsInputsRequest(Modbus.ReadCoils, 2, 3, 4);
- ReadCoilsInputsResponse expectedResponse = new ReadCoilsInputsResponse(Modbus.ReadCoils, 2, 1, new DiscreteCollection(true, false, true, false, false, false, false, false));
- ReadCoilsInputsResponse response = transport.UnicastMessage<ReadCoilsInputsResponse>(request);
- Assert.AreEqual(expectedResponse.MessageFrame, response.MessageFrame);
- mocks.VerifyAll();
- }
- [Test, ExpectedException(typeof(IOException))]
- public void UnicastMessage_WrongResponseFunctionCode()
- {
- MockRepository mocks = new MockRepository();
- ModbusTransport transport = mocks.PartialMock<ModbusTransport>();
- transport.Write(null);
- LastCall.IgnoreArguments().Repeat.Times(Modbus.DefaultRetries + 1);
- // read 4 coils from slave id 2
- Expect.Call(transport.ReadResponse<ReadCoilsInputsResponse>())
- .Return(new ReadCoilsInputsResponse(Modbus.ReadCoils, 2, 0, new DiscreteCollection()))
- .Repeat.Times(Modbus.DefaultRetries + 1);
- mocks.ReplayAll();
- ReadCoilsInputsRequest request = new ReadCoilsInputsRequest(Modbus.ReadInputs, 2, 3, 4);
- transport.UnicastMessage<ReadCoilsInputsResponse>(request);
- mocks.VerifyAll();
- }
- [Test, ExpectedException(typeof(SlaveException))]
- public void UnicastMessage_ErrorSlaveException()
- {
- MockRepository mocks = new MockRepository();
- ModbusTransport transport = mocks.PartialMock<ModbusTransport>();
- transport.Write(null);
- LastCall.IgnoreArguments().Repeat.Times(Modbus.DefaultRetries + 1);
- Expect.Call(transport.ReadResponse<ReadCoilsInputsResponse>())
- .Do((ThrowExceptionDelegate) delegate { throw new SlaveException(); });
- mocks.ReplayAll();
- ReadCoilsInputsRequest request = new ReadCoilsInputsRequest(Modbus.ReadInputs, 2, 3, 4);
- transport.UnicastMessage<ReadCoilsInputsResponse>(request);
- mocks.VerifyAll();
- }
- /// <summary>
- /// We should reread the response w/o retransmitting the request.
- /// </summary>
- [Test]
- public void UnicastMessage_AcknowlegeSlaveException()
- {
- MockRepository mocks = new MockRepository();
- ModbusTransport transport = mocks.PartialMock<ModbusTransport>();
- // set the wait to retry property to a small value so the test completes quickly
- transport.WaitToRetryMilliseconds = 5;
- transport.Write(null);
- LastCall.IgnoreArguments();
- // return a slave exception a greater number of times than number of retries to make sure we aren't just retrying
- Expect.Call(transport.ReadResponse<ReadHoldingInputRegistersResponse>())
- .Return(new SlaveExceptionResponse(1, Modbus.ReadHoldingRegisters + Modbus.ExceptionOffset, Modbus.Acknowledge))
- .Repeat.Times(transport.Retries + 1);
- Expect.Call(transport.ReadResponse<ReadHoldingInputRegistersResponse>())
- .Return(new ReadHoldingInputRegistersResponse(Modbus.ReadHoldingRegisters, 1, new RegisterCollection(1)));
- transport.OnValidateResponse(null, null);
- LastCall.IgnoreArguments();
- mocks.ReplayAll();
- ReadHoldingInputRegistersRequest request = new ReadHoldingInputRegistersRequest(Modbus.ReadHoldingRegisters, 1, 1, 1);
- ReadHoldingInputRegistersResponse expectedResponse = new ReadHoldingInputRegistersResponse(Modbus.ReadHoldingRegisters, 1, new RegisterCollection(1));
- ReadHoldingInputRegistersResponse response = transport.UnicastMessage<ReadHoldingInputRegistersResponse>(request);
- Assert.AreEqual(expectedResponse.MessageFrame, response.MessageFrame);
- mocks.VerifyAll();
- }
- /// <summary>
- /// We should retransmit the request.
- /// </summary>
- [Test]
- public void UnicastMessage_SlaveDeviceBusySlaveException()
- {
- MockRepository mocks = new MockRepository();
- ModbusTransport transport = mocks.PartialMock<ModbusTransport>();
- // set the wait to retry property to a small value so the test completes quickly
- transport.WaitToRetryMilliseconds = 5;
- transport.Write(null);
- LastCall.IgnoreArguments()
- .Repeat.Times(2);
- // return a slave exception a greater number of times than number of retries to make sure we aren't just retrying
- Expect.Call(transport.ReadResponse<ReadHoldingInputRegistersResponse>())
- .Return(new SlaveExceptionResponse(1, Modbus.ReadHoldingRegisters + Modbus.ExceptionOffset, Modbus.SlaveDeviceBusy));
- Expect.Call(transport.ReadResponse<ReadHoldingInputRegistersResponse>())
- .Return(new ReadHoldingInputRegistersResponse(Modbus.ReadHoldingRegisters, 1, new RegisterCollection(1)));
- transport.OnValidateResponse(null, null);
- LastCall.IgnoreArguments();
- mocks.ReplayAll();
- ReadHoldingInputRegistersRequest request = new ReadHoldingInputRegistersRequest(Modbus.ReadHoldingRegisters, 1, 1, 1);
- ReadHoldingInputRegistersResponse expectedResponse = new ReadHoldingInputRegistersResponse(Modbus.ReadHoldingRegisters, 1, new RegisterCollection(1));
- ReadHoldingInputRegistersResponse response = transport.UnicastMessage<ReadHoldingInputRegistersResponse>(request);
- Assert.AreEqual(expectedResponse.MessageFrame, response.MessageFrame);
- mocks.VerifyAll();
- }
- /// <summary>
- /// We should retransmit the request.
- /// </summary>
- [Test]
- public void UnicastMessage_SlaveDeviceBusySlaveExceptionDoesNotFailAfterExceedingRetries()
- {
- MockRepository mocks = new MockRepository();
- ModbusTransport transport = mocks.PartialMock<ModbusTransport>();
- // set the wait to retry property to a small value so the test completes quickly
- transport.WaitToRetryMilliseconds = 5;
- transport.Write(null);
- LastCall.IgnoreArguments()
- .Repeat.Times(transport.Retries + 1);
- // return a slave exception a greater number of times than number of retries to make sure we aren't just retrying
- Expect.Call(transport.ReadResponse<ReadHoldingInputRegistersResponse>())
- .Return(new SlaveExceptionResponse(1, Modbus.ReadHoldingRegisters + Modbus.ExceptionOffset, Modbus.SlaveDeviceBusy))
- .Repeat.Times(transport.Retries);
- Expect.Call(transport.ReadResponse<ReadHoldingInputRegistersResponse>())
- .Return(new ReadHoldingInputRegistersResponse(Modbus.ReadHoldingRegisters, 1, new RegisterCollection(1)));
- transport.OnValidateResponse(null, null);
- LastCall.IgnoreArguments();
- mocks.ReplayAll();
- ReadHoldingInputRegistersRequest request = new ReadHoldingInputRegistersRequest(Modbus.ReadHoldingRegisters, 1, 1, 1);
- ReadHoldingInputRegistersResponse expectedResponse = new ReadHoldingInputRegistersResponse(Modbus.ReadHoldingRegisters, 1, new RegisterCollection(1));
- ReadHoldingInputRegistersResponse response = transport.UnicastMessage<ReadHoldingInputRegistersResponse>(request);
- Assert.AreEqual(expectedResponse.MessageFrame, response.MessageFrame);
- mocks.VerifyAll();
- }
- [RowTest,
- Row(typeof(TimeoutException)),
- Row(typeof(IOException)),
- Row(typeof(NotImplementedException)),
- Row(typeof(FormatException))]
- public void UnicastMessage_SingleFailingException(Type exceptionType)
- {
- MockRepository mocks = new MockRepository();
- ModbusTransport transport = mocks.PartialMock<ModbusTransport>();
- transport.Retries = 1;
- transport.Write(null);
- LastCall.IgnoreArguments().Repeat.Times(2);
- Expect.Call(transport.ReadResponse<ReadCoilsInputsResponse>())
- .Do((ThrowExceptionDelegate) delegate { throw (Exception) Activator.CreateInstance(exceptionType); });
-
- Expect.Call(transport.ReadResponse<ReadCoilsInputsResponse>())
- .Return(new ReadCoilsInputsResponse(Modbus.ReadCoils, 2, 1, new DiscreteCollection(true, false, true, false, false, false, false, false)));
- transport.OnValidateResponse(null, null);
- LastCall.IgnoreArguments();
- mocks.ReplayAll();
- ReadCoilsInputsRequest request = new ReadCoilsInputsRequest(Modbus.ReadCoils, 2, 3, 4);
- transport.UnicastMessage<ReadCoilsInputsResponse>(request);
- mocks.VerifyAll();
- }
- [RowTest,
- Row(typeof(TimeoutException)),
- Row(typeof(IOException)),
- Row(typeof(NotImplementedException)),
- Row(typeof(FormatException))]
- public void UnicastMessage_TooManyFailingExceptions(Type exceptionType)
- {
- MockRepository mocks = new MockRepository();
- ModbusTransport transport = mocks.PartialMock<ModbusTransport>();
-
- transport.Write(null);
- LastCall.IgnoreArguments().Repeat.Times(transport.Retries + 1);
-
- Expect.Call(transport.ReadResponse<ReadCoilsInputsResponse>())
- .Do((ThrowExceptionDelegate) delegate { throw (Exception) Activator.CreateInstance(exceptionType); })
- .Repeat.Times(transport.Retries + 1);
- mocks.ReplayAll();
- ReadCoilsInputsRequest request = new ReadCoilsInputsRequest(Modbus.ReadCoils, 2, 3, 4);
- Action action = () => transport.UnicastMessage<ReadCoilsInputsResponse>(request);
- typeof(AssertUtility).GetMethod("Throws", BindingFlags.Public | BindingFlags.Static).
- MakeGenericMethod(new Type[] { exceptionType }).
- Invoke(transport, new object[] { action });
- mocks.VerifyAll();
- }
- [Test, ExpectedException(typeof(TimeoutException))]
- public void UnicastMessage_TimeoutException()
- {
- MockRepository mocks = new MockRepository();
- ModbusTransport transport = mocks.PartialMock<ModbusTransport>();
- transport.Write(null);
- LastCall.IgnoreArguments().Repeat.Times(Modbus.DefaultRetries + 1);
- Expect.Call(transport.ReadResponse<ReadCoilsInputsResponse>())
- .Do((ThrowExceptionDelegate) delegate { throw new TimeoutException(); })
- .Repeat.Times(Modbus.DefaultRetries + 1);
- mocks.ReplayAll();
- ReadCoilsInputsRequest request = new ReadCoilsInputsRequest(Modbus.ReadInputs, 2, 3, 4);
- transport.UnicastMessage<ReadCoilsInputsResponse>(request);
- mocks.VerifyAll();
- }
- [Test, ExpectedException(typeof(TimeoutException))]
- public void UnicastMessage_Retries()
- {
- MockRepository mocks = new MockRepository();
- ModbusTransport transport = mocks.PartialMock<ModbusTransport>();
- transport.Retries = 5;
- transport.Write(null);
- LastCall.IgnoreArguments().Repeat.Times(transport.Retries + 1);
- Expect.Call(transport.ReadResponse<ReadCoilsInputsResponse>())
- .Do((ThrowExceptionDelegate) delegate { throw new TimeoutException(); })
- .Repeat.Times(transport.Retries + 1);
- mocks.ReplayAll();
- ReadCoilsInputsRequest request = new ReadCoilsInputsRequest(Modbus.ReadInputs, 2, 3, 4);
- transport.UnicastMessage<ReadCoilsInputsResponse>(request);
- mocks.VerifyAll();
- }
- [Test]
- public void CreateResponse_SlaveException()
- {
- ModbusTransport transport = new ModbusAsciiTransport(MockRepository.GenerateStub<IStreamResource>());
- byte[] frame = { 2, 129, 2 };
- IModbusMessage message = transport.CreateResponse<ReadCoilsInputsResponse>(frame.Concat(SequenceUtility.ToSequence(ModbusUtility.CalculateLrc(frame))).ToArray());
- Assert.IsTrue(message is SlaveExceptionResponse);
- }
- [Test, ExpectedException(typeof(IOException))]
- public void ValidateResponse_MismatchingFunctionCodes()
- {
- MockRepository mocks = new MockRepository();
- ModbusTransport transport = mocks.PartialMock<ModbusTransport>();
- IModbusMessage request = new ReadCoilsInputsRequest(Modbus.ReadCoils, 1, 1, 1);
- IModbusMessage response = new ReadHoldingInputRegistersResponse(Modbus.ReadHoldingRegisters, 1, new RegisterCollection());
- mocks.ReplayAll();
- transport.ValidateResponse(request, response);
- mocks.VerifyAll();
- }
- [Test]
- public void ValidateResponse()
- {
- MockRepository mocks = new MockRepository();
- ModbusTransport transport = mocks.PartialMock<ModbusTransport>();
- IModbusMessage request = new ReadCoilsInputsRequest(Modbus.ReadCoils, 1, 1, 1);
- IModbusMessage response = new ReadCoilsInputsResponse(Modbus.ReadCoils, 1, 1, null);
- transport.OnValidateResponse(null, null);
- LastCall.IgnoreArguments();
- mocks.ReplayAll();
- transport.ValidateResponse(request, response);
- mocks.VerifyAll();
- }
- }
- }